diff options
Diffstat (limited to 'drivers/ata/ata_piix.c')
| -rw-r--r-- | drivers/ata/ata_piix.c | 1105 |
1 files changed, 664 insertions, 441 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index e6b4606e36b..893e30e9a9e 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1,7 +1,7 @@ /* * ata_piix.c - Intel PATA/SATA controllers * - * Maintained by: Jeff Garzik <jgarzik@pobox.com> + * Maintained by: Tejun Heo <tj@kernel.org> * Please ALWAYS copy linux-ide@vger.kernel.org * on emails. * @@ -14,7 +14,7 @@ * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> - * Copyright (C) 2003 Red Hat Inc <alan@redhat.com> + * Copyright (C) 2003 Red Hat Inc * * * This program is free software; you can redistribute it and/or modify @@ -38,16 +38,16 @@ * Hardware documentation available at http://developer.intel.com/ * * Documentation - * Publically available from Intel web site. Errata documentation - * is also publically available. As an aide to anyone hacking on this + * Publicly available from Intel web site. Errata documentation + * is also publicly available. As an aide to anyone hacking on this * driver the list of errata that are relevant is below, going back to * PIIX4. Older device documentation is now a bit tricky to find. * - * The chipsets all follow very much the same design. The orginal Triton - * series chipsets do _not_ support independant device timings, but this + * The chipsets all follow very much the same design. The original Triton + * series chipsets do _not_ support independent device timings, but this * is fixed in Triton II. With the odd mobile exception the chips then * change little except in gaining more modes until SATA arrives. This - * driver supports only the chips with independant timing (that is those + * driver supports only the chips with independent timing (that is those * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix * for the early chip drivers. * @@ -72,6 +72,7 @@ * ICH2 spec c #20 - IDE PRD must not cross a 64K boundary * and must be dword aligned * ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3 + * ICH7 errata #16 - MWDMA1 timings are incorrect * * Should have been BIOS fixed: * 450NX: errata #19 - DMA hangs on old 450NX @@ -89,16 +90,17 @@ #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/gfp.h> #include <scsi/scsi_host.h> #include <linux/libata.h> #include <linux/dmi.h> #define DRV_NAME "ata_piix" -#define DRV_VERSION "2.12" +#define DRV_VERSION "2.13" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ - ICH5_PMR = 0x90, /* port mapping register */ + ICH5_PMR = 0x90, /* address map register */ ICH5_PCS = 0x92, /* port control and status */ PIIX_SIDPR_BAR = 5, PIIX_SIDPR_LEN = 16, @@ -111,6 +113,8 @@ enum { PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS, PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, + PIIX_FLAG_PIO16 = (1 << 30), /*support 16bit PIO only*/ + PIIX_80C_PRI = (1 << 5) | (1 << 4), PIIX_80C_SEC = (1 << 7) | (1 << 6), @@ -120,7 +124,7 @@ enum { P2 = 2, /* port 2 */ P3 = 3, /* port 3 */ IDE = -1, /* IDE */ - NA = -2, /* not avaliable */ + NA = -2, /* not available */ RV = -3, /* reserved */ PIIX_AHCI_DEVICE = 6, @@ -136,6 +140,7 @@ enum piix_controller_ids { ich_pata_33, /* ICH up to UDMA 33 only */ ich_pata_66, /* ICH up to 66 Mhz */ ich_pata_100, /* ICH up to UDMA 100 */ + ich_pata_100_nomwdma1, /* ICH up to UDMA 100 but with no MWDMA1*/ ich5_sata, ich6_sata, ich6m_sata, @@ -144,6 +149,9 @@ enum piix_controller_ids { ich8m_apple_sata, /* locks up on second port enable */ tolapai_sata, piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */ + ich8_sata_snb, + ich8_2port_sata_snb, + ich8_2port_sata_byt, }; struct piix_map_db { @@ -154,24 +162,10 @@ 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 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); -static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev); -static int ich_pata_cable_detect(struct ata_port *ap); -static u8 piix_vmw_bmdma_status(struct ata_port *ap); -static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val); -static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val); -#ifdef CONFIG_PM -static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); -static int piix_pci_device_resume(struct pci_dev *pdev); -#endif - static unsigned int in_module_init = 1; static const struct pci_device_id piix_pci_tbl[] = { @@ -200,6 +194,8 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* Intel ICH3 (E7500/1) UDMA 100 */ { 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, + /* Intel ICH4-L */ + { 0x8086, 0x24C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */ { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, @@ -212,14 +208,12 @@ static const struct pci_device_id piix_pci_tbl[] = { /* ICH6 (and 6) (i915) UDMA 100 */ { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* ICH7/7-R (i945, i975) UDMA 100*/ - { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, + { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 }, + { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 }, /* ICH8 Mobile PATA Controller */ { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* NOTE: The following PCI ids must be kept in sync with the - * list in drivers/pci/quirks.c. - */ + /* SATA ports */ /* 82801EB (ICH5) */ { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, @@ -239,7 +233,7 @@ static const struct pci_device_id piix_pci_tbl[] = { PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich6m_sata }, /* 82801GB/GR/GH (ICH7, identical to ICH6) */ { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, - /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ + /* 82801GBM/GHM (ICH7M, identical to ICH6M) */ { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata }, /* Enterprise Southbridge 2 (631xESB/632xESB) */ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, @@ -278,60 +272,78 @@ static const struct pci_device_id piix_pci_tbl[] = { /* SATA Controller IDE (PCH) */ { 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PCH) */ { 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (PCH) */ { 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (PCH) */ { 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (CPT) */ + { 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (CPT) */ + { 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (CPT) */ + { 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (CPT) */ + { 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PBG) */ + { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (PBG) */ + { 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Panther Point) */ + { 0x8086, 0x1e09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Lynx Point) */ + { 0x8086, 0x8c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Lynx Point) */ + { 0x8086, 0x8c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Lynx Point) */ + { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, + /* SATA Controller IDE (Lynx Point) */ + { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Lynx Point-LP) */ + { 0x8086, 0x9c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Lynx Point-LP) */ + { 0x8086, 0x9c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Lynx Point-LP) */ + { 0x8086, 0x9c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Lynx Point-LP) */ + { 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (DH89xxCC) */ + { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d68, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (BayTrail) */ + { 0x8086, 0x0F20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, + { 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, + /* SATA Controller IDE (Coleto Creek) */ + { 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, { } /* terminate list */ }; -static struct pci_driver piix_pci_driver = { - .name = DRV_NAME, - .id_table = piix_pci_tbl, - .probe = piix_init_one, - .remove = ata_pci_remove_one, -#ifdef CONFIG_PM - .suspend = piix_pci_device_suspend, - .resume = piix_pci_device_resume, -#endif -}; - -static struct scsi_host_template piix_sht = { - ATA_BMDMA_SHT(DRV_NAME), -}; - -static struct ata_port_operations piix_pata_ops = { - .inherits = &ata_bmdma_port_ops, - .cable_detect = ata_cable_40wire, - .set_piomode = piix_set_piomode, - .set_dmamode = piix_set_dmamode, - .prereset = piix_pata_prereset, -}; - -static struct ata_port_operations piix_vmw_ops = { - .inherits = &piix_pata_ops, - .bmdma_status = piix_vmw_bmdma_status, -}; - -static struct ata_port_operations ich_pata_ops = { - .inherits = &piix_pata_ops, - .cable_detect = ich_pata_cable_detect, - .set_dmamode = ich_set_dmamode, -}; - -static struct ata_port_operations piix_sata_ops = { - .inherits = &ata_bmdma_port_ops, -}; - -static struct ata_port_operations piix_sidpr_sata_ops = { - .inherits = &piix_sata_ops, - .hardreset = sata_std_hardreset, - .scr_read = piix_sidpr_scr_read, - .scr_write = piix_sidpr_scr_write, -}; - static const struct piix_map_db ich5_map_db = { .mask = 0x7, .port_enable = 0x3, @@ -433,125 +445,9 @@ static const struct piix_map_db *piix_map_db_table[] = { [ich8_2port_sata] = &ich8_2port_map_db, [ich8m_apple_sata] = &ich8m_apple_map_db, [tolapai_sata] = &tolapai_map_db, -}; - -static struct ata_port_info piix_port_info[] = { - [piix_pata_mwdma] = /* PIIX3 MWDMA only */ - { - .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ - .port_ops = &piix_pata_ops, - }, - - [piix_pata_33] = /* PIIX4 at 33MHz */ - { - .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ - .udma_mask = ATA_UDMA_MASK_40C, - .port_ops = &piix_pata_ops, - }, - - [ich_pata_33] = /* ICH0 - ICH at 33Mhz*/ - { - .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* Check: maybe 0x07 */ - .udma_mask = ATA_UDMA2, /* UDMA33 */ - .port_ops = &ich_pata_ops, - }, - - [ich_pata_66] = /* ICH controllers up to 66MHz */ - { - .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ - .udma_mask = ATA_UDMA4, - .port_ops = &ich_pata_ops, - }, - - [ich_pata_100] = - { - .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ - .port_ops = &ich_pata_ops, - }, - - [ich5_sata] = - { - .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, - - [ich6_sata] = - { - .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, - - [ich6m_sata] = - { - .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, - - [ich8_sata] = - { - .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, - - [ich8_2port_sata] = - { - .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, - - [tolapai_sata] = - { - .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, - - [ich8m_apple_sata] = - { - .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, - - [piix_pata_vmw] = - { - .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ - .udma_mask = ATA_UDMA_MASK_40C, - .port_ops = &piix_vmw_ops, - }, - + [ich8_sata_snb] = &ich8_map_db, + [ich8_2port_sata_snb] = &ich8_2port_map_db, + [ich8_2port_sata_byt] = &ich8_2port_map_db, }; static struct pci_bits piix_enable_bits[] = { @@ -580,16 +476,29 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ + { 0x27DF, 0x1028, 0x02b0 }, /* ICH7 on unknown Dell */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ + { 0x27DF, 0x103C, 0x361a }, /* ICH7 on unknown HP */ + { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */ + { 0x27DF, 0x152D, 0x0778 }, /* ICH7 on unknown Intel */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */ { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ + { 0x27df, 0x104d, 0x900e }, /* ICH7 on Sony TZ-90 */ /* end marker */ { 0, } }; +static int piix_port_start(struct ata_port *ap) +{ + if (!(ap->flags & PIIX_FLAG_PIO16)) + ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE; + + return ata_bmdma_port_start(ap); +} + /** * ich_pata_cable_detect - Probe host controller cable detect info * @ap: Port for which cable detect info is desired @@ -604,10 +513,11 @@ 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 */ + /* Check for specials */ while (lap->device) { if (lap->device == pdev->device && lap->subvendor == pdev->subsystem_vendor && @@ -619,8 +529,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; } @@ -643,21 +552,13 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline) return ata_sff_prereset(link, deadline); } -/** - * piix_set_piomode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: um - * - * Set PIO mode for device, in host controller PCI config space. - * - * LOCKING: - * None (inherited from caller). - */ +static DEFINE_SPINLOCK(piix_lock); -static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) +static void piix_set_timings(struct ata_port *ap, struct ata_device *adev, + u8 pio) { - unsigned int pio = adev->pio_mode - XFER_PIO_0; struct pci_dev *dev = to_pci_dev(ap->host->dev); + unsigned long flags; unsigned int is_slave = (adev->devno != 0); unsigned int master_port= ap->port_no ? 0x42 : 0x40; unsigned int slave_port = 0x44; @@ -682,10 +583,18 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) control |= 1; /* TIME1 enable */ if (ata_pio_need_iordy(adev)) control |= 2; /* IE enable */ - /* Intel specifies that the PPE functionality is for disk only */ if (adev->class == ATA_DEV_ATA) control |= 4; /* PPE enable */ + /* + * If the drive MWDMA is faster than it can do PIO then + * we must force PIO into PIO0 + */ + if (adev->pio_mode < XFER_PIO_0 + pio) + /* Enable DMA timing only */ + control |= 8; /* PIO cycles in PIO0 */ + + spin_lock_irqsave(&piix_lock, flags); /* PIO configuration clears DTE unconditionally. It will be * programmed in set_dmamode which is guaranteed to be called @@ -695,8 +604,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) if (is_slave) { /* clear TIME1|IE1|PPE1|DTE1 */ master_data &= 0xff0f; - /* Enable SITRE (separate slave timing register) */ - master_data |= 0x4000; /* enable PPE1, IE1 and TIME1 as needed */ master_data |= (control << 4); pci_read_config_byte(dev, slave_port, &slave_data); @@ -714,6 +621,9 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) (timings[pio][0] << 12) | (timings[pio][1] << 8); } + + /* Enable SITRE (separate slave timing register) */ + master_data |= 0x4000; pci_write_config_word(dev, master_port, master_data); if (is_slave) pci_write_config_byte(dev, slave_port, slave_data); @@ -726,13 +636,30 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); pci_write_config_byte(dev, 0x48, udma_enable); } + + spin_unlock_irqrestore(&piix_lock, flags); +} + +/** + * piix_set_piomode - Initialize host controller PATA PIO timings + * @ap: Port whose timings we are configuring + * @adev: Drive in question + * + * Set PIO mode for device, in host controller PCI config space. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ + piix_set_timings(ap, adev, adev->pio_mode - XFER_PIO_0); } /** * do_pata_set_dmamode - Initialize host controller PATA PIO timings * @ap: Port whose timings we are configuring * @adev: Drive in question - * @udma: udma mode, 0 - 6 * @isich: set if the chip is an ICH device * * Set UDMA mode for device, in host controller PCI config space. @@ -744,29 +671,21 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich) { struct pci_dev *dev = to_pci_dev(ap->host->dev); - u8 master_port = ap->port_no ? 0x42 : 0x40; - u16 master_data; + unsigned long flags; u8 speed = adev->dma_mode; int devid = adev->devno + 2 * ap->port_no; u8 udma_enable = 0; - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - pci_read_config_word(dev, master_port, &master_data); - if (ap->udma_mask) - pci_read_config_byte(dev, 0x48, &udma_enable); - if (speed >= XFER_UDMA_0) { - unsigned int udma = adev->dma_mode - XFER_UDMA_0; + unsigned int udma = speed - XFER_UDMA_0; u16 udma_timing; u16 ideconf; int u_clock, u_speed; + spin_lock_irqsave(&piix_lock, flags); + + pci_read_config_byte(dev, 0x48, &udma_enable); + /* * UDMA is handled by a combination of clock switching and * selection of dividers @@ -799,54 +718,21 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in performance (WR_PingPong_En) */ pci_write_config_word(dev, 0x54, ideconf); } + + pci_write_config_byte(dev, 0x48, udma_enable); + + spin_unlock_irqrestore(&piix_lock, flags); } else { - /* - * MWDMA is driven by the PIO timings. We must also enable - * IORDY unconditionally along with TIME1. PPE has already - * been set when the PIO timing was set. - */ - unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; - unsigned int control; - u8 slave_data; + /* MWDMA is driven by the PIO timings. */ + unsigned int mwdma = speed - XFER_MW_DMA_0; const unsigned int needed_pio[3] = { XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 }; int pio = needed_pio[mwdma] - XFER_PIO_0; - control = 3; /* IORDY|TIME1 */ - - /* If the drive MWDMA is faster than it can do PIO then - we must force PIO into PIO0 */ - - if (adev->pio_mode < needed_pio[mwdma]) - /* Enable DMA timing only */ - control |= 8; /* PIO cycles in PIO0 */ - - if (adev->devno) { /* Slave */ - master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ - master_data |= control << 4; - pci_read_config_byte(dev, 0x44, &slave_data); - slave_data &= (ap->port_no ? 0x0f : 0xf0); - /* Load the matching timing */ - slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); - pci_write_config_byte(dev, 0x44, slave_data); - } else { /* Master */ - master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY - and master timing bits */ - master_data |= control; - master_data |= - (timings[pio][0] << 12) | - (timings[pio][1] << 8); - } - - if (ap->udma_mask) { - udma_enable &= ~(1 << devid); - pci_write_config_word(dev, master_port, master_data); - } + /* XFER_PIO_0 is never used currently */ + piix_set_timings(ap, adev, pio); } - /* Don't scribble on 0x48 if the controller does not support UDMA */ - if (ap->udma_mask) - pci_write_config_byte(dev, 0x48, udma_enable); } /** @@ -885,23 +771,9 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev) * Serial ATA Index/Data Pair Superset Registers access * * Beginning from ICH8, there's a sane way to access SCRs using index - * and data register pair located at BAR5. This creates an - * interesting problem of mapping two SCRs to one port. - * - * Although they have separate SCRs, the master and slave aren't - * independent enough to be treated as separate links - e.g. softreset - * resets both. Also, there's no protocol defined for hard resetting - * singled device sharing the virtual port (no defined way to acquire - * device signature). This is worked around by merging the SCR values - * into one sensible value and requesting follow-up SRST after - * hardreset. - * - * SCR merging is perfomed in nibbles which is the unit contents in - * SCRs are organized. If two values are equal, the value is used. - * When they differ, merge table which lists precedence of possible - * values is consulted and the first match or the last entry when - * nothing matches is used. When there's no merge table for the - * specific nibble, value from the first port is used. + * and data register pair located at BAR5 which means that we have + * separate SCRs for master and slave. This is handled using libata + * slave_link facility. */ static const int piix_sidx_map[] = { [SCR_STATUS] = 0, @@ -909,124 +781,56 @@ static const int piix_sidx_map[] = { [SCR_CONTROL] = 1, }; -static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg) +static void piix_sidpr_sel(struct ata_link *link, unsigned int reg) { - struct ata_port *ap = dev->link->ap; + struct ata_port *ap = link->ap; struct piix_host_priv *hpriv = ap->host->private_data; - iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg], + iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg], hpriv->sidpr + PIIX_SIDPR_IDX); } -static int piix_sidpr_read(struct ata_device *dev, unsigned int reg) -{ - struct piix_host_priv *hpriv = dev->link->ap->host->private_data; - - piix_sidpr_sel(dev, reg); - return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); -} - -static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val) +static int piix_sidpr_scr_read(struct ata_link *link, + unsigned int reg, u32 *val) { - struct piix_host_priv *hpriv = dev->link->ap->host->private_data; + struct piix_host_priv *hpriv = link->ap->host->private_data; - piix_sidpr_sel(dev, reg); - iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); -} - -static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl) -{ - u32 val = 0; - int i, mi; - - for (i = 0, mi = 0; i < 32 / 4; i++) { - u8 c0 = (val0 >> (i * 4)) & 0xf; - u8 c1 = (val1 >> (i * 4)) & 0xf; - u8 merged = c0; - const int *cur; - - /* if no merge preference, assume the first value */ - cur = merge_tbl[mi]; - if (!cur) - goto done; - mi++; - - /* if two values equal, use it */ - if (c0 == c1) - goto done; - - /* choose the first match or the last from the merge table */ - while (*cur != -1) { - if (c0 == *cur || c1 == *cur) - break; - cur++; - } - if (*cur == -1) - cur--; - merged = *cur; - done: - val |= merged << (i * 4); - } + if (reg >= ARRAY_SIZE(piix_sidx_map)) + return -EINVAL; - return val; + piix_sidpr_sel(link, reg); + *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); + return 0; } -static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val) +static int piix_sidpr_scr_write(struct ata_link *link, + unsigned int reg, u32 val) { - const int * const sstatus_merge_tbl[] = { - /* DET */ (const int []){ 1, 3, 0, 4, 3, -1 }, - /* SPD */ (const int []){ 2, 1, 0, -1 }, - /* IPM */ (const int []){ 6, 2, 1, 0, -1 }, - NULL, - }; - const int * const scontrol_merge_tbl[] = { - /* DET */ (const int []){ 1, 0, 4, 0, -1 }, - /* SPD */ (const int []){ 0, 2, 1, 0, -1 }, - /* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 }, - NULL, - }; - u32 v0, v1; + struct piix_host_priv *hpriv = link->ap->host->private_data; if (reg >= ARRAY_SIZE(piix_sidx_map)) return -EINVAL; - if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) { - *val = piix_sidpr_read(&ap->link.device[0], reg); - return 0; - } - - v0 = piix_sidpr_read(&ap->link.device[0], reg); - v1 = piix_sidpr_read(&ap->link.device[1], reg); - - switch (reg) { - case SCR_STATUS: - *val = piix_merge_scr(v0, v1, sstatus_merge_tbl); - break; - case SCR_ERROR: - *val = v0 | v1; - break; - case SCR_CONTROL: - *val = piix_merge_scr(v0, v1, scontrol_merge_tbl); - break; - } - + piix_sidpr_sel(link, reg); + iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); return 0; } -static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val) +static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, + unsigned hints) { - if (reg >= ARRAY_SIZE(piix_sidx_map)) - return -EINVAL; - - piix_sidpr_write(&ap->link.device[0], reg, val); + return sata_link_scr_lpm(link, policy, false); +} - if (ap->flags & ATA_FLAG_SLAVE_POSS) - piix_sidpr_write(&ap->link.device[1], reg, val); +static bool piix_irq_check(struct ata_port *ap) +{ + if (unlikely(!ap->ioaddr.bmdma_addr)) + return false; - return 0; + return ap->ops->bmdma_status(ap) & ATA_DMA_INTR; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int piix_broken_suspend(void) { static const struct dmi_system_id sysids[] = { @@ -1136,12 +940,26 @@ static int piix_broken_suspend(void) }, }, { + .ident = "Satellite Pro A120", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite Pro A120"), + }, + }, + { .ident = "Portege M500", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M500"), }, }, + { + .ident = "VGN-BX297XP", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-BX297XP"), + }, + }, { } /* terminate list */ }; @@ -1157,12 +975,27 @@ static int piix_broken_suspend(void) if (dmi_find_device(DMI_DEV_TYPE_OEM_STRING, oemstrs[i], NULL)) return 1; + /* TECRA M4 sometimes forgets its identify and reports bogus + * DMI information. As the bogus information is a bit + * generic, match as many entries as possible. This manual + * matching is necessary because dmi_system_id.matches is + * limited to four entries. + */ + if (dmi_match(DMI_SYS_VENDOR, "TOSHIBA") && + dmi_match(DMI_PRODUCT_NAME, "000000") && + dmi_match(DMI_PRODUCT_VERSION, "000000") && + dmi_match(DMI_PRODUCT_SERIAL, "000000") && + dmi_match(DMI_BOARD_VENDOR, "TOSHIBA") && + dmi_match(DMI_BOARD_NAME, "Portable PC") && + dmi_match(DMI_BOARD_VERSION, "Version A0")) + return 1; + return 0; } static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) { - struct ata_host *host = dev_get_drvdata(&pdev->dev); + struct ata_host *host = pci_get_drvdata(pdev); unsigned long flags; int rc = 0; @@ -1197,7 +1030,7 @@ static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) static int piix_pci_device_resume(struct pci_dev *pdev) { - struct ata_host *host = dev_get_drvdata(&pdev->dev); + struct ata_host *host = pci_get_drvdata(pdev); unsigned long flags; int rc; @@ -1215,8 +1048,9 @@ static int piix_pci_device_resume(struct pci_dev *pdev) */ rc = pci_reenable_device(pdev); if (rc) - dev_printk(KERN_ERR, &pdev->dev, "failed to enable " - "device after resume (%d)\n", rc); + dev_err(&pdev->dev, + "failed to enable device after resume (%d)\n", + rc); } else rc = ata_pci_device_do_resume(pdev); @@ -1232,6 +1066,213 @@ static u8 piix_vmw_bmdma_status(struct ata_port *ap) return ata_bmdma_status(ap) & ~ATA_DMA_ERR; } +static struct scsi_host_template piix_sht = { + ATA_BMDMA_SHT(DRV_NAME), +}; + +static struct ata_port_operations piix_sata_ops = { + .inherits = &ata_bmdma32_port_ops, + .sff_irq_check = piix_irq_check, + .port_start = piix_port_start, +}; + +static struct ata_port_operations piix_pata_ops = { + .inherits = &piix_sata_ops, + .cable_detect = ata_cable_40wire, + .set_piomode = piix_set_piomode, + .set_dmamode = piix_set_dmamode, + .prereset = piix_pata_prereset, +}; + +static struct ata_port_operations piix_vmw_ops = { + .inherits = &piix_pata_ops, + .bmdma_status = piix_vmw_bmdma_status, +}; + +static struct ata_port_operations ich_pata_ops = { + .inherits = &piix_pata_ops, + .cable_detect = ich_pata_cable_detect, + .set_dmamode = ich_set_dmamode, +}; + +static struct device_attribute *piix_sidpr_shost_attrs[] = { + &dev_attr_link_power_management_policy, + NULL +}; + +static struct scsi_host_template piix_sidpr_sht = { + ATA_BMDMA_SHT(DRV_NAME), + .shost_attrs = piix_sidpr_shost_attrs, +}; + +static struct ata_port_operations piix_sidpr_sata_ops = { + .inherits = &piix_sata_ops, + .hardreset = sata_std_hardreset, + .scr_read = piix_sidpr_scr_read, + .scr_write = piix_sidpr_scr_write, + .set_lpm = piix_sidpr_set_lpm, +}; + +static struct ata_port_info piix_port_info[] = { + [piix_pata_mwdma] = /* PIIX3 MWDMA only */ + { + .flags = PIIX_PATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .port_ops = &piix_pata_ops, + }, + + [piix_pata_33] = /* PIIX4 at 33MHz */ + { + .flags = PIIX_PATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .udma_mask = ATA_UDMA2, + .port_ops = &piix_pata_ops, + }, + + [ich_pata_33] = /* ICH0 - ICH at 33Mhz*/ + { + .flags = PIIX_PATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok */ + .udma_mask = ATA_UDMA2, + .port_ops = &ich_pata_ops, + }, + + [ich_pata_66] = /* ICH controllers up to 66MHz */ + { + .flags = PIIX_PATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */ + .udma_mask = ATA_UDMA4, + .port_ops = &ich_pata_ops, + }, + + [ich_pata_100] = + { + .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, + .udma_mask = ATA_UDMA5, + .port_ops = &ich_pata_ops, + }, + + [ich_pata_100_nomwdma1] = + { + .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2_ONLY, + .udma_mask = ATA_UDMA5, + .port_ops = &ich_pata_ops, + }, + + [ich5_sata] = + { + .flags = PIIX_SATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [ich6_sata] = + { + .flags = PIIX_SATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [ich6m_sata] = + { + .flags = PIIX_SATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [ich8_sata] = + { + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [ich8_2port_sata] = + { + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [tolapai_sata] = + { + .flags = PIIX_SATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [ich8m_apple_sata] = + { + .flags = PIIX_SATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [piix_pata_vmw] = + { + .flags = PIIX_PATA_FLAGS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .udma_mask = ATA_UDMA2, + .port_ops = &piix_vmw_ops, + }, + + /* + * some Sandybridge chipsets have broken 32 mode up to now, + * see https://bugzilla.kernel.org/show_bug.cgi?id=40592 + */ + [ich8_sata_snb] = + { + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [ich8_2port_sata_snb] = + { + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR + | PIIX_FLAG_PIO16, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [ich8_2port_sata_byt] = + { + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + +}; + #define AHCI_PCI_BAR 5 #define AHCI_GLOBAL_CTL 0x04 #define AHCI_ENABLE (1 << 31) @@ -1275,7 +1316,7 @@ static int piix_disable_ahci(struct pci_dev *pdev) * they are found return an error code so we can turn off DMA */ -static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) +static int piix_check_450nx_errata(struct pci_dev *ata_dev) { struct pci_dev *pdev = NULL; u16 cfg; @@ -1293,14 +1334,16 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) no_piix_dma = 2; } if (no_piix_dma) - dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n"); - if (no_piix_dma == 2) - dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n"); + dev_warn(&ata_dev->dev, + "450NX errata present, disabling IDE DMA%s\n", + no_piix_dma == 2 ? " - a BIOS update may resolve this" + : ""); + return no_piix_dma; } -static void __devinit piix_init_pcs(struct ata_host *host, - const struct piix_map_db *map_db) +static void piix_init_pcs(struct ata_host *host, + const struct piix_map_db *map_db) { struct pci_dev *pdev = to_pci_dev(host->dev); u16 pcs, new_pcs; @@ -1316,75 +1359,112 @@ static void __devinit piix_init_pcs(struct ata_host *host, } } -static const int *__devinit piix_init_sata_map(struct pci_dev *pdev, - struct ata_port_info *pinfo, - const struct piix_map_db *map_db) +static const int *piix_init_sata_map(struct pci_dev *pdev, + struct ata_port_info *pinfo, + const struct piix_map_db *map_db) { const int *map; int i, invalid_map = 0; u8 map_value; + char buf[32]; + char *p = buf, *end = buf + sizeof(buf); pci_read_config_byte(pdev, ICH5_PMR, &map_value); map = map_db->map[map_value & map_db->mask]; - dev_printk(KERN_INFO, &pdev->dev, "MAP ["); for (i = 0; i < 4; i++) { switch (map[i]) { case RV: invalid_map = 1; - printk(" XX"); + p += scnprintf(p, end - p, " XX"); break; case NA: - printk(" --"); + p += scnprintf(p, end - p, " --"); break; case IDE: WARN_ON((i & 1) || map[i + 1] != IDE); pinfo[i / 2] = piix_port_info[ich_pata_100]; i++; - printk(" IDE IDE"); + p += scnprintf(p, end - p, " IDE IDE"); break; default: - printk(" P%d", map[i]); + p += scnprintf(p, end - p, " P%d", map[i]); if (i & 1) pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS; break; } } - printk(" ]\n"); + dev_info(&pdev->dev, "MAP [%s ]\n", buf); if (invalid_map) - dev_printk(KERN_ERR, &pdev->dev, - "invalid MAP value %u\n", map_value); + dev_err(&pdev->dev, "invalid MAP value %u\n", map_value); return map; } -static void __devinit piix_init_sidpr(struct ata_host *host) +static bool piix_no_sidpr(struct ata_host *host) +{ + struct pci_dev *pdev = to_pci_dev(host->dev); + + /* + * Samsung DB-P70 only has three ATA ports exposed and + * curiously the unconnected first port reports link online + * while not responding to SRST protocol causing excessive + * detection delay. + * + * Unfortunately, the system doesn't carry enough DMI + * information to identify the machine but does have subsystem + * vendor and device set. As it's unclear whether the + * subsystem vendor/device is used only for this specific + * board, the port can't be disabled solely with the + * information; however, turning off SIDPR access works around + * the problem. Turn it off. + * + * This problem is reported in bnc#441240. + * + * https://bugzilla.novell.com/show_bug.cgi?id=441420 + */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 && + pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && + pdev->subsystem_device == 0xb049) { + dev_warn(host->dev, + "Samsung DB-P70 detected, disabling SIDPR\n"); + return true; + } + + return false; +} + +static int piix_init_sidpr(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); struct piix_host_priv *hpriv = host->private_data; - struct ata_device *dev0 = &host->ports[0]->link.device[0]; + struct ata_link *link0 = &host->ports[0]->link; u32 scontrol; - int i; + int i, rc; /* check for availability */ for (i = 0; i < 4; i++) if (hpriv->map[i] == IDE) - return; + return 0; + + /* is it blacklisted? */ + if (piix_no_sidpr(host)) + return 0; if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) - return; + return 0; if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 || pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN) - return; + return 0; if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME)) - return; + return 0; hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR]; @@ -1392,7 +1472,7 @@ static void __devinit piix_init_sidpr(struct ata_host *host) * Give it a test drive by inhibiting power save modes which * we'll do anyway. */ - scontrol = piix_sidpr_read(dev0, SCR_CONTROL); + piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); /* if IPM is already 3, SCR access is probably working. Don't * un-inhibit power save modes as BIOS might have inhibited @@ -1400,21 +1480,33 @@ static void __devinit piix_init_sidpr(struct ata_host *host) */ if ((scontrol & 0xf00) != 0x300) { scontrol |= 0x300; - piix_sidpr_write(dev0, SCR_CONTROL, scontrol); - scontrol = piix_sidpr_read(dev0, SCR_CONTROL); + piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol); + piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); if ((scontrol & 0xf00) != 0x300) { - dev_printk(KERN_INFO, host->dev, "SCR access via " - "SIDPR is available but doesn't work\n"); - return; + dev_info(host->dev, + "SCR access via SIDPR is available but doesn't work\n"); + return 0; + } + } + + /* okay, SCRs available, set ops and ask libata for slave_link */ + for (i = 0; i < 2; i++) { + struct ata_port *ap = host->ports[i]; + + ap->ops = &piix_sidpr_sata_ops; + + if (ap->flags & ATA_FLAG_SLAVE_POSS) { + rc = ata_slave_link_init(ap); + if (rc) + return rc; } } - host->ports[0]->ops = &piix_sidpr_sata_ops; - host->ports[1]->ops = &piix_sidpr_sata_ops; + 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[] = { { @@ -1431,7 +1523,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; @@ -1440,15 +1533,104 @@ 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)) { - dev_printk(KERN_INFO, &pdev->dev, - "applying IOCFG bit18 quirk\n"); - iocfg &= ~(1 << 18); - pci_write_config_dword(pdev, PIIX_IOCFG, iocfg); + if (hpriv->saved_iocfg & (1 << 18)) { + dev_info(&pdev->dev, "applying IOCFG bit18 quirk\n"); + pci_write_config_dword(pdev, PIIX_IOCFG, + hpriv->saved_iocfg & ~(1 << 18)); } } +static bool piix_broken_system_poweroff(struct pci_dev *pdev) +{ + static const struct dmi_system_id broken_systems[] = { + { + .ident = "HP Compaq 2510p", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 2510p"), + }, + /* PCI slot number of the controller */ + .driver_data = (void *)0x1FUL, + }, + { + .ident = "HP Compaq nc6000", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6000"), + }, + /* PCI slot number of the controller */ + .driver_data = (void *)0x1FUL, + }, + + { } /* terminate list */ + }; + const struct dmi_system_id *dmi = dmi_first_match(broken_systems); + + if (dmi) { + unsigned long slot = (unsigned long)dmi->driver_data; + /* apply the quirk only to on-board controllers */ + return slot == PCI_SLOT(pdev->devfn); + } + + return false; +} + +static int prefer_ms_hyperv = 1; +module_param(prefer_ms_hyperv, int, 0); +MODULE_PARM_DESC(prefer_ms_hyperv, + "Prefer Hyper-V paravirtualization drivers instead of ATA, " + "0 - Use ATA drivers, " + "1 (Default) - Use the paravirtualization drivers."); + +static void piix_ignore_devices_quirk(struct ata_host *host) +{ +#if IS_ENABLED(CONFIG_HYPERV_STORAGE) + static const struct dmi_system_id ignore_hyperv[] = { + { + /* On Hyper-V hypervisors the disks are exposed on + * both the emulated SATA controller and on the + * paravirtualised drivers. The CD/DVD devices + * are only exposed on the emulated controller. + * Request we ignore ATA devices on this host. + */ + .ident = "Hyper-V Virtual Machine", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, + "Microsoft Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), + }, + }, + { } /* terminate list */ + }; + static const struct dmi_system_id allow_virtual_pc[] = { + { + /* In MS Virtual PC guests the DMI ident is nearly + * identical to a Hyper-V guest. One difference is the + * product version which is used here to identify + * a Virtual PC guest. This entry allows ata_piix to + * drive the emulated hardware. + */ + .ident = "MS Virtual PC 2007", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, + "Microsoft Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), + DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), + }, + }, + { } /* terminate list */ + }; + const struct dmi_system_id *ignore = dmi_first_match(ignore_hyperv); + const struct dmi_system_id *allow = dmi_first_match(allow_virtual_pc); + + if (ignore && !allow && prefer_ms_hyperv) { + host->flags |= ATA_HOST_IGNORE_ATA; + dev_info(host->dev, "%s detected, ATA device ignore set\n", + ignore->ident); + } +#endif +} + /** * piix_init_one - Register PIIX ATA PCI device with kernel services * @pdev: PCI device to register @@ -1464,26 +1646,31 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) * Zero on success, or -ERRNO value. */ -static int __devinit piix_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int printed_version; struct device *dev = &pdev->dev; struct ata_port_info port_info[2]; const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] }; + struct scsi_host_template *sht = &piix_sht; unsigned long port_flags; struct ata_host *host; struct piix_host_priv *hpriv; int rc; - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, - "version " DRV_VERSION "\n"); + ata_print_version_once(&pdev->dev, DRV_VERSION); - /* no hotplugging support (FIXME) */ - if (!in_module_init) + /* no hotplugging support for later devices (FIXME) */ + if (!in_module_init && ent->driver_data >= ich5_sata) return -ENODEV; + if (piix_broken_system_poweroff(pdev)) { + piix_port_info[ent->driver_data].flags |= + ATA_FLAG_NO_POWEROFF_SPINDOWN | + ATA_FLAG_NO_HIBERNATE_SPINDOWN; + dev_info(&pdev->dev, "quirky BIOS, skipping spindown " + "on poweroff and hibernation\n"); + } + port_info[0] = piix_port_info[ent->driver_data]; port_info[1] = piix_port_info[ent->driver_data]; @@ -1494,6 +1681,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. @@ -1505,15 +1703,11 @@ 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]); - rc = ata_pci_sff_prepare_host(pdev, ppi, &host); + rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); if (rc) return rc; host->private_data = hpriv; @@ -1521,11 +1715,15 @@ static int __devinit piix_init_one(struct pci_dev *pdev, /* initialize controller */ if (port_flags & ATA_FLAG_SATA) { piix_init_pcs(host, piix_map_db_table[ent->driver_data]); - piix_init_sidpr(host); + rc = piix_init_sidpr(host); + if (rc) + return rc; + if (host->ports[0]->ops == &piix_sidpr_sata_ops) + sht = &piix_sidpr_sht; } /* 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. @@ -1545,11 +1743,36 @@ static int __devinit piix_init_one(struct pci_dev *pdev, host->ports[1]->mwdma_mask = 0; host->ports[1]->udma_mask = 0; } + host->flags |= ATA_HOST_PARALLEL_SCAN; + + /* Allow hosts to specify device types to ignore when scanning. */ + piix_ignore_devices_quirk(host); pci_set_master(pdev); - return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht); + return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); } +static void piix_remove_one(struct pci_dev *pdev) +{ + struct ata_host *host = pci_get_drvdata(pdev); + struct piix_host_priv *hpriv = host->private_data; + + pci_write_config_dword(pdev, PIIX_IOCFG, hpriv->saved_iocfg); + + ata_pci_remove_one(pdev); +} + +static struct pci_driver piix_pci_driver = { + .name = DRV_NAME, + .id_table = piix_pci_tbl, + .probe = piix_init_one, + .remove = piix_remove_one, +#ifdef CONFIG_PM_SLEEP + .suspend = piix_pci_device_suspend, + .resume = piix_pci_device_resume, +#endif +}; + static int __init piix_init(void) { int rc; |
