diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/ata_piix.c | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 94b1261a259..bf41dd3a35d 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -144,8 +144,13 @@ struct piix_map_db { const int map[][4]; }; +struct piix_host_priv { + const int *map; +}; + static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static void piix_host_stop(struct ata_host_set *host_set); 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); static void piix_pata_error_handler(struct ata_port *ap); @@ -254,7 +259,7 @@ static const struct ata_port_operations piix_pata_ops = { .port_start = ata_port_start, .port_stop = ata_port_stop, - .host_stop = ata_host_stop, + .host_stop = piix_host_stop, }; static const struct ata_port_operations piix_sata_ops = { @@ -284,10 +289,10 @@ static const struct ata_port_operations piix_sata_ops = { .port_start = ata_port_start, .port_stop = ata_port_stop, - .host_stop = ata_host_stop, + .host_stop = piix_host_stop, }; -static struct piix_map_db ich5_map_db = { +static const struct piix_map_db ich5_map_db = { .mask = 0x7, .map = { /* PM PS SM SS MAP */ @@ -302,7 +307,7 @@ static struct piix_map_db ich5_map_db = { }, }; -static struct piix_map_db ich6_map_db = { +static const struct piix_map_db ich6_map_db = { .mask = 0x3, .map = { /* PM PS SM SS MAP */ @@ -313,7 +318,7 @@ static struct piix_map_db ich6_map_db = { }, }; -static struct piix_map_db ich6m_map_db = { +static const struct piix_map_db ich6m_map_db = { .mask = 0x3, .map = { /* PM PS SM SS MAP */ @@ -324,6 +329,14 @@ static struct piix_map_db ich6m_map_db = { }, }; +static const struct piix_map_db *piix_map_db_table[] = { + [ich5_sata] = &ich5_map_db, + [esb_sata] = &ich5_map_db, + [ich6_sata] = &ich6_map_db, + [ich6_sata_ahci] = &ich6_map_db, + [ich6m_sata_ahci] = &ich6m_map_db, +}; + static struct ata_port_info piix_port_info[] = { /* piix4_pata */ { @@ -362,7 +375,6 @@ static struct ata_port_info piix_port_info[] = { .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, - .private_data = &ich5_map_db, }, /* i6300esb_sata */ @@ -374,7 +386,6 @@ static struct ata_port_info piix_port_info[] = { .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, - .private_data = &ich5_map_db, }, /* ich6_sata */ @@ -386,7 +397,6 @@ static struct ata_port_info piix_port_info[] = { .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, - .private_data = &ich6_map_db, }, /* ich6_sata_ahci */ @@ -399,7 +409,6 @@ static struct ata_port_info piix_port_info[] = { .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, - .private_data = &ich6_map_db, }, /* ich6m_sata_ahci */ @@ -412,7 +421,6 @@ static struct ata_port_info piix_port_info[] = { .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, - .private_data = &ich6m_map_db, }, }; @@ -508,7 +516,8 @@ static void piix_pata_error_handler(struct ata_port *ap) static int piix_sata_prereset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); - const unsigned int *map = ap->host_set->private_data; + struct piix_host_priv *hpriv = ap->host_set->private_data; + const unsigned int *map = hpriv->map; int base = 2 * ap->hard_port_no; unsigned int present_mask = 0; int port, i; @@ -762,9 +771,10 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) } static void __devinit piix_init_sata_map(struct pci_dev *pdev, - struct ata_port_info *pinfo) + struct ata_port_info *pinfo, + const struct piix_map_db *map_db) { - struct piix_map_db *map_db = pinfo[0].private_data; + struct piix_host_priv *hpriv = pinfo[0].private_data; const unsigned int *map; int i, invalid_map = 0; u8 map_value; @@ -805,8 +815,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, dev_printk(KERN_ERR, &pdev->dev, "invalid MAP value %u\n", map_value); - pinfo[0].private_data = (void *)map; - pinfo[1].private_data = (void *)map; + hpriv->map = map; } /** @@ -829,6 +838,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; struct ata_port_info port_info[2]; struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] }; + struct piix_host_priv *hpriv; unsigned long host_flags; if (!printed_version++) @@ -839,8 +849,14 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (!in_module_init) return -ENODEV; + hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL); + if (!hpriv) + return -ENOMEM; + port_info[0] = piix_port_info[ent->driver_data]; port_info[1] = piix_port_info[ent->driver_data]; + port_info[0].private_data = hpriv; + port_info[1].private_data = hpriv; host_flags = port_info[0].host_flags; @@ -856,7 +872,8 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) /* Initialize SATA map */ if (host_flags & ATA_FLAG_SATA) - piix_init_sata_map(pdev, port_info); + piix_init_sata_map(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. @@ -879,6 +896,13 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) return ata_pci_init_one(pdev, ppinfo, 2); } +static void piix_host_stop(struct ata_host_set *host_set) +{ + if (host_set->next == NULL) + kfree(host_set->private_data); + ata_host_stop(host_set); +} + static int __init piix_init(void) { int rc; |