Merge branch 'master' [vanilla Linus master] into libata-dev.git/upstream
[firefly-linux-kernel-4.4.55.git] / drivers / ata / libata-eh.c
index 938b6996c38fec1faea6c7d3e70635a076baeef9..7d4535e989bf5580d76909c2402460898ff86062 100644 (file)
@@ -793,12 +793,12 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
                ata_for_each_link(link, ap, HOST_FIRST)
                        memset(&link->eh_info, 0, sizeof(link->eh_info));
 
-               /* Clear host_eh_scheduled while holding ap->lock such
-                * that if exception occurs after this point but
-                * before EH completion, SCSI midlayer will
+               /* end eh (clear host_eh_scheduled) while holding
+                * ap->lock such that if exception occurs after this
+                * point but before EH completion, SCSI midlayer will
                 * re-initiate EH.
                 */
-               host->host_eh_scheduled = 0;
+               ap->ops->end_eh(ap);
 
                spin_unlock_irqrestore(ap->lock, flags);
                ata_eh_release(ap);
@@ -986,16 +986,13 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
 }
 
 /**
- *     ata_port_schedule_eh - schedule error handling without a qc
- *     @ap: ATA port to schedule EH for
- *
- *     Schedule error handling for @ap.  EH will kick in as soon as
- *     all commands are drained.
+ * ata_std_sched_eh - non-libsas ata_ports issue eh with this common routine
+ * @ap: ATA port to schedule EH for
  *
- *     LOCKING:
+ *     LOCKING: inherited from ata_port_schedule_eh
  *     spin_lock_irqsave(host lock)
  */
-void ata_port_schedule_eh(struct ata_port *ap)
+void ata_std_sched_eh(struct ata_port *ap)
 {
        WARN_ON(!ap->ops->error_handler);
 
@@ -1007,6 +1004,44 @@ void ata_port_schedule_eh(struct ata_port *ap)
 
        DPRINTK("port EH scheduled\n");
 }
+EXPORT_SYMBOL_GPL(ata_std_sched_eh);
+
+/**
+ * ata_std_end_eh - non-libsas ata_ports complete eh with this common routine
+ * @ap: ATA port to end EH for
+ *
+ * In the libata object model there is a 1:1 mapping of ata_port to
+ * shost, so host fields can be directly manipulated under ap->lock, in
+ * the libsas case we need to hold a lock at the ha->level to coordinate
+ * these events.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ */
+void ata_std_end_eh(struct ata_port *ap)
+{
+       struct Scsi_Host *host = ap->scsi_host;
+
+       host->host_eh_scheduled = 0;
+}
+EXPORT_SYMBOL(ata_std_end_eh);
+
+
+/**
+ *     ata_port_schedule_eh - schedule error handling without a qc
+ *     @ap: ATA port to schedule EH for
+ *
+ *     Schedule error handling for @ap.  EH will kick in as soon as
+ *     all commands are drained.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ */
+void ata_port_schedule_eh(struct ata_port *ap)
+{
+       /* see: ata_std_sched_eh, unless you know better */
+       ap->ops->sched_eh(ap);
+}
 
 static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)
 {