aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-10-06 04:08:40 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-10-06 20:58:18 -0400
commit3b761d3d437cffcaf160a5d37eb6b3b186e491d5 (patch)
treec1f501cb350776f60eb1d4deaf206b10ed852c4e /drivers
parentf80ae7e45a0e03da188494c6e947a5c8b0cdfb4a (diff)
libata: fix incorrect link online check during probe
While trying to work around spurious detection retries for non-existent devices on slave links, commit 816ab89782ac139a8b65147cca990822bb7e8675 incorrectly added link offline check logic before ata_eh_thaw() was called. This means that if an occupied link goes down briefly at the time that offline check was performed, device class will be cleared to ATA_DEV_NONE and libata wouldn't retry thus failing detection of the device. The offline check should be done after the port is thawed together with online check so that such link glitches can be detected by the interrupt handler and handled properly. Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Tim Blechmann <tim@klingt.org> Cc: stable@kernel.org Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libata-eh.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index a04488f0de88..0a97822da211 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2667,14 +2667,14 @@ int ata_eh_reset(struct ata_link *link, int classify,
2667 dev->pio_mode = XFER_PIO_0; 2667 dev->pio_mode = XFER_PIO_0;
2668 dev->flags &= ~ATA_DFLAG_SLEEPING; 2668 dev->flags &= ~ATA_DFLAG_SLEEPING;
2669 2669
2670 if (!ata_phys_link_offline(ata_dev_phys_link(dev))) { 2670 if (ata_phys_link_offline(ata_dev_phys_link(dev)))
2671 /* apply class override */ 2671 continue;
2672 if (lflags & ATA_LFLAG_ASSUME_ATA) 2672
2673 classes[dev->devno] = ATA_DEV_ATA; 2673 /* apply class override */
2674 else if (lflags & ATA_LFLAG_ASSUME_SEMB) 2674 if (lflags & ATA_LFLAG_ASSUME_ATA)
2675 classes[dev->devno] = ATA_DEV_SEMB_UNSUP; 2675 classes[dev->devno] = ATA_DEV_ATA;
2676 } else 2676 else if (lflags & ATA_LFLAG_ASSUME_SEMB)
2677 classes[dev->devno] = ATA_DEV_NONE; 2677 classes[dev->devno] = ATA_DEV_SEMB_UNSUP;
2678 } 2678 }
2679 2679
2680 /* record current link speed */ 2680 /* record current link speed */
@@ -2713,34 +2713,48 @@ int ata_eh_reset(struct ata_link *link, int classify,
2713 ap->pflags &= ~ATA_PFLAG_EH_PENDING; 2713 ap->pflags &= ~ATA_PFLAG_EH_PENDING;
2714 spin_unlock_irqrestore(link->ap->lock, flags); 2714 spin_unlock_irqrestore(link->ap->lock, flags);
2715 2715
2716 /* Make sure onlineness and classification result correspond. 2716 /*
2717 * Make sure onlineness and classification result correspond.
2717 * Hotplug could have happened during reset and some 2718 * Hotplug could have happened during reset and some
2718 * controllers fail to wait while a drive is spinning up after 2719 * controllers fail to wait while a drive is spinning up after
2719 * being hotplugged causing misdetection. By cross checking 2720 * being hotplugged causing misdetection. By cross checking
2720 * link onlineness and classification result, those conditions 2721 * link on/offlineness and classification result, those
2721 * can be reliably detected and retried. 2722 * conditions can be reliably detected and retried.
2722 */ 2723 */
2723 nr_unknown = 0; 2724 nr_unknown = 0;
2724 ata_for_each_dev(dev, link, ALL) { 2725 ata_for_each_dev(dev, link, ALL) {
2725 /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ 2726 if (ata_phys_link_online(ata_dev_phys_link(dev))) {
2726 if (classes[dev->devno] == ATA_DEV_UNKNOWN) { 2727 if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
2727 classes[dev->devno] = ATA_DEV_NONE; 2728 ata_dev_printk(dev, KERN_DEBUG, "link online "
2728 if (ata_phys_link_online(ata_dev_phys_link(dev))) 2729 "but device misclassifed\n");
2730 classes[dev->devno] = ATA_DEV_NONE;
2729 nr_unknown++; 2731 nr_unknown++;
2732 }
2733 } else if (ata_phys_link_offline(ata_dev_phys_link(dev))) {
2734 if (ata_class_enabled(classes[dev->devno]))
2735 ata_dev_printk(dev, KERN_DEBUG, "link offline, "
2736 "clearing class %d to NONE\n",
2737 classes[dev->devno]);
2738 classes[dev->devno] = ATA_DEV_NONE;
2739 } else if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
2740 ata_dev_printk(dev, KERN_DEBUG, "link status unknown, "
2741 "clearing UNKNOWN to NONE\n");
2742 classes[dev->devno] = ATA_DEV_NONE;
2730 } 2743 }
2731 } 2744 }
2732 2745
2733 if (classify && nr_unknown) { 2746 if (classify && nr_unknown) {
2734 if (try < max_tries) { 2747 if (try < max_tries) {
2735 ata_link_printk(link, KERN_WARNING, "link online but " 2748 ata_link_printk(link, KERN_WARNING, "link online but "
2736 "device misclassified, retrying\n"); 2749 "%d devices misclassified, retrying\n",
2750 nr_unknown);
2737 failed_link = link; 2751 failed_link = link;
2738 rc = -EAGAIN; 2752 rc = -EAGAIN;
2739 goto fail; 2753 goto fail;
2740 } 2754 }
2741 ata_link_printk(link, KERN_WARNING, 2755 ata_link_printk(link, KERN_WARNING,
2742 "link online but device misclassified, " 2756 "link online but %d devices misclassified, "
2743 "device detection might fail\n"); 2757 "device detection might fail\n", nr_unknown);
2744 } 2758 }
2745 2759
2746 /* reset successful, schedule revalidation */ 2760 /* reset successful, schedule revalidation */