qc->flags |= ATA_QCFLAG_FAILED;
}
- dev->sata_dev.fis[3] = 0x04; /* status err */
- dev->sata_dev.fis[2] = ATA_ERR;
+ dev->sata_dev.fis[2] = ATA_ERR | ATA_DRDY; /* tf status */
+ dev->sata_dev.fis[3] = ATA_ABORTED; /* tf error */
}
}
return 1;
}
+int smp_ata_check_ready_type(struct ata_link *link)
+{
+ struct domain_device *dev = link->ap->private_data;
+ struct sas_phy *phy = sas_get_local_phy(dev);
+ struct domain_device *ex_dev = dev->parent;
+ enum sas_device_type type = SAS_PHY_UNUSED;
+ u8 sas_addr[SAS_ADDR_SIZE];
+ int res;
+
+ res = sas_get_phy_attached_dev(ex_dev, phy->number, sas_addr, &type);
+ sas_put_local_phy(phy);
+ if (res)
+ return res;
+
+ switch (type) {
+ case SAS_SATA_PENDING:
+ return 0;
+ case SAS_END_DEVICE:
+ return 1;
+ default:
+ return -ENODEV;
+ }
+}
+EXPORT_SYMBOL_GPL(smp_ata_check_ready_type);
+
static int smp_ata_check_ready(struct ata_link *link)
{
int res;
return r;
}
-int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline)
+static int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline)
{
struct sata_device *sata_dev = &dev->sata_dev;
int (*check_ready)(struct ata_link *link);
return ret;
}
-EXPORT_SYMBOL_GPL(sas_ata_wait_after_reset);
static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
ata_port_wait_eh(ap);
}
+void sas_ata_device_link_abort(struct domain_device *device, bool force_reset)
+{
+ struct ata_port *ap = device->sata_dev.ap;
+ struct ata_link *link = &ap->link;
+
+ device->sata_dev.fis[2] = ATA_ERR | ATA_DRDY; /* tf status */
+ device->sata_dev.fis[3] = ATA_ABORTED; /* tf error */
+
+ link->eh_info.err_mask |= AC_ERR_DEV;
+ if (force_reset)
+ link->eh_info.action |= ATA_EH_RESET;
+ ata_link_abort(link);
+}
+EXPORT_SYMBOL_GPL(sas_ata_device_link_abort);
+
int sas_execute_ata_cmd(struct domain_device *device, u8 *fis, int force_phy_id)
{
struct sas_tmf_task tmf_task = {};