aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-04-07 09:47:19 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-04-17 15:44:22 -0400
commitaa2731ad9ad80ac3fca48bd1c4cf0eceede4810e (patch)
treedb6d3327017b9b84355aba49a5ccd5c322d3f248
parent705e76beb90b97421e1f61e857c4246799781bb5 (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.c98
-rw-r--r--drivers/ata/libata-sff.c62
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--include/linux/libata.h2
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 */
3333int 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 */
3402extern 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);
6075EXPORT_SYMBOL_GPL(ata_port_probe); 6172EXPORT_SYMBOL_GPL(ata_port_probe);
6076EXPORT_SYMBOL_GPL(ata_dev_disable); 6173EXPORT_SYMBOL_GPL(ata_dev_disable);
6077EXPORT_SYMBOL_GPL(sata_set_spd); 6174EXPORT_SYMBOL_GPL(sata_set_spd);
6175EXPORT_SYMBOL_GPL(ata_wait_after_reset);
6078EXPORT_SYMBOL_GPL(sata_link_debounce); 6176EXPORT_SYMBOL_GPL(sata_link_debounce);
6079EXPORT_SYMBOL_GPL(sata_link_resume); 6177EXPORT_SYMBOL_GPL(sata_link_resume);
6080EXPORT_SYMBOL_GPL(ata_std_prereset); 6178EXPORT_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
311static 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 */
325int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline) 336int 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);
83extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd); 83extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
84extern int ata_wait_ready(struct ata_link *link, unsigned long deadline,
85 int (*check_ready)(struct ata_link *link));
84extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, 86extern 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);
86extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags); 88extern 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);
837extern void ata_port_probe(struct ata_port *); 837extern void ata_port_probe(struct ata_port *);
838extern int sata_set_spd(struct ata_link *link); 838extern int sata_set_spd(struct ata_link *link);
839extern int ata_std_prereset(struct ata_link *link, unsigned long deadline); 839extern int ata_std_prereset(struct ata_link *link, unsigned long deadline);
840extern int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
841 int (*check_ready)(struct ata_link *link));
840extern int sata_link_debounce(struct ata_link *link, 842extern int sata_link_debounce(struct ata_link *link,
841 const unsigned long *params, unsigned long deadline); 843 const unsigned long *params, unsigned long deadline);
842extern int sata_link_resume(struct ata_link *link, const unsigned long *params, 844extern int sata_link_resume(struct ata_link *link, const unsigned long *params,