Implement SATA async notification handler sata_async_notification(). LLDs can call this function when it suspects SDB_NOTIFY has occurred. This function will check SCR_NOTIFICATION if available and schedule proper EH action. Currently, only PMP notification is handled. The function can be easily extended to cover ATAPI notification later. Signed-off-by: Tejun Heo <htejun@xxxxxxxxx> --- drivers/ata/libata-core.c | 1 + drivers/ata/libata-eh.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 1 + 3 files changed, 51 insertions(+), 0 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 17b1734..2d960da 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -7051,6 +7051,7 @@ EXPORT_SYMBOL_GPL(ata_port_schedule_eh); EXPORT_SYMBOL_GPL(ata_link_abort); EXPORT_SYMBOL_GPL(ata_port_abort); EXPORT_SYMBOL_GPL(ata_port_freeze); +EXPORT_SYMBOL_GPL(sata_async_notification); EXPORT_SYMBOL_GPL(ata_eh_freeze_port); EXPORT_SYMBOL_GPL(ata_eh_thaw_port); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index f4dae06..03b1665 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -773,6 +773,55 @@ int ata_port_freeze(struct ata_port *ap) } /** + * 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_SDB_NOTIFY)) + return 0; + + rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf); + if (rc == 0) { + if (!sntf) + return 0; + + /* clear it */ + sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf); + + /* PMP is reporting that PHY status of some downstream + * ports have changed. Schedule EH. + */ + if (ap->nr_pmp_links && (sntf & (1 << SATA_PMP_CTRL_PORT))) { + ata_port_schedule_eh(ap); + return 1; + } + } else { + /* Dunno what's going on. Schedule EH if PMP is + * attached. It might be reporting PHY status change. + */ + if (ap->nr_pmp_links) { + ata_port_schedule_eh(ap); + return 1; + } + } + + return 0; +} + +/** * ata_eh_freeze_port - EH helper to freeze port * @ap: ATA port to freeze * diff --git a/include/linux/libata.h b/include/linux/libata.h index d41da74..09959a7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -947,6 +947,7 @@ extern void ata_port_schedule_eh(struct ata_port *ap); extern int ata_link_abort(struct ata_link *link); extern int ata_port_abort(struct ata_port *ap); extern int ata_port_freeze(struct ata_port *ap); +extern int sata_async_notification(struct ata_port *ap); extern void ata_eh_freeze_port(struct ata_port *ap); extern void ata_eh_thaw_port(struct ata_port *ap); -- 1.5.0.3 - To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html