aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2007-10-25 09:21:16 -0400
committerJeff Garzik <jeff@garzik.org>2008-01-23 05:24:15 -0500
commitc5038fc05d4aa4ae0671776199459690e4c973cb (patch)
tree4011035b5a738fa51403882153e5e1c5047a1d87 /drivers
parenta5df2eabdae7cd7840d59cffe621b3658a3a70cb (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')
-rw-r--r--drivers/ata/libata-core.c36
-rw-r--r--drivers/ata/pata_it821x.c35
2 files changed, 53 insertions, 18 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;
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index ca9aae09daed..109ddd42c266 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -430,7 +430,7 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
430 return ata_qc_issue_prot(qc); 430 return ata_qc_issue_prot(qc);
431 } 431 }
432 printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command); 432 printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
433 return AC_ERR_INVALID; 433 return AC_ERR_DEV;
434} 434}
435 435
436/** 436/**
@@ -516,6 +516,37 @@ static void it821x_dev_config(struct ata_device *adev)
516 printk("(%dK stripe)", adev->id[146]); 516 printk("(%dK stripe)", adev->id[146]);
517 printk(".\n"); 517 printk(".\n");
518 } 518 }
519 /* This is a controller firmware triggered funny, don't
520 report the drive faulty! */
521 adev->horkage &= ~ATA_HORKAGE_DIAGNOSTIC;
522}
523
524/**
525 * it821x_ident_hack - Hack identify data up
526 * @ap: Port
527 *
528 * Walk the devices on this firmware driven port and slightly
529 * mash the identify data to stop us and common tools trying to
530 * use features not firmware supported. The firmware itself does
531 * some masking (eg SMART) but not enough.
532 *
533 * This is a bit of an abuse of the cable method, but it is the
534 * only method called at the right time. We could modify the libata
535 * core specifically for ident hacking but while we have one offender
536 * it seems better to keep the fallout localised.
537 */
538
539static int it821x_ident_hack(struct ata_port *ap)
540{
541 struct ata_device *adev;
542 ata_link_for_each_dev(adev, &ap->link) {
543 if (ata_dev_enabled(adev)) {
544 adev->id[84] &= ~(1 << 6); /* No FUA */
545 adev->id[85] &= ~(1 << 10); /* No HPA */
546 adev->id[76] = 0; /* No NCQ/AN etc */
547 }
548 }
549 return ata_cable_unknown(ap);
519} 550}
520 551
521 552
@@ -634,7 +665,7 @@ static struct ata_port_operations it821x_smart_port_ops = {
634 .thaw = ata_bmdma_thaw, 665 .thaw = ata_bmdma_thaw,
635 .error_handler = ata_bmdma_error_handler, 666 .error_handler = ata_bmdma_error_handler,
636 .post_internal_cmd = ata_bmdma_post_internal_cmd, 667 .post_internal_cmd = ata_bmdma_post_internal_cmd,
637 .cable_detect = ata_cable_unknown, 668 .cable_detect = it821x_ident_hack,
638 669
639 .bmdma_setup = ata_bmdma_setup, 670 .bmdma_setup = ata_bmdma_setup,
640 .bmdma_start = ata_bmdma_start, 671 .bmdma_start = ata_bmdma_start,