|
@@ -154,11 +154,13 @@ struct piix_map_db {
|
|
|
|
|
|
struct piix_host_priv {
|
|
|
const int *map;
|
|
|
+ u32 saved_iocfg;
|
|
|
void __iomem *sidpr;
|
|
|
};
|
|
|
|
|
|
static int piix_init_one(struct pci_dev *pdev,
|
|
|
const struct pci_device_id *ent);
|
|
|
+static void piix_remove_one(struct pci_dev *pdev);
|
|
|
static int piix_pata_prereset(struct ata_link *link, unsigned long deadline);
|
|
|
static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);
|
|
|
static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
|
|
@@ -296,7 +298,7 @@ static struct pci_driver piix_pci_driver = {
|
|
|
.name = DRV_NAME,
|
|
|
.id_table = piix_pci_tbl,
|
|
|
.probe = piix_init_one,
|
|
|
- .remove = ata_pci_remove_one,
|
|
|
+ .remove = piix_remove_one,
|
|
|
#ifdef CONFIG_PM
|
|
|
.suspend = piix_pci_device_suspend,
|
|
|
.resume = piix_pci_device_resume,
|
|
@@ -610,8 +612,9 @@ static const struct ich_laptop ich_laptop[] = {
|
|
|
static int ich_pata_cable_detect(struct ata_port *ap)
|
|
|
{
|
|
|
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
|
|
+ struct piix_host_priv *hpriv = ap->host->private_data;
|
|
|
const struct ich_laptop *lap = &ich_laptop[0];
|
|
|
- u8 tmp, mask;
|
|
|
+ u8 mask;
|
|
|
|
|
|
/* Check for specials - Acer Aspire 5602WLMi */
|
|
|
while (lap->device) {
|
|
@@ -625,8 +628,7 @@ static int ich_pata_cable_detect(struct ata_port *ap)
|
|
|
|
|
|
/* check BIOS cable detect results */
|
|
|
mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
|
|
|
- pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
|
|
|
- if ((tmp & mask) == 0)
|
|
|
+ if ((hpriv->saved_iocfg & mask) == 0)
|
|
|
return ATA_CBL_PATA40;
|
|
|
return ATA_CBL_PATA80;
|
|
|
}
|
|
@@ -1350,7 +1352,7 @@ static int __devinit piix_init_sidpr(struct ata_host *host)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
|
|
|
+static void piix_iocfg_bit18_quirk(struct ata_host *host)
|
|
|
{
|
|
|
static const struct dmi_system_id sysids[] = {
|
|
|
{
|
|
@@ -1367,7 +1369,8 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
|
|
|
|
|
|
{ } /* terminate list */
|
|
|
};
|
|
|
- u32 iocfg;
|
|
|
+ struct pci_dev *pdev = to_pci_dev(host->dev);
|
|
|
+ struct piix_host_priv *hpriv = host->private_data;
|
|
|
|
|
|
if (!dmi_check_system(sysids))
|
|
|
return;
|
|
@@ -1376,12 +1379,11 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
|
|
|
* seem to use it to disable a channel. Clear the bit on the
|
|
|
* affected systems.
|
|
|
*/
|
|
|
- pci_read_config_dword(pdev, PIIX_IOCFG, &iocfg);
|
|
|
- if (iocfg & (1 << 18)) {
|
|
|
+ if (hpriv->saved_iocfg & (1 << 18)) {
|
|
|
dev_printk(KERN_INFO, &pdev->dev,
|
|
|
"applying IOCFG bit18 quirk\n");
|
|
|
- iocfg &= ~(1 << 18);
|
|
|
- pci_write_config_dword(pdev, PIIX_IOCFG, iocfg);
|
|
|
+ pci_write_config_dword(pdev, PIIX_IOCFG,
|
|
|
+ hpriv->saved_iocfg & ~(1 << 18));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1430,6 +1432,17 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
+ hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
|
|
|
+ if (!hpriv)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ /* Save IOCFG, this will be used for cable detection, quirk
|
|
|
+ * detection and restoration on detach. This is necessary
|
|
|
+ * because some ACPI implementations mess up cable related
|
|
|
+ * bits on _STM. Reported on kernel bz#11879.
|
|
|
+ */
|
|
|
+ pci_read_config_dword(pdev, PIIX_IOCFG, &hpriv->saved_iocfg);
|
|
|
+
|
|
|
/* ICH6R may be driven by either ata_piix or ahci driver
|
|
|
* regardless of BIOS configuration. Make sure AHCI mode is
|
|
|
* off.
|
|
@@ -1441,10 +1454,6 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
|
|
|
}
|
|
|
|
|
|
/* SATA map init can change port_info, do it before prepping host */
|
|
|
- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
|
|
|
- if (!hpriv)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
if (port_flags & ATA_FLAG_SATA)
|
|
|
hpriv->map = piix_init_sata_map(pdev, port_info,
|
|
|
piix_map_db_table[ent->driver_data]);
|
|
@@ -1463,7 +1472,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
|
|
|
}
|
|
|
|
|
|
/* apply IOCFG bit18 quirk */
|
|
|
- piix_iocfg_bit18_quirk(pdev);
|
|
|
+ piix_iocfg_bit18_quirk(host);
|
|
|
|
|
|
/* On ICH5, some BIOSen disable the interrupt using the
|
|
|
* PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
|
|
@@ -1488,6 +1497,16 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
|
|
|
return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
|
|
|
}
|
|
|
|
|
|
+static void piix_remove_one(struct pci_dev *pdev)
|
|
|
+{
|
|
|
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
|
|
|
+ struct piix_host_priv *hpriv = host->private_data;
|
|
|
+
|
|
|
+ pci_write_config_dword(pdev, PIIX_IOCFG, hpriv->saved_iocfg);
|
|
|
+
|
|
|
+ ata_pci_remove_one(pdev);
|
|
|
+}
|
|
|
+
|
|
|
static int __init piix_init(void)
|
|
|
{
|
|
|
int rc;
|