aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-02-02 02:50:52 -0500
committerJeff Garzik <jeff@garzik.org>2007-05-01 07:49:54 -0400
commit9b89391cc861b8a1105551909eb66c024fe18ab2 (patch)
treef0783823927ea013c8d58c1041ad1e1d884eed9e /drivers/ata/libata-core.c
parentd4b2bab4f26345ea1803feb23ea92fbe3f6b77bc (diff)
libata: improve 0xff status handling
For PATA, 0xff status indicates empty port. For SATA, it depends on how the controller emulates status register. On some controllers, 0xff is used to represent broken link or certain stage during reset. libata currently deals SATA the same. This hasn't caused any problem because problematic situations usually only occur after hotplug or other link disruption events and libata blindly waited for the device to spin up and settle after hotplug giving the link and device whatever time to go through those stages. libata is going to replace unconditional spinup wait with generic timed sequence of resets, so not only getting 0xff handling right for SATA is, well, the right thing to do, it's much more important now. This patch makes the following changes. * Make ata_bus_softreset() return -ENODEV if any of its wait fails due to 0xff status. * Fail soft/hardreset if status wait returns -ENODEV indicating 0xff status while SStatus says the link is online. e.g. Reset fails if status is 0xff after reset when SStatus reports the linke is online. If SCR registers are not available, everything is the same as before. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 84e9448c12d..49d26675932 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -3027,15 +3027,18 @@ static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
3027 struct ata_ioports *ioaddr = &ap->ioaddr; 3027 struct ata_ioports *ioaddr = &ap->ioaddr;
3028 unsigned int dev0 = devmask & (1 << 0); 3028 unsigned int dev0 = devmask & (1 << 0);
3029 unsigned int dev1 = devmask & (1 << 1); 3029 unsigned int dev1 = devmask & (1 << 1);
3030 int rc; 3030 int rc, ret = 0;
3031 3031
3032 /* if device 0 was found in ata_devchk, wait for its 3032 /* if device 0 was found in ata_devchk, wait for its
3033 * BSY bit to clear 3033 * BSY bit to clear
3034 */ 3034 */
3035 if (dev0) { 3035 if (dev0) {
3036 rc = ata_wait_ready(ap, deadline); 3036 rc = ata_wait_ready(ap, deadline);
3037 if (rc && rc != -ENODEV) 3037 if (rc) {
3038 return rc; 3038 if (rc != -ENODEV)
3039 return rc;
3040 ret = rc;
3041 }
3039 } 3042 }
3040 3043
3041 /* if device 1 was found in ata_devchk, wait for 3044 /* if device 1 was found in ata_devchk, wait for
@@ -3055,8 +3058,11 @@ static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
3055 } 3058 }
3056 if (dev1) { 3059 if (dev1) {
3057 rc = ata_wait_ready(ap, deadline); 3060 rc = ata_wait_ready(ap, deadline);
3058 if (rc && rc != -ENODEV) 3061 if (rc) {
3059 return rc; 3062 if (rc != -ENODEV)
3063 return rc;
3064 ret = rc;
3065 }
3060 } 3066 }
3061 3067
3062 /* is all this really necessary? */ 3068 /* is all this really necessary? */
@@ -3066,7 +3072,7 @@ static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
3066 if (dev0) 3072 if (dev0)
3067 ap->ops->dev_select(ap, 0); 3073 ap->ops->dev_select(ap, 0);
3068 3074
3069 return 0; 3075 return ret;
3070} 3076}
3071 3077
3072static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, 3078static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
@@ -3100,7 +3106,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
3100 * pulldown resistor. 3106 * pulldown resistor.
3101 */ 3107 */
3102 if (ata_check_status(ap) == 0xFF) 3108 if (ata_check_status(ap) == 0xFF)
3103 return 0; 3109 return -ENODEV;
3104 3110
3105 return ata_bus_post_reset(ap, devmask, deadline); 3111 return ata_bus_post_reset(ap, devmask, deadline);
3106} 3112}
@@ -3131,6 +3137,7 @@ void ata_bus_reset(struct ata_port *ap)
3131 unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; 3137 unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
3132 u8 err; 3138 u8 err;
3133 unsigned int dev0, dev1 = 0, devmask = 0; 3139 unsigned int dev0, dev1 = 0, devmask = 0;
3140 int rc;
3134 3141
3135 DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no); 3142 DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
3136 3143
@@ -3152,9 +3159,11 @@ void ata_bus_reset(struct ata_port *ap)
3152 ap->ops->dev_select(ap, 0); 3159 ap->ops->dev_select(ap, 0);
3153 3160
3154 /* issue bus reset */ 3161 /* issue bus reset */
3155 if (ap->flags & ATA_FLAG_SRST) 3162 if (ap->flags & ATA_FLAG_SRST) {
3156 if (ata_bus_softreset(ap, devmask, jiffies + 40 * HZ)) 3163 rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
3164 if (rc && rc != -ENODEV)
3157 goto err_out; 3165 goto err_out;
3166 }
3158 3167
3159 /* 3168 /*
3160 * determine by signature whether we have ATA or ATAPI devices 3169 * determine by signature whether we have ATA or ATAPI devices
@@ -3417,7 +3426,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes,
3417 /* issue bus reset */ 3426 /* issue bus reset */
3418 DPRINTK("about to softreset, devmask=%x\n", devmask); 3427 DPRINTK("about to softreset, devmask=%x\n", devmask);
3419 rc = ata_bus_softreset(ap, devmask, deadline); 3428 rc = ata_bus_softreset(ap, devmask, deadline);
3420 if (rc) { 3429 /* if link is occupied, -ENODEV too is an error */
3430 if (rc && (rc != -ENODEV || sata_scr_valid(ap))) {
3421 ata_port_printk(ap, KERN_ERR, "SRST failed (errno=%d)\n", rc); 3431 ata_port_printk(ap, KERN_ERR, "SRST failed (errno=%d)\n", rc);
3422 return rc; 3432 return rc;
3423 } 3433 }
@@ -3534,7 +3544,8 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class,
3534 msleep(150); 3544 msleep(150);
3535 3545
3536 rc = ata_wait_ready(ap, deadline); 3546 rc = ata_wait_ready(ap, deadline);
3537 if (rc && rc != -ENODEV) { 3547 /* link occupied, -ENODEV too is an error */
3548 if (rc) {
3538 ata_port_printk(ap, KERN_ERR, 3549 ata_port_printk(ap, KERN_ERR,
3539 "COMRESET failed (errno=%d)\n", rc); 3550 "COMRESET failed (errno=%d)\n", rc);
3540 return rc; 3551 return rc;