From 099f7bbfca69809c21818f6157474e884343d1f3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 11 Apr 2006 22:22:29 +0900 Subject: [PATCH] --- yaml --- r: 29253 b: refs/heads/master c: c22daff41001e9ccead87179ac0547f85447139e h: refs/heads/master i: 29251: 86eac3c2891f88482041ae47293ebd5e8275c92c v: v3 --- [refs] | 2 +- trunk/drivers/scsi/libata-core.c | 47 ++++++++++++++++++++++++++++++++ trunk/include/linux/libata.h | 3 ++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index e69f0387834a..18e45db25286 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 643be977f9feba8c3c1e768fc06cac84596ec6f8 +refs/heads/master: c22daff41001e9ccead87179ac0547f85447139e diff --git a/trunk/drivers/scsi/libata-core.c b/trunk/drivers/scsi/libata-core.c index 2d76ce23728f..0075fe7404d5 100644 --- a/trunk/drivers/scsi/libata-core.c +++ b/trunk/drivers/scsi/libata-core.c @@ -5029,6 +5029,52 @@ int ata_ratelimit(void) return rc; } +/** + * ata_wait_register - wait until register value changes + * @reg: IO-mapped register + * @mask: Mask to apply to read register value + * @val: Wait condition + * @interval_msec: polling interval in milliseconds + * @timeout_msec: timeout in milliseconds + * + * Waiting for some bits of register to change is a common + * operation for ATA controllers. This function reads 32bit LE + * IO-mapped register @reg and tests for the following condition. + * + * (*@reg & mask) != val + * + * If the condition is met, it returns; otherwise, the process is + * repeated after @interval_msec until timeout. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * The final register value. + */ +u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, + unsigned long interval_msec, + unsigned long timeout_msec) +{ + unsigned long timeout; + u32 tmp; + + tmp = ioread32(reg); + + /* Calculate timeout _after_ the first read to make sure + * preceding writes reach the controller before starting to + * eat away the timeout. + */ + timeout = jiffies + (timeout_msec * HZ) / 1000; + + while ((tmp & mask) == val && time_before(jiffies, timeout)) { + msleep(interval_msec); + tmp = ioread32(reg); + } + + return tmp; +} + /* * libata is essentially a library of internal helper functions for * low-level ATA host controller drivers. As such, the API/ABI is @@ -5079,6 +5125,7 @@ EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_pair); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); +EXPORT_SYMBOL_GPL(ata_wait_register); EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index d5fd5c06e755..dd5bcb5d29b5 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -543,6 +543,9 @@ extern unsigned int ata_busy_sleep(struct ata_port *ap, unsigned long timeout); extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, unsigned long delay); +extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, + unsigned long interval_msec, + unsigned long timeout_msec); /* * Default driver ops implementations