summaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-06-22 02:25:27 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-07-20 03:58:45 -0400
commite4a9c3732cea3e3c8c704aad86636090ffe6b25f (patch)
treefaea8e91b3d917dcdb4c89adbb021ac737a6cb35 /drivers/ata/libata-eh.c
parent3b661a92e869ebe2358de8f4b3230ad84f7fce51 (diff)
[SCSI] libata, libsas: introduce sched_eh and end_eh port ops
When managing shost->host_eh_scheduled libata assumes that there is a 1:1 shost-to-ata_port relationship. libsas creates a 1:N relationship so it needs to manage host_eh_scheduled cumulatively at the host level. The sched_eh and end_eh port port ops allow libsas to track when domain devices enter/leave the "eh-pending" state under ha->lock (previously named ha->state_lock, but it is no longer just a lock for ha->state changes). Since host_eh_scheduled indicates eh without backing commands pinning the device it can be deallocated at any time. Move the taking of the domain_device reference under the port_lock to guarantee that the ata_port stays around for the duration of eh. Reviewed-by: Jacek Danecki <jacek.danecki@intel.com> Acked-by: Jeff Garzik <jgarzik@redhat.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c57
1 files changed, 46 insertions, 11 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 6d53cf9b3b6e..77fc80640e26 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -793,12 +793,12 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
793 ata_for_each_link(link, ap, HOST_FIRST) 793 ata_for_each_link(link, ap, HOST_FIRST)
794 memset(&link->eh_info, 0, sizeof(link->eh_info)); 794 memset(&link->eh_info, 0, sizeof(link->eh_info));
795 795
796 /* Clear host_eh_scheduled while holding ap->lock such 796 /* end eh (clear host_eh_scheduled) while holding
797 * that if exception occurs after this point but 797 * ap->lock such that if exception occurs after this
798 * before EH completion, SCSI midlayer will 798 * point but before EH completion, SCSI midlayer will
799 * re-initiate EH. 799 * re-initiate EH.
800 */ 800 */
801 host->host_eh_scheduled = 0; 801 ap->ops->end_eh(ap);
802 802
803 spin_unlock_irqrestore(ap->lock, flags); 803 spin_unlock_irqrestore(ap->lock, flags);
804 ata_eh_release(ap); 804 ata_eh_release(ap);
@@ -986,16 +986,13 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
986} 986}
987 987
988/** 988/**
989 * ata_port_schedule_eh - schedule error handling without a qc 989 * ata_std_sched_eh - non-libsas ata_ports issue eh with this common routine
990 * @ap: ATA port to schedule EH for 990 * @ap: ATA port to schedule EH for
991 *
992 * Schedule error handling for @ap. EH will kick in as soon as
993 * all commands are drained.
994 * 991 *
995 * LOCKING: 992 * LOCKING: inherited from ata_port_schedule_eh
996 * spin_lock_irqsave(host lock) 993 * spin_lock_irqsave(host lock)
997 */ 994 */
998void ata_port_schedule_eh(struct ata_port *ap) 995void ata_std_sched_eh(struct ata_port *ap)
999{ 996{
1000 WARN_ON(!ap->ops->error_handler); 997 WARN_ON(!ap->ops->error_handler);
1001 998
@@ -1007,6 +1004,44 @@ void ata_port_schedule_eh(struct ata_port *ap)
1007 1004
1008 DPRINTK("port EH scheduled\n"); 1005 DPRINTK("port EH scheduled\n");
1009} 1006}
1007EXPORT_SYMBOL_GPL(ata_std_sched_eh);
1008
1009/**
1010 * ata_std_end_eh - non-libsas ata_ports complete eh with this common routine
1011 * @ap: ATA port to end EH for
1012 *
1013 * In the libata object model there is a 1:1 mapping of ata_port to
1014 * shost, so host fields can be directly manipulated under ap->lock, in
1015 * the libsas case we need to hold a lock at the ha->level to coordinate
1016 * these events.
1017 *
1018 * LOCKING:
1019 * spin_lock_irqsave(host lock)
1020 */
1021void ata_std_end_eh(struct ata_port *ap)
1022{
1023 struct Scsi_Host *host = ap->scsi_host;
1024
1025 host->host_eh_scheduled = 0;
1026}
1027EXPORT_SYMBOL(ata_std_end_eh);
1028
1029
1030/**
1031 * ata_port_schedule_eh - schedule error handling without a qc
1032 * @ap: ATA port to schedule EH for
1033 *
1034 * Schedule error handling for @ap. EH will kick in as soon as
1035 * all commands are drained.
1036 *
1037 * LOCKING:
1038 * spin_lock_irqsave(host lock)
1039 */
1040void ata_port_schedule_eh(struct ata_port *ap)
1041{
1042 /* see: ata_std_sched_eh, unless you know better */
1043 ap->ops->sched_eh(ap);
1044}
1010 1045
1011static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link) 1046static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)
1012{ 1047{