|
@@ -904,6 +904,79 @@ int ata_port_freeze(struct ata_port *ap)
|
|
|
return nr_aborted;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * sata_async_notification - SATA async notification handler
|
|
|
+ * @ap: ATA port where async notification is received
|
|
|
+ *
|
|
|
+ * Handler to be called when async notification via SDB FIS is
|
|
|
+ * received. This function schedules EH if necessary.
|
|
|
+ *
|
|
|
+ * LOCKING:
|
|
|
+ * spin_lock_irqsave(host lock)
|
|
|
+ *
|
|
|
+ * RETURNS:
|
|
|
+ * 1 if EH is scheduled, 0 otherwise.
|
|
|
+ */
|
|
|
+int sata_async_notification(struct ata_port *ap)
|
|
|
+{
|
|
|
+ u32 sntf;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ if (!(ap->flags & ATA_FLAG_AN))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf);
|
|
|
+ if (rc == 0)
|
|
|
+ sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);
|
|
|
+
|
|
|
+ if (!ap->nr_pmp_links || rc) {
|
|
|
+ /* PMP is not attached or SNTF is not available */
|
|
|
+ if (!ap->nr_pmp_links) {
|
|
|
+ /* PMP is not attached. Check whether ATAPI
|
|
|
+ * AN is configured. If so, notify media
|
|
|
+ * change.
|
|
|
+ */
|
|
|
+ struct ata_device *dev = ap->link.device;
|
|
|
+
|
|
|
+ if ((dev->class == ATA_DEV_ATAPI) &&
|
|
|
+ (dev->flags & ATA_DFLAG_AN))
|
|
|
+ ata_scsi_media_change_notify(dev);
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ /* PMP is attached but SNTF is not available.
|
|
|
+ * ATAPI async media change notification is
|
|
|
+ * not used. The PMP must be reporting PHY
|
|
|
+ * status change, schedule EH.
|
|
|
+ */
|
|
|
+ ata_port_schedule_eh(ap);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /* PMP is attached and SNTF is available */
|
|
|
+ struct ata_link *link;
|
|
|
+
|
|
|
+ /* check and notify ATAPI AN */
|
|
|
+ ata_port_for_each_link(link, ap) {
|
|
|
+ if (!(sntf & (1 << link->pmp)))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if ((link->device->class == ATA_DEV_ATAPI) &&
|
|
|
+ (link->device->flags & ATA_DFLAG_AN))
|
|
|
+ ata_scsi_media_change_notify(link->device);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* If PMP is reporting that PHY status of some
|
|
|
+ * downstream ports has changed, schedule EH.
|
|
|
+ */
|
|
|
+ if (sntf & (1 << SATA_PMP_CTRL_PORT)) {
|
|
|
+ ata_port_schedule_eh(ap);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ata_eh_freeze_port - EH helper to freeze port
|
|
|
* @ap: ATA port to freeze
|