diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 2d20caf..46f7c9b 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -553,15 +553,42 @@ static unsigned int piix_sata_present_ma { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); struct piix_host_priv *hpriv = ap->host_set->private_data; + const struct piix_map_db *map_db = hpriv->map_db; const unsigned int *map = hpriv->map; int base = 2 * ap->hard_port_no; unsigned int present_mask = 0; int port, i; - u16 pcs; + u16 pcs, new_pcs; pci_read_config_word(pdev, ICH5_PCS, &pcs); DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); + new_pcs = pcs | map_db->port_enable; + + if (pcs != new_pcs) { + u16 old_pcs = pcs; + + for (i = 0; i < 10; i++) { + pci_write_config_word(pdev, ICH5_PCS, new_pcs); + msleep(150); + pci_read_config_word(pdev, ICH5_PCS, &pcs); + + new_pcs = pcs | map_db->port_enable; + if (pcs == new_pcs) + break; + } + + if (pcs == new_pcs) + ata_port_printk(ap, KERN_INFO, "updated PCS from " + "0x%x to 0x%x (%d tries)\n", + old_pcs, pcs, i); + else + ata_port_printk(ap, KERN_WARNING, + "failed to update PCS after %d tries, " + "old=0x%x cur=0x%x new=0x%x\n", + i, old_pcs, pcs, new_pcs); + } + for (i = 0; i < 2; i++) { port = map[base + i]; if (port < 0) @@ -816,35 +843,6 @@ static int __devinit piix_check_450nx_er return no_piix_dma; } -static void __devinit piix_init_pcs(struct pci_dev *pdev, - struct ata_port_info *pinfo, - const struct piix_map_db *map_db) -{ - u16 pcs, new_pcs; - - pci_read_config_word(pdev, ICH5_PCS, &pcs); - - new_pcs = pcs | map_db->port_enable; - - if (new_pcs != pcs) { - DPRINTK("updating PCS from 0x%x to 0x%x\n", pcs, new_pcs); - pci_write_config_word(pdev, ICH5_PCS, new_pcs); - msleep(150); - } - - if (force_pcs == 1) { - dev_printk(KERN_INFO, &pdev->dev, - "force ignoring PCS (0x%x)\n", new_pcs); - pinfo[0].host_flags |= PIIX_FLAG_IGNORE_PCS; - pinfo[1].host_flags |= PIIX_FLAG_IGNORE_PCS; - } else if (force_pcs == 2) { - dev_printk(KERN_INFO, &pdev->dev, - "force honoring PCS (0x%x)\n", new_pcs); - pinfo[0].host_flags &= ~PIIX_FLAG_IGNORE_PCS; - pinfo[1].host_flags &= ~PIIX_FLAG_IGNORE_PCS; - } -} - static void __devinit piix_init_sata_map(struct pci_dev *pdev, struct ata_port_info *pinfo, const struct piix_map_db *map_db) @@ -893,6 +891,17 @@ static void __devinit piix_init_sata_map hpriv->map = map; hpriv->map_db = map_db; + + /* handle force_pcs module parameter */ + if (force_pcs == 1) { + dev_printk(KERN_INFO, &pdev->dev, "force ignoring PCS\n"); + pinfo[0].host_flags |= PIIX_FLAG_IGNORE_PCS; + pinfo[1].host_flags |= PIIX_FLAG_IGNORE_PCS; + } else if (force_pcs == 2) { + dev_printk(KERN_INFO, &pdev->dev, "force honoring PCS\n"); + pinfo[0].host_flags &= ~PIIX_FLAG_IGNORE_PCS; + pinfo[1].host_flags &= ~PIIX_FLAG_IGNORE_PCS; + } } /** @@ -948,12 +957,9 @@ static int piix_init_one (struct pci_dev } /* Initialize SATA map */ - if (host_flags & ATA_FLAG_SATA) { + if (host_flags & ATA_FLAG_SATA) piix_init_sata_map(pdev, port_info, piix_map_db_table[ent->driver_data]); - piix_init_pcs(pdev, port_info, - piix_map_db_table[ent->driver_data]); - } /* On ICH5, some BIOSen disable the interrupt using the * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.