diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-12-04 01:06:24 -0800 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 14:24:02 -0600 |
commit | 50824d6c5657ce340e3911171865a8d99fdd8eba (patch) | |
tree | fcc9a9250cf596f9d12e3b92d9fa67cb8a77f09c | |
parent | 89d3cf6ac3cdc4f15a82709f8c78ed169a98be5b (diff) | |
download | linux-50824d6c5657ce340e3911171865a8d99fdd8eba.tar.bz2 |
[SCSI] libsas: async ata-eh
Once sas_ata_hard_reset() starts honoring the 'deadline' parameter a
pathological configuration could take 25 seconds per ata device
(serialized) to recover. Run per-port recoveries in parallel.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 03930a04a679..4beca66728b4 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -23,6 +23,7 @@ #include <linux/scatterlist.h> #include <linux/slab.h> +#include <linux/async.h> #include <scsi/sas_ata.h> #include "sas_internal.h" @@ -605,10 +606,21 @@ int sas_discover_sata(struct domain_device *dev) return 0; } +static void async_sas_ata_eh(void *data, async_cookie_t cookie) +{ + struct domain_device *dev = data; + struct ata_port *ap = dev->sata_dev.ap; + struct sas_ha_struct *ha = dev->port->ha; + + ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler"); + ata_scsi_port_error_handler(ha->core.shost, ap); +} + void sas_ata_strategy_handler(struct Scsi_Host *shost) { struct scsi_device *sdev; struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); + LIST_HEAD(async); /* it's ok to defer revalidation events during ata eh, these * disks are in one of three states: @@ -622,14 +634,13 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost) shost_for_each_device(sdev, shost) { struct domain_device *ddev = sdev_to_domain_dev(sdev); - struct ata_port *ap = ddev->sata_dev.ap; if (!dev_is_sata(ddev)) continue; - ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler"); - ata_scsi_port_error_handler(shost, ap); + async_schedule_domain(async_sas_ata_eh, ddev, &async); } + async_synchronize_full_domain(&async); sas_enable_revalidation(sas_ha); } |