diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2007-10-25 09:21:16 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-01-23 05:24:15 -0500 |
commit | c5038fc05d4aa4ae0671776199459690e4c973cb (patch) | |
tree | 4011035b5a738fa51403882153e5e1c5047a1d87 /drivers/ata/libata-core.c | |
parent | a5df2eabdae7cd7840d59cffe621b3658a3a70cb (diff) |
libata/pata_it821x: Improve handling of poorly compatible emulations
Some it821x RAID firmwares return 0 for the err return off both devices.
A similar issue occurs with the slave returning 0 not 1 if you plug a
gigabyte sata ramdisk into a controller that fakes two SATA ports as
master/slave on an SFF channel.
The patch does the following
- Allow the 'failed diagnostics' case on both master and slave
- Move the HORKAGE_DIAGNOSTIC check after ->dev_config
This second change also allows IT821x to fix up a problem where we report
drive diagnostic failures when in fact the drive is fine but the
microcontroller firmware doesn't appear to get it right. IT821x clears
the flag again to avoid giving the user bogus warnings about their disk.
The other IT821x change is a bit ugly, we slightly abuse the cable type
hook to fiddle with the identify data for the devices. We could add a new
hook for this but as we have only one offender and no more seeming likely
it seems better to keep libata-core clean.
Please let this sit in -mm briefly, just in case the relaxed checking
breaks some other emulated interface.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ee72994500a3..627703cba9a6 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -950,8 +950,8 @@ unsigned int ata_dev_try_classify(struct ata_device *dev, int present, | |||
950 | if (r_err) | 950 | if (r_err) |
951 | *r_err = err; | 951 | *r_err = err; |
952 | 952 | ||
953 | /* see if device passed diags: if master then continue and warn later */ | 953 | /* see if device passed diags: continue and warn later */ |
954 | if (err == 0 && dev->devno == 0) | 954 | if (err == 0) |
955 | /* diagnostic fail : do nothing _YET_ */ | 955 | /* diagnostic fail : do nothing _YET_ */ |
956 | dev->horkage |= ATA_HORKAGE_DIAGNOSTIC; | 956 | dev->horkage |= ATA_HORKAGE_DIAGNOSTIC; |
957 | else if (err == 1) | 957 | else if (err == 1) |
@@ -2262,19 +2262,8 @@ int ata_dev_configure(struct ata_device *dev) | |||
2262 | dev->flags |= ATA_DFLAG_DIPM; | 2262 | dev->flags |= ATA_DFLAG_DIPM; |
2263 | } | 2263 | } |
2264 | 2264 | ||
2265 | if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { | 2265 | /* Limit PATA drive on SATA cable bridge transfers to udma5, |
2266 | /* Let the user know. We don't want to disallow opens for | 2266 | 200 sectors */ |
2267 | rescue purposes, or in case the vendor is just a blithering | ||
2268 | idiot */ | ||
2269 | if (print_info) { | ||
2270 | ata_dev_printk(dev, KERN_WARNING, | ||
2271 | "Drive reports diagnostics failure. This may indicate a drive\n"); | ||
2272 | ata_dev_printk(dev, KERN_WARNING, | ||
2273 | "fault or invalid emulation. Contact drive vendor for information.\n"); | ||
2274 | } | ||
2275 | } | ||
2276 | |||
2277 | /* limit bridge transfers to udma5, 200 sectors */ | ||
2278 | if (ata_dev_knobble(dev)) { | 2267 | if (ata_dev_knobble(dev)) { |
2279 | if (ata_msg_drv(ap) && print_info) | 2268 | if (ata_msg_drv(ap) && print_info) |
2280 | ata_dev_printk(dev, KERN_INFO, | 2269 | ata_dev_printk(dev, KERN_INFO, |
@@ -2303,6 +2292,21 @@ int ata_dev_configure(struct ata_device *dev) | |||
2303 | if (ap->ops->dev_config) | 2292 | if (ap->ops->dev_config) |
2304 | ap->ops->dev_config(dev); | 2293 | ap->ops->dev_config(dev); |
2305 | 2294 | ||
2295 | if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { | ||
2296 | /* Let the user know. We don't want to disallow opens for | ||
2297 | rescue purposes, or in case the vendor is just a blithering | ||
2298 | idiot. Do this after the dev_config call as some controllers | ||
2299 | with buggy firmware may want to avoid reporting false device | ||
2300 | bugs */ | ||
2301 | |||
2302 | if (print_info) { | ||
2303 | ata_dev_printk(dev, KERN_WARNING, | ||
2304 | "Drive reports diagnostics failure. This may indicate a drive\n"); | ||
2305 | ata_dev_printk(dev, KERN_WARNING, | ||
2306 | "fault or invalid emulation. Contact drive vendor for information.\n"); | ||
2307 | } | ||
2308 | } | ||
2309 | |||
2306 | if (ata_msg_probe(ap)) | 2310 | if (ata_msg_probe(ap)) |
2307 | ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", | 2311 | ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", |
2308 | __FUNCTION__, ata_chk_status(ap)); | 2312 | __FUNCTION__, ata_chk_status(ap)); |
@@ -3066,7 +3070,7 @@ static int ata_dev_set_mode(struct ata_device *dev) | |||
3066 | 3070 | ||
3067 | /* Early MWDMA devices do DMA but don't allow DMA mode setting. | 3071 | /* Early MWDMA devices do DMA but don't allow DMA mode setting. |
3068 | Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */ | 3072 | Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */ |
3069 | if (dev->xfer_shift == ATA_SHIFT_MWDMA && | 3073 | if (dev->xfer_shift == ATA_SHIFT_MWDMA && |
3070 | dev->dma_mode == XFER_MW_DMA_0 && | 3074 | dev->dma_mode == XFER_MW_DMA_0 && |
3071 | (dev->id[63] >> 8) & 1) | 3075 | (dev->id[63] >> 8) & 1) |
3072 | err_mask &= ~AC_ERR_DEV; | 3076 | err_mask &= ~AC_ERR_DEV; |