diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/ata_piix.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 5fdf1678d0cc..78659546130c 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
@@ -154,11 +154,13 @@ struct piix_map_db { | |||
154 | 154 | ||
155 | struct piix_host_priv { | 155 | struct piix_host_priv { |
156 | const int *map; | 156 | const int *map; |
157 | u32 saved_iocfg; | ||
157 | void __iomem *sidpr; | 158 | void __iomem *sidpr; |
158 | }; | 159 | }; |
159 | 160 | ||
160 | static int piix_init_one(struct pci_dev *pdev, | 161 | static int piix_init_one(struct pci_dev *pdev, |
161 | const struct pci_device_id *ent); | 162 | const struct pci_device_id *ent); |
163 | static void piix_remove_one(struct pci_dev *pdev); | ||
162 | static int piix_pata_prereset(struct ata_link *link, unsigned long deadline); | 164 | static int piix_pata_prereset(struct ata_link *link, unsigned long deadline); |
163 | static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev); | 165 | static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev); |
164 | static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev); | 166 | static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev); |
@@ -296,7 +298,7 @@ static struct pci_driver piix_pci_driver = { | |||
296 | .name = DRV_NAME, | 298 | .name = DRV_NAME, |
297 | .id_table = piix_pci_tbl, | 299 | .id_table = piix_pci_tbl, |
298 | .probe = piix_init_one, | 300 | .probe = piix_init_one, |
299 | .remove = ata_pci_remove_one, | 301 | .remove = piix_remove_one, |
300 | #ifdef CONFIG_PM | 302 | #ifdef CONFIG_PM |
301 | .suspend = piix_pci_device_suspend, | 303 | .suspend = piix_pci_device_suspend, |
302 | .resume = piix_pci_device_resume, | 304 | .resume = piix_pci_device_resume, |
@@ -610,8 +612,9 @@ static const struct ich_laptop ich_laptop[] = { | |||
610 | static int ich_pata_cable_detect(struct ata_port *ap) | 612 | static int ich_pata_cable_detect(struct ata_port *ap) |
611 | { | 613 | { |
612 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 614 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
615 | struct piix_host_priv *hpriv = ap->host->private_data; | ||
613 | const struct ich_laptop *lap = &ich_laptop[0]; | 616 | const struct ich_laptop *lap = &ich_laptop[0]; |
614 | u8 tmp, mask; | 617 | u8 mask; |
615 | 618 | ||
616 | /* Check for specials - Acer Aspire 5602WLMi */ | 619 | /* Check for specials - Acer Aspire 5602WLMi */ |
617 | while (lap->device) { | 620 | while (lap->device) { |
@@ -625,8 +628,7 @@ static int ich_pata_cable_detect(struct ata_port *ap) | |||
625 | 628 | ||
626 | /* check BIOS cable detect results */ | 629 | /* check BIOS cable detect results */ |
627 | mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; | 630 | mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; |
628 | pci_read_config_byte(pdev, PIIX_IOCFG, &tmp); | 631 | if ((hpriv->saved_iocfg & mask) == 0) |
629 | if ((tmp & mask) == 0) | ||
630 | return ATA_CBL_PATA40; | 632 | return ATA_CBL_PATA40; |
631 | return ATA_CBL_PATA80; | 633 | return ATA_CBL_PATA80; |
632 | } | 634 | } |
@@ -1350,7 +1352,7 @@ static int __devinit piix_init_sidpr(struct ata_host *host) | |||
1350 | return 0; | 1352 | return 0; |
1351 | } | 1353 | } |
1352 | 1354 | ||
1353 | static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) | 1355 | static void piix_iocfg_bit18_quirk(struct ata_host *host) |
1354 | { | 1356 | { |
1355 | static const struct dmi_system_id sysids[] = { | 1357 | static const struct dmi_system_id sysids[] = { |
1356 | { | 1358 | { |
@@ -1367,7 +1369,8 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) | |||
1367 | 1369 | ||
1368 | { } /* terminate list */ | 1370 | { } /* terminate list */ |
1369 | }; | 1371 | }; |
1370 | u32 iocfg; | 1372 | struct pci_dev *pdev = to_pci_dev(host->dev); |
1373 | struct piix_host_priv *hpriv = host->private_data; | ||
1371 | 1374 | ||
1372 | if (!dmi_check_system(sysids)) | 1375 | if (!dmi_check_system(sysids)) |
1373 | return; | 1376 | return; |
@@ -1376,12 +1379,11 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) | |||
1376 | * seem to use it to disable a channel. Clear the bit on the | 1379 | * seem to use it to disable a channel. Clear the bit on the |
1377 | * affected systems. | 1380 | * affected systems. |
1378 | */ | 1381 | */ |
1379 | pci_read_config_dword(pdev, PIIX_IOCFG, &iocfg); | 1382 | if (hpriv->saved_iocfg & (1 << 18)) { |
1380 | if (iocfg & (1 << 18)) { | ||
1381 | dev_printk(KERN_INFO, &pdev->dev, | 1383 | dev_printk(KERN_INFO, &pdev->dev, |
1382 | "applying IOCFG bit18 quirk\n"); | 1384 | "applying IOCFG bit18 quirk\n"); |
1383 | iocfg &= ~(1 << 18); | 1385 | pci_write_config_dword(pdev, PIIX_IOCFG, |
1384 | pci_write_config_dword(pdev, PIIX_IOCFG, iocfg); | 1386 | hpriv->saved_iocfg & ~(1 << 18)); |
1385 | } | 1387 | } |
1386 | } | 1388 | } |
1387 | 1389 | ||
@@ -1430,6 +1432,17 @@ static int __devinit piix_init_one(struct pci_dev *pdev, | |||
1430 | if (rc) | 1432 | if (rc) |
1431 | return rc; | 1433 | return rc; |
1432 | 1434 | ||
1435 | hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); | ||
1436 | if (!hpriv) | ||
1437 | return -ENOMEM; | ||
1438 | |||
1439 | /* Save IOCFG, this will be used for cable detection, quirk | ||
1440 | * detection and restoration on detach. This is necessary | ||
1441 | * because some ACPI implementations mess up cable related | ||
1442 | * bits on _STM. Reported on kernel bz#11879. | ||
1443 | */ | ||
1444 | pci_read_config_dword(pdev, PIIX_IOCFG, &hpriv->saved_iocfg); | ||
1445 | |||
1433 | /* ICH6R may be driven by either ata_piix or ahci driver | 1446 | /* ICH6R may be driven by either ata_piix or ahci driver |
1434 | * regardless of BIOS configuration. Make sure AHCI mode is | 1447 | * regardless of BIOS configuration. Make sure AHCI mode is |
1435 | * off. | 1448 | * off. |
@@ -1441,10 +1454,6 @@ static int __devinit piix_init_one(struct pci_dev *pdev, | |||
1441 | } | 1454 | } |
1442 | 1455 | ||
1443 | /* SATA map init can change port_info, do it before prepping host */ | 1456 | /* SATA map init can change port_info, do it before prepping host */ |
1444 | hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); | ||
1445 | if (!hpriv) | ||
1446 | return -ENOMEM; | ||
1447 | |||
1448 | if (port_flags & ATA_FLAG_SATA) | 1457 | if (port_flags & ATA_FLAG_SATA) |
1449 | hpriv->map = piix_init_sata_map(pdev, port_info, | 1458 | hpriv->map = piix_init_sata_map(pdev, port_info, |
1450 | piix_map_db_table[ent->driver_data]); | 1459 | piix_map_db_table[ent->driver_data]); |
@@ -1463,7 +1472,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev, | |||
1463 | } | 1472 | } |
1464 | 1473 | ||
1465 | /* apply IOCFG bit18 quirk */ | 1474 | /* apply IOCFG bit18 quirk */ |
1466 | piix_iocfg_bit18_quirk(pdev); | 1475 | piix_iocfg_bit18_quirk(host); |
1467 | 1476 | ||
1468 | /* On ICH5, some BIOSen disable the interrupt using the | 1477 | /* On ICH5, some BIOSen disable the interrupt using the |
1469 | * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. | 1478 | * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. |
@@ -1488,6 +1497,16 @@ static int __devinit piix_init_one(struct pci_dev *pdev, | |||
1488 | return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht); | 1497 | return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht); |
1489 | } | 1498 | } |
1490 | 1499 | ||
1500 | static void piix_remove_one(struct pci_dev *pdev) | ||
1501 | { | ||
1502 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
1503 | struct piix_host_priv *hpriv = host->private_data; | ||
1504 | |||
1505 | pci_write_config_dword(pdev, PIIX_IOCFG, hpriv->saved_iocfg); | ||
1506 | |||
1507 | ata_pci_remove_one(pdev); | ||
1508 | } | ||
1509 | |||
1491 | static int __init piix_init(void) | 1510 | static int __init piix_init(void) |
1492 | { | 1511 | { |
1493 | int rc; | 1512 | int rc; |