[PATCH] libata: implement ata_wait_register()
As waiting for some register bits to change seems to be a common operation shared by some controllers, implement helper function ata_wait_register(). This function also takes care of register write flushing. Note that the condition is inverted, the wait is over when the masked value does NOT match @val. As we're waiting for bits to change, this test is more powerful and allows the function to be used in more places. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
Родитель
643be977f9
Коммит
c22daff410
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче