From 4da646b7b52552f3b43eae27ffa5aa2c200f6db6 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 8 Apr 2009 02:00:13 -0400 Subject: [libata] ahci: use less error-prone array initializers Also, remove unneeded prototype. Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/ata/ahci.c') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 6b91c26a4635..cd832cb69492 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -313,7 +313,6 @@ static void ahci_error_handler(struct ata_port *ap); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static int ahci_port_resume(struct ata_port *ap); static void ahci_dev_config(struct ata_device *dev); -static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl); static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, u32 opts); #ifdef CONFIG_PM @@ -404,14 +403,14 @@ static struct ata_port_operations ahci_sb600_ops = { #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) static const struct ata_port_info ahci_port_info[] = { - /* board_ahci */ + [board_ahci] = { .flags = AHCI_FLAG_COMMON, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, - /* board_ahci_vt8251 */ + [board_ahci_vt8251] = { AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), .flags = AHCI_FLAG_COMMON, @@ -419,7 +418,7 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_vt8251_ops, }, - /* board_ahci_ign_iferr */ + [board_ahci_ign_iferr] = { AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), .flags = AHCI_FLAG_COMMON, @@ -427,7 +426,7 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, - /* board_ahci_sb600 */ + [board_ahci_sb600] = { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | @@ -437,7 +436,7 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_sb600_ops, }, - /* board_ahci_mv */ + [board_ahci_mv] = { AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), @@ -447,7 +446,7 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, - /* board_ahci_sb700, for SB700 and SB800 */ + [board_ahci_sb700] = /* for SB700 and SB800 */ { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), .flags = AHCI_FLAG_COMMON, @@ -455,7 +454,7 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_sb600_ops, }, - /* board_ahci_mcp65 */ + [board_ahci_mcp65] = { AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), .flags = AHCI_FLAG_COMMON, @@ -463,7 +462,7 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, - /* board_ahci_nopmp */ + [board_ahci_nopmp] = { AHCI_HFLAGS (AHCI_HFLAG_NO_PMP), .flags = AHCI_FLAG_COMMON, -- cgit v1.2.3 From d50ce07d6fd8a422757a231f9d7293cbddeaec31 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 12 May 2009 10:57:41 +0900 Subject: ahci: misc cleanups for EM stuff Make the following EM related cleanups. * Use msleep(1) instead of udelay(100) and reduce retry count to 5. * s/MAX_SLOTS/EM_MAX_SLOTS/, s/MAX_RETRY/EM_MAX_RETRY/ * Make EM constants enums as suggested by Jeff. Signed-off-by: Tejun Heo Acked-by: David Milburn Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/ata/ahci.c') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index cd832cb69492..2141a31f176b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -77,8 +77,6 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, size_t size); static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, ssize_t size); -#define MAX_SLOTS 8 -#define MAX_RETRY 15 enum { AHCI_PCI_BAR = 5, @@ -231,6 +229,10 @@ enum { ICH_MAP = 0x90, /* ICH MAP register */ + /* em constants */ + EM_MAX_SLOTS = 8, + EM_MAX_RETRY = 5, + /* em_ctl bits */ EM_CTL_RST = (1 << 9), /* Reset */ EM_CTL_TM = (1 << 8), /* Transmit Message */ @@ -282,8 +284,8 @@ struct ahci_port_priv { unsigned int ncq_saw_dmas:1; unsigned int ncq_saw_sdb:1; u32 intr_mask; /* interrupts to enable */ - struct ahci_em_priv em_priv[MAX_SLOTS];/* enclosure management info - * per PM slot */ + /* enclosure management info per PM slot */ + struct ahci_em_priv em_priv[EM_MAX_SLOTS]; }; static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); @@ -1140,12 +1142,12 @@ static void ahci_start_port(struct ata_port *ap) emp = &pp->em_priv[link->pmp]; /* EM Transmit bit maybe busy during init */ - for (i = 0; i < MAX_RETRY; i++) { + for (i = 0; i < EM_MAX_RETRY; i++) { rc = ahci_transmit_led_message(ap, emp->led_state, 4); if (rc == -EBUSY) - udelay(100); + msleep(1); else break; } @@ -1339,7 +1341,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, /* get the slot number from the message */ pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; - if (pmp < MAX_SLOTS) + if (pmp < EM_MAX_SLOTS) emp = &pp->em_priv[pmp]; else return -EINVAL; @@ -1407,7 +1409,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, /* get the slot number from the message */ pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; - if (pmp < MAX_SLOTS) + if (pmp < EM_MAX_SLOTS) emp = &pp->em_priv[pmp]; else return -EINVAL; -- cgit v1.2.3 From 58a09b38cfcd700b796ea07ae3d2e0efbb28b561 Mon Sep 17 00:00:00 2001 From: Shane Huang Date: Wed, 27 May 2009 15:04:43 +0800 Subject: [libata] ahci: Restore SB600 SATA controller 64 bit DMA Community reported one SB600 SATA issue(BZ #9412), which led to 64 bit DMA disablement for all SB600 revisions by driver maintainers with commits c7a42156d99bcea7f8173ba7a6034bbaa2ecb77c and 4cde32fc4b32e96a99063af3183acdfd54c563f0. But the root cause is ASUS M2A-VM system BIOS bug in old revisions like 0901, while forcing into 32bit DMA happens to work as workaround. Now it's time to withdraw 4cde32fc4b32e96a99063af3183acdfd54c563f0 so as to restore the SB600 SATA 64bit DMA capability. This patch is also adding the workaround for M2A-VM old BIOS revisions, but users are suggested to upgrade their system BIOS to the latest one if they meet this issue. Signed-off-by: Shane Huang Cc: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 52 +++++++++++++++++++++++++++++++++++++++++++-- drivers/firmware/dmi_scan.c | 1 + 2 files changed, 51 insertions(+), 2 deletions(-) (limited to 'drivers/ata/ahci.c') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 2141a31f176b..15a23031833f 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -431,8 +431,7 @@ static const struct ata_port_info ahci_port_info[] = { [board_ahci_sb600] = { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | - AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | - AHCI_HFLAG_SECT255), + AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255), .flags = AHCI_FLAG_COMMON, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, @@ -2585,6 +2584,51 @@ static void ahci_p5wdh_workaround(struct ata_host *host) } } +/* + * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older + * BIOS. The oldest version known to be broken is 0901 and working is + * 1501 which was released on 2007-10-26. Force 32bit DMA on anything + * older than 1501. Please read bko#9412 for more info. + */ +static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev) +{ + static const struct dmi_system_id sysids[] = { + { + .ident = "ASUS M2A-VM", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, + "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), + }, + }, + { } + }; + const char *cutoff_mmdd = "10/26"; + const char *date; + int year; + + if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || + !dmi_check_system(sysids)) + return false; + + /* + * Argh.... both version and date are free form strings. + * Let's hope they're using the same date format across + * different versions. + */ + date = dmi_get_system_info(DMI_BIOS_DATE); + year = dmi_get_year(DMI_BIOS_DATE); + if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' && + (year > 2007 || + (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0))) + return false; + + dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, " + "forcing 32bit DMA, update BIOS\n"); + + return true; +} + static bool ahci_broken_system_poweroff(struct pci_dev *pdev) { static const struct dmi_system_id broken_systems[] = { @@ -2745,6 +2789,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; + /* apply ASUS M2A_VM quirk */ + if (ahci_asus_m2a_vm_32bit_only(pdev)) + hpriv->flags |= AHCI_HFLAG_32BIT_ONLY; + if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) pci_enable_msi(pdev); diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 5f1b5400d96a..24c84ae81527 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -596,6 +596,7 @@ int dmi_get_year(int field) return year; } +EXPORT_SYMBOL(dmi_get_year); /** * dmi_walk - Walk the DMI table and get called back for every record -- cgit v1.2.3