diff options
author | Tejun Heo <htejun@gmail.com> | 2008-04-07 09:47:19 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-17 15:44:22 -0400 |
commit | aa2731ad9ad80ac3fca48bd1c4cf0eceede4810e (patch) | |
tree | db6d3327017b9b84355aba49a5ccd5c322d3f248 | |
parent | 705e76beb90b97421e1f61e857c4246799781bb5 (diff) |
libata: separate out ata_wait_ready() and implement ata_wait_after_reset()
Factor out waiting logic (which is common to all ATA controllers) from
ata_sff_wait_ready() into ata_wait_ready(). ata_wait_ready() takes
@check_ready function pointer and uses it to poll for readiness. This
allows non-SFF controllers to use ata_wait_ready() to wait for link
readiness.
This patch also implements ata_wait_after_reset() - generic version of
ata_sff_wait_after_reset() - using ata_wait_ready().
ata_sff_wait_ready() is reimplemented using ata_wait_ready() and
ata_sff_check_ready(). Functionality remains the same.
Signed-off-by: Tejun Heo <htejun@gmail.com>
-rw-r--r-- | drivers/ata/libata-core.c | 98 | ||||
-rw-r--r-- | drivers/ata/libata-sff.c | 62 | ||||
-rw-r--r-- | drivers/ata/libata.h | 2 | ||||
-rw-r--r-- | include/linux/libata.h | 2 |
4 files changed, 114 insertions, 50 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index eaead76c9443..3bad6f189190 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -3311,6 +3311,103 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) | |||
3311 | } | 3311 | } |
3312 | 3312 | ||
3313 | /** | 3313 | /** |
3314 | * ata_wait_ready - wait for link to become ready | ||
3315 | * @link: link to be waited on | ||
3316 | * @deadline: deadline jiffies for the operation | ||
3317 | * @check_ready: callback to check link readiness | ||
3318 | * | ||
3319 | * Wait for @link to become ready. @check_ready should return | ||
3320 | * positive number if @link is ready, 0 if it isn't, -ENODEV if | ||
3321 | * link doesn't seem to be occupied, other errno for other error | ||
3322 | * conditions. | ||
3323 | * | ||
3324 | * Transient -ENODEV conditions are allowed for | ||
3325 | * ATA_TMOUT_FF_WAIT. | ||
3326 | * | ||
3327 | * LOCKING: | ||
3328 | * EH context. | ||
3329 | * | ||
3330 | * RETURNS: | ||
3331 | * 0 if @linke is ready before @deadline; otherwise, -errno. | ||
3332 | */ | ||
3333 | int ata_wait_ready(struct ata_link *link, unsigned long deadline, | ||
3334 | int (*check_ready)(struct ata_link *link)) | ||
3335 | { | ||
3336 | unsigned long start = jiffies; | ||
3337 | unsigned long nodev_deadline = start + ATA_TMOUT_FF_WAIT; | ||
3338 | int warned = 0; | ||
3339 | |||
3340 | if (time_after(nodev_deadline, deadline)) | ||
3341 | nodev_deadline = deadline; | ||
3342 | |||
3343 | while (1) { | ||
3344 | unsigned long now = jiffies; | ||
3345 | int ready, tmp; | ||
3346 | |||
3347 | ready = tmp = check_ready(link); | ||
3348 | if (ready > 0) | ||
3349 | return 0; | ||
3350 | |||
3351 | /* -ENODEV could be transient. Ignore -ENODEV if link | ||
3352 | * is online. Also, some SATA devices take a long | ||
3353 | * time to clear 0xff after reset. For example, | ||
3354 | * HHD424020F7SV00 iVDR needs >= 800ms while Quantum | ||
3355 | * GoVault needs even more than that. Wait for | ||
3356 | * ATA_TMOUT_FF_WAIT on -ENODEV if link isn't offline. | ||
3357 | * | ||
3358 | * Note that some PATA controllers (pata_ali) explode | ||
3359 | * if status register is read more than once when | ||
3360 | * there's no device attached. | ||
3361 | */ | ||
3362 | if (ready == -ENODEV) { | ||
3363 | if (ata_link_online(link)) | ||
3364 | ready = 0; | ||
3365 | else if ((link->ap->flags & ATA_FLAG_SATA) && | ||
3366 | !ata_link_offline(link) && | ||
3367 | time_before(now, nodev_deadline)) | ||
3368 | ready = 0; | ||
3369 | } | ||
3370 | |||
3371 | if (ready) | ||
3372 | return ready; | ||
3373 | if (time_after(now, deadline)) | ||
3374 | return -EBUSY; | ||
3375 | |||
3376 | if (!warned && time_after(now, start + 5 * HZ) && | ||
3377 | (deadline - now > 3 * HZ)) { | ||
3378 | ata_link_printk(link, KERN_WARNING, | ||
3379 | "link is slow to respond, please be patient " | ||
3380 | "(ready=%d)\n", tmp); | ||
3381 | warned = 1; | ||
3382 | } | ||
3383 | |||
3384 | msleep(50); | ||
3385 | } | ||
3386 | } | ||
3387 | |||
3388 | /** | ||
3389 | * ata_wait_after_reset - wait for link to become ready after reset | ||
3390 | * @link: link to be waited on | ||
3391 | * @deadline: deadline jiffies for the operation | ||
3392 | * @check_ready: callback to check link readiness | ||
3393 | * | ||
3394 | * Wait for @link to become ready after reset. | ||
3395 | * | ||
3396 | * LOCKING: | ||
3397 | * EH context. | ||
3398 | * | ||
3399 | * RETURNS: | ||
3400 | * 0 if @linke is ready before @deadline; otherwise, -errno. | ||
3401 | */ | ||
3402 | extern int ata_wait_after_reset(struct ata_link *link, unsigned long deadline, | ||
3403 | int (*check_ready)(struct ata_link *link)) | ||
3404 | { | ||
3405 | msleep(ATA_WAIT_AFTER_RESET_MSECS); | ||
3406 | |||
3407 | return ata_wait_ready(link, deadline, check_ready); | ||
3408 | } | ||
3409 | |||
3410 | /** | ||
3314 | * sata_link_debounce - debounce SATA phy status | 3411 | * sata_link_debounce - debounce SATA phy status |
3315 | * @link: ATA link to debounce SATA phy status for | 3412 | * @link: ATA link to debounce SATA phy status for |
3316 | * @params: timing parameters { interval, duratinon, timeout } in msec | 3413 | * @params: timing parameters { interval, duratinon, timeout } in msec |
@@ -6075,6 +6172,7 @@ EXPORT_SYMBOL_GPL(ata_noop_qc_prep); | |||
6075 | EXPORT_SYMBOL_GPL(ata_port_probe); | 6172 | EXPORT_SYMBOL_GPL(ata_port_probe); |
6076 | EXPORT_SYMBOL_GPL(ata_dev_disable); | 6173 | EXPORT_SYMBOL_GPL(ata_dev_disable); |
6077 | EXPORT_SYMBOL_GPL(sata_set_spd); | 6174 | EXPORT_SYMBOL_GPL(sata_set_spd); |
6175 | EXPORT_SYMBOL_GPL(ata_wait_after_reset); | ||
6078 | EXPORT_SYMBOL_GPL(sata_link_debounce); | 6176 | EXPORT_SYMBOL_GPL(sata_link_debounce); |
6079 | EXPORT_SYMBOL_GPL(sata_link_resume); | 6177 | EXPORT_SYMBOL_GPL(sata_link_resume); |
6080 | EXPORT_SYMBOL_GPL(ata_std_prereset); | 6178 | EXPORT_SYMBOL_GPL(ata_std_prereset); |
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 6e8de3c1595e..78912c5011ad 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -308,6 +308,17 @@ int ata_sff_busy_sleep(struct ata_port *ap, | |||
308 | return 0; | 308 | return 0; |
309 | } | 309 | } |
310 | 310 | ||
311 | static int ata_sff_check_ready(struct ata_link *link) | ||
312 | { | ||
313 | u8 status = link->ap->ops->sff_check_status(link->ap); | ||
314 | |||
315 | if (!(status & ATA_BUSY)) | ||
316 | return 1; | ||
317 | if (status == 0xff) | ||
318 | return -ENODEV; | ||
319 | return 0; | ||
320 | } | ||
321 | |||
311 | /** | 322 | /** |
312 | * ata_sff_wait_ready - sleep until BSY clears, or timeout | 323 | * ata_sff_wait_ready - sleep until BSY clears, or timeout |
313 | * @link: SFF link to wait ready status for | 324 | * @link: SFF link to wait ready status for |
@@ -324,56 +335,7 @@ int ata_sff_busy_sleep(struct ata_port *ap, | |||
324 | */ | 335 | */ |
325 | int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline) | 336 | int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline) |
326 | { | 337 | { |
327 | struct ata_port *ap = link->ap; | 338 | return ata_wait_ready(link, deadline, ata_sff_check_ready); |
328 | unsigned long start = jiffies; | ||
329 | unsigned long nodev_deadline = start + ATA_TMOUT_FF_WAIT; | ||
330 | int warned = 0; | ||
331 | |||
332 | if (time_after(nodev_deadline, deadline)) | ||
333 | nodev_deadline = deadline; | ||
334 | |||
335 | while (1) { | ||
336 | u8 status = ap->ops->sff_check_status(ap); | ||
337 | unsigned long now = jiffies; | ||
338 | |||
339 | if (!(status & ATA_BUSY)) | ||
340 | return 0; | ||
341 | |||
342 | /* No device status could be transient. Ignore it if | ||
343 | * link is online. Also, some SATA devices take a | ||
344 | * long time to clear 0xff after reset. For example, | ||
345 | * HHD424020F7SV00 iVDR needs >= 800ms while Quantum | ||
346 | * GoVault needs even more than that. Wait for | ||
347 | * ATA_TMOUT_FF_WAIT on -ENODEV if link isn't offline. | ||
348 | * | ||
349 | * Note that some PATA controllers (pata_ali) explode | ||
350 | * if status register is read more than once when | ||
351 | * there's no device attached. | ||
352 | */ | ||
353 | if (status == 0xff) { | ||
354 | if (ata_link_online(link)) | ||
355 | status = ATA_BUSY; | ||
356 | else if ((link->ap->flags & ATA_FLAG_SATA) && | ||
357 | !ata_link_offline(link) && | ||
358 | time_before(now, nodev_deadline)) | ||
359 | status = ATA_BUSY; | ||
360 | if (status == 0xff) | ||
361 | return -ENODEV; | ||
362 | } | ||
363 | |||
364 | if (time_after(now, deadline)) | ||
365 | return -EBUSY; | ||
366 | |||
367 | if (!warned && time_after(now, start + 5 * HZ) && | ||
368 | (deadline - now > 3 * HZ)) { | ||
369 | ata_link_printk(link, KERN_WARNING, | ||
370 | "link is slow to respond, please be patient " | ||
371 | "(Status 0x%x)\n", status); | ||
372 | warned = 1; | ||
373 | } | ||
374 | |||
375 | msleep(50); | ||
376 | } | ||
377 | } | 339 | } |
378 | 340 | ||
379 | /** | 341 | /** |
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 11b5f67a19d4..08af43e2c081 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -81,6 +81,8 @@ extern unsigned ata_exec_internal_sg(struct ata_device *dev, | |||
81 | int dma_dir, struct scatterlist *sg, | 81 | int dma_dir, struct scatterlist *sg, |
82 | unsigned int n_elem, unsigned long timeout); | 82 | unsigned int n_elem, unsigned long timeout); |
83 | extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd); | 83 | extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd); |
84 | extern int ata_wait_ready(struct ata_link *link, unsigned long deadline, | ||
85 | int (*check_ready)(struct ata_link *link)); | ||
84 | extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | 86 | extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, |
85 | unsigned int flags, u16 *id); | 87 | unsigned int flags, u16 *id); |
86 | extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags); | 88 | extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags); |
diff --git a/include/linux/libata.h b/include/linux/libata.h index da5560244787..4bbf2524e473 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -837,6 +837,8 @@ extern void sata_print_link_status(struct ata_link *link); | |||
837 | extern void ata_port_probe(struct ata_port *); | 837 | extern void ata_port_probe(struct ata_port *); |
838 | extern int sata_set_spd(struct ata_link *link); | 838 | extern int sata_set_spd(struct ata_link *link); |
839 | extern int ata_std_prereset(struct ata_link *link, unsigned long deadline); | 839 | extern int ata_std_prereset(struct ata_link *link, unsigned long deadline); |
840 | extern int ata_wait_after_reset(struct ata_link *link, unsigned long deadline, | ||
841 | int (*check_ready)(struct ata_link *link)); | ||
840 | extern int sata_link_debounce(struct ata_link *link, | 842 | extern int sata_link_debounce(struct ata_link *link, |
841 | const unsigned long *params, unsigned long deadline); | 843 | const unsigned long *params, unsigned long deadline); |
842 | extern int sata_link_resume(struct ata_link *link, const unsigned long *params, | 844 | extern int sata_link_resume(struct ata_link *link, const unsigned long *params, |