aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_ata.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
-rw-r--r--drivers/scsi/libsas/sas_ata.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index d109cc3a17b6..b035acf18730 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -523,6 +523,31 @@ static void sas_ata_set_dmamode(struct ata_port *ap, struct ata_device *ata_dev)
523 i->dft->lldd_ata_set_dmamode(dev); 523 i->dft->lldd_ata_set_dmamode(dev);
524} 524}
525 525
526static void sas_ata_sched_eh(struct ata_port *ap)
527{
528 struct domain_device *dev = ap->private_data;
529 struct sas_ha_struct *ha = dev->port->ha;
530 unsigned long flags;
531
532 spin_lock_irqsave(&ha->lock, flags);
533 if (!test_and_set_bit(SAS_DEV_EH_PENDING, &dev->state))
534 ha->eh_active++;
535 ata_std_sched_eh(ap);
536 spin_unlock_irqrestore(&ha->lock, flags);
537}
538
539void sas_ata_end_eh(struct ata_port *ap)
540{
541 struct domain_device *dev = ap->private_data;
542 struct sas_ha_struct *ha = dev->port->ha;
543 unsigned long flags;
544
545 spin_lock_irqsave(&ha->lock, flags);
546 if (test_and_clear_bit(SAS_DEV_EH_PENDING, &dev->state))
547 ha->eh_active--;
548 spin_unlock_irqrestore(&ha->lock, flags);
549}
550
526static struct ata_port_operations sas_sata_ops = { 551static struct ata_port_operations sas_sata_ops = {
527 .prereset = ata_std_prereset, 552 .prereset = ata_std_prereset,
528 .hardreset = sas_ata_hard_reset, 553 .hardreset = sas_ata_hard_reset,
@@ -536,6 +561,8 @@ static struct ata_port_operations sas_sata_ops = {
536 .port_start = ata_sas_port_start, 561 .port_start = ata_sas_port_start,
537 .port_stop = ata_sas_port_stop, 562 .port_stop = ata_sas_port_stop,
538 .set_dmamode = sas_ata_set_dmamode, 563 .set_dmamode = sas_ata_set_dmamode,
564 .sched_eh = sas_ata_sched_eh,
565 .end_eh = sas_ata_end_eh,
539}; 566};
540 567
541static struct ata_port_info sata_port_info = { 568static struct ata_port_info sata_port_info = {
@@ -708,10 +735,6 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie)
708 struct ata_port *ap = dev->sata_dev.ap; 735 struct ata_port *ap = dev->sata_dev.ap;
709 struct sas_ha_struct *ha = dev->port->ha; 736 struct sas_ha_struct *ha = dev->port->ha;
710 737
711 /* hold a reference over eh since we may be racing with final
712 * remove once all commands are completed
713 */
714 kref_get(&dev->kref);
715 sas_ata_printk(KERN_DEBUG, dev, "dev error handler\n"); 738 sas_ata_printk(KERN_DEBUG, dev, "dev error handler\n");
716 ata_scsi_port_error_handler(ha->core.shost, ap); 739 ata_scsi_port_error_handler(ha->core.shost, ap);
717 sas_put_device(dev); 740 sas_put_device(dev);
@@ -742,6 +765,13 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost)
742 list_for_each_entry(dev, &port->dev_list, dev_list_node) { 765 list_for_each_entry(dev, &port->dev_list, dev_list_node) {
743 if (!dev_is_sata(dev)) 766 if (!dev_is_sata(dev))
744 continue; 767 continue;
768
769 /* hold a reference over eh since we may be
770 * racing with final remove once all commands
771 * are completed
772 */
773 kref_get(&dev->kref);
774
745 async_schedule_domain(async_sas_ata_eh, dev, &async); 775 async_schedule_domain(async_sas_ata_eh, dev, &async);
746 } 776 }
747 spin_unlock(&port->dev_list_lock); 777 spin_unlock(&port->dev_list_lock);