diff options
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 5 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_discover.c | 5 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 3 |
3 files changed, 10 insertions, 3 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 37a9e73870d4..26a943eb153a 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -661,8 +661,13 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie) struct ata_port *ap = dev->sata_dev.ap; struct sas_ha_struct *ha = dev->port->ha; + /* hold a reference over eh since we may be racing with final + * remove once all commands are completed + */ + kref_get(&dev->kref); ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler"); ata_scsi_port_error_handler(ha->core.shost, ap); + sas_put_device(dev); } void sas_ata_strategy_handler(struct Scsi_Host *shost) diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index b91866a8233b..4be5ddad7be7 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -242,6 +242,11 @@ void sas_free_device(struct kref *kref) if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) kfree(dev->ex_dev.ex_phy); + if (dev_is_sata(dev) && dev->sata_dev.ap) { + ata_sas_port_destroy(dev->sata_dev.ap); + dev->sata_dev.ap = NULL; + } + kfree(dev); } diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 731c89250639..b563ff27626b 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -1028,9 +1028,6 @@ void sas_target_destroy(struct scsi_target *starget) if (!found_dev) return; - if (dev_is_sata(found_dev)) - ata_sas_port_destroy(found_dev->sata_dev.ap); - starget->hostdata = NULL; sas_put_device(found_dev); } |