From 188c3a646ad5404da1485aeffaff80765432f77a Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 17 Mar 2023 10:19:17 +0800 Subject: [PATCH] scsi: libsas: Add sas_ata_device_link_abort() mainline inclusion from mainline-v6.2-rc1 commit 44112922674b94a7d699dfff6307fc830018df7c category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6NPLN CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=44112922674b94a7d699dfff6307fc830018df7c ---------------------------------------------------------------------- Similar to how AHCI handles NCQ errors in ahci_error_intr() -> ata_port_abort() -> ata_do_link_abort(), add an NCQ error handler for LLDDs to call to initiate a link abort. This will mark all outstanding QCs as failed and kick-off EH. Note: A "force reset" argument is added for drivers which require the ATA error handling to always reset the device. A driver may require this feature for when SATA device per-SCSI cmnd resources are only released during reset for ATA EH. As such, we need an option to force reset to be done, regardless of what any EH autopsy decides. The SATA device FIS fields are set to indicate a device error from ata_eh_analyze_tf(). Suggested-by: Damien Le Moal Suggested-by: Niklas Cassel Signed-off-by: John Garry Link: https://lore.kernel.org/r/1665998435-199946-2-git-send-email-john.garry@huawei.com Tested-by: Damien Le Moal Tested-by: Niklas Cassel # pm80xx Reviewed-by: Jason Yan Signed-off-by: Martin K. Petersen Signed-off-by: xiabing --- drivers/scsi/libsas/sas_ata.c | 15 +++++++++++++++ include/scsi/sas_ata.h | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index d54f91636ad1..434083c2c2f7 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -875,3 +875,18 @@ void sas_ata_wait_eh(struct domain_device *dev) ap = dev->sata_dev.ap; 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); diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h index e0d2d4915257..68c342e55f6f 100644 --- a/include/scsi/sas_ata.h +++ b/include/scsi/sas_ata.h @@ -33,6 +33,7 @@ void sas_probe_sata(struct asd_sas_port *port); void sas_suspend_sata(struct asd_sas_port *port); void sas_resume_sata(struct asd_sas_port *port); void sas_ata_end_eh(struct ata_port *ap); +void sas_ata_device_link_abort(struct domain_device *dev, bool force_reset); int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline); #else @@ -87,6 +88,11 @@ static inline void sas_ata_end_eh(struct ata_port *ap) { } +static inline void sas_ata_device_link_abort(struct domain_device *dev, + bool force_reset) +{ +} + static inline int sas_ata_wait_after_reset(struct domain_device *dev, unsigned long deadline) { -- GitLab