aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ata_piix.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-08-20 04:56:38 -0400
committerJeff Garzik <jeff@garzik.org>2006-08-22 06:07:48 -0400
commitf1a58ecae527fc67c87ce4dcb9e73894f64aadfe (patch)
treee89e6440350a6990023b77fd5a0d7e9f5f9c4b28 /drivers/scsi/ata_piix.c
parentd14b50cc60ca465290fcdb3b88e7d5fb684361ed (diff)
[PATCH] ata_piix: fix ghost device probing by honoring PCS present bits
Move out PCS handling from piix_sata_prereset() into piix_sata_present_mask() and use it from newly implemented piix_sata_softreset(). Class codes for devices which are indicated to be absent by PCS are cleared to ATA_DEV_NONE. This fixes ghost device problem reported on ICH6 and 7. This patch moves PCS handling from prereset to softreset, which makes two behavior changes. * perform softreset even when PCS indicates no device * PCS handling is repeated before retrying softresets due to reset failures. Both behavior changes are intended and more consistent with how other drivers behave. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/scsi/ata_piix.c')
-rw-r--r--drivers/scsi/ata_piix.c60
1 files changed, 43 insertions, 17 deletions
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 5e8afc876980..01b3530cf6df 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -531,27 +531,25 @@ static void piix_pata_error_handler(struct ata_port *ap)
531} 531}
532 532
533/** 533/**
534 * piix_sata_prereset - prereset for SATA host controller 534 * piix_sata_present_mask - determine present mask for SATA host controller
535 * @ap: Target port 535 * @ap: Target port
536 * 536 *
537 * Reads and configures SATA PCI device's PCI config register 537 * Reads SATA PCI device's PCI config register Port Configuration
538 * Port Configuration and Status (PCS) to determine port and 538 * and Status (PCS) to determine port and device availability.
539 * device availability. Return -ENODEV to skip reset if no
540 * device is present.
541 * 539 *
542 * LOCKING: 540 * LOCKING:
543 * None (inherited from caller). 541 * None (inherited from caller).
544 * 542 *
545 * RETURNS: 543 * RETURNS:
546 * 0 if device is present, -ENODEV otherwise. 544 * determined present_mask
547 */ 545 */
548static int piix_sata_prereset(struct ata_port *ap) 546static unsigned int piix_sata_present_mask(struct ata_port *ap)
549{ 547{
550 struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); 548 struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
551 struct piix_host_priv *hpriv = ap->host_set->private_data; 549 struct piix_host_priv *hpriv = ap->host_set->private_data;
552 const unsigned int *map = hpriv->map; 550 const unsigned int *map = hpriv->map;
553 int base = 2 * ap->hard_port_no; 551 int base = 2 * ap->hard_port_no;
554 unsigned int present = 0; 552 unsigned int present_mask = 0;
555 int port, i; 553 int port, i;
556 u16 pcs; 554 u16 pcs;
557 555
@@ -564,24 +562,52 @@ static int piix_sata_prereset(struct ata_port *ap)
564 continue; 562 continue;
565 if ((ap->flags & PIIX_FLAG_IGNORE_PCS) || 563 if ((ap->flags & PIIX_FLAG_IGNORE_PCS) ||
566 (pcs & 1 << (hpriv->map_db->present_shift + port))) 564 (pcs & 1 << (hpriv->map_db->present_shift + port)))
567 present = 1; 565 present_mask |= 1 << i;
568 } 566 }
569 567
570 DPRINTK("ata%u: LEAVE, pcs=0x%x present=0x%x\n", 568 DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
571 ap->id, pcs, present); 569 ap->id, pcs, present_mask);
572 570
573 if (!present) { 571 return present_mask;
574 ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); 572}
575 ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; 573
576 return 0; 574/**
575 * piix_sata_softreset - reset SATA host port via ATA SRST
576 * @ap: port to reset
577 * @classes: resulting classes of attached devices
578 *
579 * Reset SATA host port via ATA SRST. On controllers with
580 * reliable PCS present bits, the bits are used to determine
581 * device presence.
582 *
583 * LOCKING:
584 * Kernel thread context (may sleep)
585 *
586 * RETURNS:
587 * 0 on success, -errno otherwise.
588 */
589static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes)
590{
591 unsigned int present_mask;
592 int i, rc;
593
594 present_mask = piix_sata_present_mask(ap);
595
596 rc = ata_std_softreset(ap, classes);
597 if (rc)
598 return rc;
599
600 for (i = 0; i < ATA_MAX_DEVICES; i++) {
601 if (!(present_mask & (1 << i)))
602 classes[i] = ATA_DEV_NONE;
577 } 603 }
578 604
579 return ata_std_prereset(ap); 605 return 0;
580} 606}
581 607
582static void piix_sata_error_handler(struct ata_port *ap) 608static void piix_sata_error_handler(struct ata_port *ap)
583{ 609{
584 ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL, 610 ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL,
585 ata_std_postreset); 611 ata_std_postreset);
586} 612}
587 613