|
@@ -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)
|
|
|
{
|