Commit 36a07902 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  pata_atp867x: add Power Management support
  pata_atp867x: PIO support fixes
  pata_atp867x: clarifications in timings calculations and cable detection
  pata_atp867x: fix it to not claim MWDMA support
  libata: fix incorrect link online check during probe
  ahci: filter FPDMA non-zero offset enable for Aspire 3810T
  libata: make gtf_filter per-dev
  libata: implement more acpi filtering options
  libata: cosmetic updates
  ahci: display all AHCI 1.3 HBA capability flags (v2)
  pata_ali: trivial fix of a very frequent spelling mistake
  ahci: disable 64bit DMA by default on SB600s
parents f579bbcd 7affb32a
...@@ -122,6 +122,7 @@ enum { ...@@ -122,6 +122,7 @@ enum {
HOST_VERSION = 0x10, /* AHCI spec. version compliancy */ HOST_VERSION = 0x10, /* AHCI spec. version compliancy */
HOST_EM_LOC = 0x1c, /* Enclosure Management location */ HOST_EM_LOC = 0x1c, /* Enclosure Management location */
HOST_EM_CTL = 0x20, /* Enclosure Management Control */ HOST_EM_CTL = 0x20, /* Enclosure Management Control */
HOST_CAP2 = 0x24, /* host capabilities, extended */
/* HOST_CTL bits */ /* HOST_CTL bits */
HOST_RESET = (1 << 0), /* reset controller; self-clear */ HOST_RESET = (1 << 0), /* reset controller; self-clear */
...@@ -129,16 +130,29 @@ enum { ...@@ -129,16 +130,29 @@ enum {
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
/* HOST_CAP bits */ /* HOST_CAP bits */
HOST_CAP_SXS = (1 << 5), /* Supports External SATA */
HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */ HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
HOST_CAP_SSC = (1 << 14), /* Slumber capable */ HOST_CAP_CCC = (1 << 7), /* Command Completion Coalescing */
HOST_CAP_PART = (1 << 13), /* Partial state capable */
HOST_CAP_SSC = (1 << 14), /* Slumber state capable */
HOST_CAP_PIO_MULTI = (1 << 15), /* PIO multiple DRQ support */
HOST_CAP_FBS = (1 << 16), /* FIS-based switching support */
HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
HOST_CAP_ONLY = (1 << 18), /* Supports AHCI mode only */
HOST_CAP_CLO = (1 << 24), /* Command List Override support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */
HOST_CAP_LED = (1 << 25), /* Supports activity LED */
HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */ HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
HOST_CAP_MPS = (1 << 28), /* Mechanical presence switch */
HOST_CAP_SNTF = (1 << 29), /* SNotification register */ HOST_CAP_SNTF = (1 << 29), /* SNotification register */
HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
/* HOST_CAP2 bits */
HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */
HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */
HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */
/* registers for each SATA port */ /* registers for each SATA port */
PORT_LST_ADDR = 0x00, /* command list DMA addr */ PORT_LST_ADDR = 0x00, /* command list DMA addr */
PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */ PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */
...@@ -267,8 +281,10 @@ struct ahci_em_priv { ...@@ -267,8 +281,10 @@ struct ahci_em_priv {
struct ahci_host_priv { struct ahci_host_priv {
unsigned int flags; /* AHCI_HFLAG_* */ unsigned int flags; /* AHCI_HFLAG_* */
u32 cap; /* cap to use */ u32 cap; /* cap to use */
u32 cap2; /* cap2 to use */
u32 port_map; /* port map to use */ u32 port_map; /* port map to use */
u32 saved_cap; /* saved initial cap */ u32 saved_cap; /* saved initial cap */
u32 saved_cap2; /* saved initial cap2 */
u32 saved_port_map; /* saved initial port_map */ u32 saved_port_map; /* saved initial port_map */
u32 em_loc; /* enclosure management location */ u32 em_loc; /* enclosure management location */
}; };
...@@ -331,12 +347,15 @@ static void ahci_init_sw_activity(struct ata_link *link); ...@@ -331,12 +347,15 @@ static void ahci_init_sw_activity(struct ata_link *link);
static ssize_t ahci_show_host_caps(struct device *dev, static ssize_t ahci_show_host_caps(struct device *dev,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *buf);
static ssize_t ahci_show_host_cap2(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t ahci_show_host_version(struct device *dev, static ssize_t ahci_show_host_version(struct device *dev,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *buf);
static ssize_t ahci_show_port_cmd(struct device *dev, static ssize_t ahci_show_port_cmd(struct device *dev,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *buf);
DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
...@@ -345,6 +364,7 @@ static struct device_attribute *ahci_shost_attrs[] = { ...@@ -345,6 +364,7 @@ static struct device_attribute *ahci_shost_attrs[] = {
&dev_attr_em_message_type, &dev_attr_em_message_type,
&dev_attr_em_message, &dev_attr_em_message,
&dev_attr_ahci_host_caps, &dev_attr_ahci_host_caps,
&dev_attr_ahci_host_cap2,
&dev_attr_ahci_host_version, &dev_attr_ahci_host_version,
&dev_attr_ahci_port_cmd, &dev_attr_ahci_port_cmd,
NULL NULL
...@@ -447,7 +467,8 @@ static const struct ata_port_info ahci_port_info[] = { ...@@ -447,7 +467,8 @@ static const struct ata_port_info ahci_port_info[] = {
[board_ahci_sb600] = [board_ahci_sb600] =
{ {
AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255), AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
AHCI_HFLAG_32BIT_ONLY),
.flags = AHCI_FLAG_COMMON, .flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4, .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
...@@ -732,6 +753,16 @@ static ssize_t ahci_show_host_caps(struct device *dev, ...@@ -732,6 +753,16 @@ static ssize_t ahci_show_host_caps(struct device *dev,
return sprintf(buf, "%x\n", hpriv->cap); return sprintf(buf, "%x\n", hpriv->cap);
} }
static ssize_t ahci_show_host_cap2(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct ata_port *ap = ata_shost_to_port(shost);
struct ahci_host_priv *hpriv = ap->host->private_data;
return sprintf(buf, "%x\n", hpriv->cap2);
}
static ssize_t ahci_show_host_version(struct device *dev, static ssize_t ahci_show_host_version(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -771,7 +802,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev, ...@@ -771,7 +802,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
struct ahci_host_priv *hpriv) struct ahci_host_priv *hpriv)
{ {
void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
u32 cap, port_map; u32 cap, cap2, vers, port_map;
int i; int i;
int mv; int mv;
...@@ -784,6 +815,14 @@ static void ahci_save_initial_config(struct pci_dev *pdev, ...@@ -784,6 +815,14 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
hpriv->saved_cap = cap = readl(mmio + HOST_CAP); hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL); hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
/* CAP2 register is only defined for AHCI 1.2 and later */
vers = readl(mmio + HOST_VERSION);
if ((vers >> 16) > 1 ||
((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200))
hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2);
else
hpriv->saved_cap2 = cap2 = 0;
/* some chips have errata preventing 64bit use */ /* some chips have errata preventing 64bit use */
if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) { if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
dev_printk(KERN_INFO, &pdev->dev, dev_printk(KERN_INFO, &pdev->dev,
...@@ -869,6 +908,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev, ...@@ -869,6 +908,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
/* record values to use during operation */ /* record values to use during operation */
hpriv->cap = cap; hpriv->cap = cap;
hpriv->cap2 = cap2;
hpriv->port_map = port_map; hpriv->port_map = port_map;
} }
...@@ -887,6 +927,8 @@ static void ahci_restore_initial_config(struct ata_host *host) ...@@ -887,6 +927,8 @@ static void ahci_restore_initial_config(struct ata_host *host)
void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
writel(hpriv->saved_cap, mmio + HOST_CAP); writel(hpriv->saved_cap, mmio + HOST_CAP);
if (hpriv->saved_cap2)
writel(hpriv->saved_cap2, mmio + HOST_CAP2);
writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL); writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
(void) readl(mmio + HOST_PORTS_IMPL); /* flush */ (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
} }
...@@ -2534,13 +2576,14 @@ static void ahci_print_info(struct ata_host *host) ...@@ -2534,13 +2576,14 @@ static void ahci_print_info(struct ata_host *host)
struct ahci_host_priv *hpriv = host->private_data; struct ahci_host_priv *hpriv = host->private_data;
struct pci_dev *pdev = to_pci_dev(host->dev); struct pci_dev *pdev = to_pci_dev(host->dev);
void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
u32 vers, cap, impl, speed; u32 vers, cap, cap2, impl, speed;
const char *speed_s; const char *speed_s;
u16 cc; u16 cc;
const char *scc_s; const char *scc_s;
vers = readl(mmio + HOST_VERSION); vers = readl(mmio + HOST_VERSION);
cap = hpriv->cap; cap = hpriv->cap;
cap2 = hpriv->cap2;
impl = hpriv->port_map; impl = hpriv->port_map;
speed = (cap >> 20) & 0xf; speed = (cap >> 20) & 0xf;
...@@ -2583,25 +2626,29 @@ static void ahci_print_info(struct ata_host *host) ...@@ -2583,25 +2626,29 @@ static void ahci_print_info(struct ata_host *host)
"flags: " "flags: "
"%s%s%s%s%s%s%s" "%s%s%s%s%s%s%s"
"%s%s%s%s%s%s%s" "%s%s%s%s%s%s%s"
"%s\n" "%s%s%s%s%s%s\n"
, ,
cap & (1 << 31) ? "64bit " : "", cap & HOST_CAP_64 ? "64bit " : "",
cap & (1 << 30) ? "ncq " : "", cap & HOST_CAP_NCQ ? "ncq " : "",
cap & (1 << 29) ? "sntf " : "", cap & HOST_CAP_SNTF ? "sntf " : "",
cap & (1 << 28) ? "ilck " : "", cap & HOST_CAP_MPS ? "ilck " : "",
cap & (1 << 27) ? "stag " : "", cap & HOST_CAP_SSS ? "stag " : "",
cap & (1 << 26) ? "pm " : "", cap & HOST_CAP_ALPM ? "pm " : "",
cap & (1 << 25) ? "led " : "", cap & HOST_CAP_LED ? "led " : "",
cap & HOST_CAP_CLO ? "clo " : "",
cap & (1 << 24) ? "clo " : "", cap & HOST_CAP_ONLY ? "only " : "",
cap & (1 << 19) ? "nz " : "", cap & HOST_CAP_PMP ? "pmp " : "",
cap & (1 << 18) ? "only " : "", cap & HOST_CAP_FBS ? "fbs " : "",
cap & (1 << 17) ? "pmp " : "", cap & HOST_CAP_PIO_MULTI ? "pio " : "",
cap & (1 << 15) ? "pio " : "", cap & HOST_CAP_SSC ? "slum " : "",
cap & (1 << 14) ? "slum " : "", cap & HOST_CAP_PART ? "part " : "",
cap & (1 << 13) ? "part " : "", cap & HOST_CAP_CCC ? "ccc " : "",
cap & (1 << 6) ? "ems ": "" cap & HOST_CAP_EMS ? "ems " : "",
cap & HOST_CAP_SXS ? "sxs " : "",
cap2 & HOST_CAP2_APST ? "apst " : "",
cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
cap2 & HOST_CAP2_BOH ? "boh " : ""
); );
} }
...@@ -2650,17 +2697,15 @@ static void ahci_p5wdh_workaround(struct ata_host *host) ...@@ -2650,17 +2697,15 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
} }
} }
/* /* only some SB600 ahci controllers can do 64bit DMA */
* SB600 ahci controller on certain boards can't do 64bit DMA with static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
* older BIOS.
*/
static bool ahci_sb600_32bit_only(struct pci_dev *pdev)
{ {
static const struct dmi_system_id sysids[] = { static const struct dmi_system_id sysids[] = {
/* /*
* The oldest version known to be broken is 0901 and * The oldest version known to be broken is 0901 and
* working is 1501 which was released on 2007-10-26. * working is 1501 which was released on 2007-10-26.
* Force 32bit DMA on anything older than 1501. * Enable 64bit DMA on 1501 and anything newer.
*
* Please read bko#9412 for more info. * Please read bko#9412 for more info.
*/ */
{ {
...@@ -2672,48 +2717,29 @@ static bool ahci_sb600_32bit_only(struct pci_dev *pdev) ...@@ -2672,48 +2717,29 @@ static bool ahci_sb600_32bit_only(struct pci_dev *pdev)
}, },
.driver_data = "20071026", /* yyyymmdd */ .driver_data = "20071026", /* yyyymmdd */
}, },
/*
* It's yet unknown whether more recent BIOS fixes the
* problem. Blacklist the whole board for the time
* being. Please read the following thread for more
* info.
*
* http://thread.gmane.org/gmane.linux.ide/42326
*/
{
.ident = "Gigabyte GA-MA69VM-S2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR,
"Gigabyte Technology Co., Ltd."),
DMI_MATCH(DMI_BOARD_NAME, "GA-MA69VM-S2"),
},
},
{ } { }
}; };
const struct dmi_system_id *match; const struct dmi_system_id *match;
int year, month, date;
char buf[9];
match = dmi_first_match(sysids); match = dmi_first_match(sysids);
if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
!match) !match)
return false; return false;
if (match->driver_data) { dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
int year, month, date; snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
char buf[9];
dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
if (strcmp(buf, match->driver_data) >= 0)
return false;
if (strcmp(buf, match->driver_data) >= 0) {
dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
match->ident);
return true;
} else {
dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, " dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, "
"forcing 32bit DMA, update BIOS\n", match->ident); "forcing 32bit DMA, update BIOS\n", match->ident);
} else return false;
dev_printk(KERN_WARNING, &pdev->dev, "%s: this board can't " }
"do 64bit DMA, forcing 32bit\n", match->ident);
return true;
} }
static bool ahci_broken_system_poweroff(struct pci_dev *pdev) static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
...@@ -2858,6 +2884,50 @@ static bool ahci_broken_online(struct pci_dev *pdev) ...@@ -2858,6 +2884,50 @@ static bool ahci_broken_online(struct pci_dev *pdev)
return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
} }
static void ahci_gtf_filter_workaround(struct ata_host *host)
{
static const struct dmi_system_id sysids[] = {
/*
* Aspire 3810T issues a bunch of SATA enable commands
* via _GTF including an invalid one and one which is
* rejected by the device. Among the successful ones
* is FPDMA non-zero offset enable which when enabled
* only on the drive side leads to NCQ command
* failures. Filter it out.
*/
{
.ident = "Aspire 3810T",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
},
.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
},
{ }
};
const struct dmi_system_id *dmi = dmi_first_match(sysids);
unsigned int filter;
int i;
if (!dmi)
return;
filter = (unsigned long)dmi->driver_data;
dev_printk(KERN_INFO, host->dev,
"applying extra ACPI _GTF filter 0x%x for %s\n",
filter, dmi->ident);
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
struct ata_link *link;
struct ata_device *dev;
ata_for_each_link(link, ap, EDGE)
ata_for_each_dev(dev, link, ALL)
dev->gtf_filter |= filter;
}
}
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
static int printed_version; static int printed_version;
...@@ -2926,9 +2996,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2926,9 +2996,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
/* apply sb600 32bit only quirk */ /* only some SB600s can do 64bit DMA */
if (ahci_sb600_32bit_only(pdev)) if (ahci_sb600_enable_64bit(pdev))
hpriv->flags |= AHCI_HFLAG_32BIT_ONLY; hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
pci_intx(pdev, 1); pci_intx(pdev, 1);
...@@ -3023,6 +3093,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3023,6 +3093,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* apply workaround for ASUS P5W DH Deluxe mainboard */ /* apply workaround for ASUS P5W DH Deluxe mainboard */
ahci_p5wdh_workaround(host); ahci_p5wdh_workaround(host);
/* apply gtf filter quirk */
ahci_gtf_filter_workaround(host);
/* initialize adapter */ /* initialize adapter */
rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
if (rc) if (rc)
......
...@@ -20,19 +20,9 @@ ...@@ -20,19 +20,9 @@
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
enum { unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;
ATA_ACPI_FILTER_SETXFER = 1 << 0,
ATA_ACPI_FILTER_LOCK = 1 << 1,
ATA_ACPI_FILTER_DIPM = 1 << 2,
ATA_ACPI_FILTER_DEFAULT = ATA_ACPI_FILTER_SETXFER |
ATA_ACPI_FILTER_LOCK |
ATA_ACPI_FILTER_DIPM,
};
static unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;
module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644); module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644);
MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM)"); MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM, 0x8=FPDMA non-zero offset, 0x10=FPDMA DMA Setup FIS auto-activate)");
#define NO_PORT_MULT 0xffff #define NO_PORT_MULT 0xffff
#define SATA_ADR(root, pmp) (((root) << 16) | (pmp)) #define SATA_ADR(root, pmp) (((root) << 16) | (pmp))
...@@ -613,10 +603,11 @@ static void ata_acpi_gtf_to_tf(struct ata_device *dev, ...@@ -613,10 +603,11 @@ static void ata_acpi_gtf_to_tf(struct ata_device *dev,
tf->command = gtf->tf[6]; /* 0x1f7 */ tf->command = gtf->tf[6]; /* 0x1f7 */
} }
static int ata_acpi_filter_tf(const struct ata_taskfile *tf, static int ata_acpi_filter_tf(struct ata_device *dev,
const struct ata_taskfile *tf,
const struct ata_taskfile *ptf) const struct ata_taskfile *ptf)
{ {
if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_SETXFER) { if (dev->gtf_filter & ATA_ACPI_FILTER_SETXFER) {
/* libata doesn't use ACPI to configure transfer mode. /* libata doesn't use ACPI to configure transfer mode.
* It will only confuse device configuration. Skip. * It will only confuse device configuration. Skip.
*/ */
...@@ -625,7 +616,7 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf, ...@@ -625,7 +616,7 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
return 1; return 1;
} }
if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_LOCK) { if (dev->gtf_filter & ATA_ACPI_FILTER_LOCK) {
/* BIOS writers, sorry but we don't wanna lock /* BIOS writers, sorry but we don't wanna lock
* features unless the user explicitly said so. * features unless the user explicitly said so.
*/ */
...@@ -647,12 +638,23 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf, ...@@ -647,12 +638,23 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
return 1; return 1;
} }
if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_DIPM) { if (tf->command == ATA_CMD_SET_FEATURES &&
tf->feature == SETFEATURES_SATA_ENABLE) {
/* inhibit enabling DIPM */ /* inhibit enabling DIPM */
if (tf->command == ATA_CMD_SET_FEATURES && if (dev->gtf_filter & ATA_ACPI_FILTER_DIPM &&
tf->feature == SETFEATURES_SATA_ENABLE &&
tf->nsect == SATA_DIPM) tf->nsect == SATA_DIPM)
return 1; return 1;
/* inhibit FPDMA non-zero offset */
if (dev->gtf_filter & ATA_ACPI_FILTER_FPDMA_OFFSET &&
(tf->nsect == SATA_FPDMA_OFFSET ||
tf->nsect == SATA_FPDMA_IN_ORDER))
return 1;
/* inhibit FPDMA auto activation */
if (dev->gtf_filter & ATA_ACPI_FILTER_FPDMA_AA &&
tf->nsect == SATA_FPDMA_AA)
return 1;
} }
return 0; return 0;
...@@ -704,7 +706,7 @@ static int ata_acpi_run_tf(struct ata_device *dev, ...@@ -704,7 +706,7 @@ static int ata_acpi_run_tf(struct ata_device *dev,
pptf = &ptf; pptf = &ptf;
} }
if (!ata_acpi_filter_tf(&tf, pptf)) { if (!ata_acpi_filter_tf(dev, &tf, pptf)) {
rtf = tf; rtf = tf;
err_mask = ata_exec_internal(dev, &rtf, NULL, err_mask = ata_exec_internal(dev, &rtf, NULL,
DMA_NONE, NULL, 0, 0); DMA_NONE, NULL, 0, 0);
......
...@@ -5591,6 +5591,9 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp) ...@@ -5591,6 +5591,9 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
dev->link = link; dev->link = link;
dev->devno = dev - link->device; dev->devno = dev - link->device;
#ifdef CONFIG_ATA_ACPI
dev->gtf_filter = ata_acpi_gtf_filter;
#endif
ata_dev_init(dev); ata_dev_init(dev);
} }
} }
......
...@@ -2667,14 +2667,14 @@ int ata_eh_reset(struct ata_link *link, int classify, ...@@ -2667,14 +2667,14 @@ int ata_eh_reset(struct ata_link *link, int classify,
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
dev->flags &= ~ATA_DFLAG_SLEEPING; dev->flags &= ~ATA_DFLAG_SLEEPING;
if (!ata_phys_link_offline(ata_dev_phys_link(dev))) { if (ata_phys_link_offline(ata_dev_phys_link(dev)))
/* apply class override */ continue;
if (lflags & ATA_LFLAG_ASSUME_ATA)
classes[dev->devno] = ATA_DEV_ATA; /* apply class override */
else if (lflags & ATA_LFLAG_ASSUME_SEMB) if (lflags & ATA_LFLAG_ASSUME_ATA)
classes[dev->devno] = ATA_DEV_SEMB_UNSUP; classes[dev->devno] = ATA_DEV_ATA;
} else else if (lflags & ATA_LFLAG_ASSUME_SEMB)
classes[dev->devno] = ATA_DEV_NONE; classes[dev->devno] = ATA_DEV_SEMB_UNSUP;
} }
/* record current link speed */ /* record current link speed */
...@@ -2713,34 +2713,48 @@ int ata_eh_reset(struct ata_link *link, int classify, ...@@ -2713,34 +2713,48 @@ int ata_eh_reset(struct ata_link *link, int classify,
ap->pflags &= ~ATA_PFLAG_EH_PENDING; ap->pflags &= ~ATA_PFLAG_EH_PENDING;
spin_unlock_irqrestore(link->ap->lock, flags); spin_unlock_irqrestore(link->ap->lock, flags);
/* Make sure onlineness and classification result correspond. /*
* Make sure onlineness and classification result correspond.
* Hotplug could have happened during reset and some * Hotplug could have happened during reset and some
* controllers fail to wait while a drive is spinning up after * controllers fail to wait while a drive is spinning up after
* being hotplugged causing misdetection. By cross checking * being hotplugged causing misdetection. By cross checking
* link onlineness and classification result, those conditions * link on/offlineness and classification result, those
* can be reliably detected and retried. * conditions can be reliably detected and retried.
*/ */
nr_unknown = 0; nr_unknown = 0;
ata_for_each_dev(dev, link, ALL) { ata_for_each_dev(dev, link, ALL) {
/* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ if (ata_phys_link_online(ata_dev_phys_link(dev))) {
if (classes[dev->devno] == ATA_DEV_UNKNOWN) { if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
classes[dev->devno] = ATA_DEV_NONE; ata_dev_printk(dev, KERN_DEBUG, "link online "
if (ata_phys_link_online(ata_dev_phys_link(dev))) "but device misclassifed\n");
classes[dev->devno] = ATA_DEV_NONE;
nr_unknown++; nr_unknown++;
}
} else if (ata_phys_link_offline(ata_dev_phys_link(dev))) {
if (ata_class_enabled(classes[dev->devno]))
ata_dev_printk(dev, KERN_DEBUG, "link offline, "
"clearing class %d to NONE\n",
classes[dev->devno]);
classes[dev->devno] = ATA_DEV_NONE;
} else if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
ata_dev_printk(dev, KERN_DEBUG, "link status unknown, "
"clearing UNKNOWN to NONE\n");
classes[dev->devno] = ATA_DEV_NONE;
} }
} }
if (classify && nr_unknown) { if (classify && nr_unknown) {
if (try < max_tries) { if (try < max_tries) {
ata_link_printk(link, KERN_WARNING, "link online but " ata_link_printk(link, KERN_WARNING, "link online but "
"device misclassified, retrying\n"); "%d devices misclassified, retrying\n",
nr_unknown);
failed_link = link; failed_link = link;
rc = -EAGAIN; rc = -EAGAIN;
goto fail; goto fail;
} }
ata_link_printk(link, KERN_WARNING, ata_link_printk(link, KERN_WARNING,
"link online but device misclassified, " "link online but %d devices misclassified, "
"device detection might fail\n"); "device detection might fail\n", nr_unknown);
} }
/* reset successful, schedule revalidation */ /* reset successful, schedule revalidation */
......
...@@ -118,6 +118,8 @@ extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm); ...@@ -118,6 +118,8 @@ extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
/* libata-acpi.c */ /* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI #ifdef CONFIG_ATA_ACPI
extern unsigned int ata_acpi_gtf_filter;
extern void ata_acpi_associate_sata_port(struct ata_port *ap); extern void ata_acpi_associate_sata_port(struct ata_port *ap);
extern void ata_acpi_associate(struct ata_host *host); extern void ata_acpi_associate(struct ata_host *host);
extern void ata_acpi_dissociate(struct ata_host *host); extern void ata_acpi_dissociate(struct ata_host *host);
......
...@@ -290,7 +290,7 @@ static void ali_warn_atapi_dma(struct ata_device *adev) ...@@ -290,7 +290,7 @@ static void ali_warn_atapi_dma(struct ata_device *adev)
if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) { if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
ata_dev_printk(adev, KERN_WARNING, ata_dev_printk(adev, KERN_WARNING,
"WARNING: ATAPI DMA disabled for reliablity issues. It can be enabled\n"); "WARNING: ATAPI DMA disabled for reliability issues. It can be enabled\n");
ata_dev_printk(adev, KERN_WARNING, ata_dev_printk(adev, KERN_WARNING,
"WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n"); "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
} }
......
...@@ -118,20 +118,13 @@ struct atp867x_priv { ...@@ -118,20 +118,13 @@ struct atp867x_priv {
int pci66mhz; int pci66mhz;
}; };
static inline u8 atp867x_speed_to_mode(u8 speed)
{
return speed - XFER_UDMA_0 + 1;
}
static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev) static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{ {
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct atp867x_priv *dp = ap->private_data; struct atp867x_priv *dp = ap->private_data;
u8 speed = adev->dma_mode; u8 speed = adev->dma_mode;
u8 b; u8 b;
u8 mode; u8 mode = speed - XFER_UDMA_0 + 1;
mode = atp867x_speed_to_mode(speed);
/* /*
* Doc 6.6.9: decrease the udma mode value by 1 for safer UDMA speed * Doc 6.6.9: decrease the udma mode value by 1 for safer UDMA speed
...@@ -156,25 +149,38 @@ static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev) ...@@ -156,25 +149,38 @@ static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
iowrite8(b, dp->dma_mode); iowrite8(b, dp->dma_mode);
} }
static int atp867x_get_active_clocks_shifted(unsigned int clk) static int atp867x_get_active_clocks_shifted(struct ata_port *ap,
unsigned int clk)
{ {
struct atp867x_priv *dp = ap->private_data;
unsigned char clocks = clk; unsigned char clocks = clk;
/*
* Doc 6.6.9: increase the clock value by 1 for safer PIO speed
* on 66MHz bus
*/
if (dp->pci66mhz)
clocks++;
switch (clocks) { switch (clocks) {
case 0: case 0:
clocks = 1; clocks = 1;
break; break;
case 1 ... 7: case 1 ... 6:
break;
case 8 ... 12:
clocks = 7;
break; break;
default: default:
printk(KERN_WARNING "ATP867X: active %dclk is invalid. " printk(KERN_WARNING "ATP867X: active %dclk is invalid. "
"Using default 8clk.\n", clk); "Using 12clk.\n", clk);
clocks = 0; /* 8 clk */ case 9 ... 12:
clocks = 7; /* 12 clk */
break; break;
case 7:
case 8: /* default 8 clk */
clocks = 0;
goto active_clock_shift_done;
} }
active_clock_shift_done:
return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT; return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT;
} }
...@@ -188,20 +194,20 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk) ...@@ -188,20 +194,20 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk)
break; break;
case 1 ... 11: case 1 ... 11:
break; break;
case 12: case 13:
clocks = 0; case 14:
break; --clocks; /* by the spec */
case 13: case 14:
--clocks;
break; break;
case 15: case 15:
break; break;
default: default:
printk(KERN_WARNING "ATP867X: recover %dclk is invalid. " printk(KERN_WARNING "ATP867X: recover %dclk is invalid. "
"Using default 15clk.\n", clk); "Using default 12clk.\n", clk);
clocks = 0; /* 12 clk */ case 12: /* default 12 clk */
clocks = 0;
break; break;
} }
return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT; return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT;
} }
...@@ -230,25 +236,38 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev) ...@@ -230,25 +236,38 @@ static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev)
b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK); b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK);
iowrite8(b, dp->dma_mode); iowrite8(b, dp->dma_mode);
b = atp867x_get_active_clocks_shifted(t.active) | b = atp867x_get_active_clocks_shifted(ap, t.active) |
atp867x_get_recover_clocks_shifted(t.recover); atp867x_get_recover_clocks_shifted(t.recover);
if (dp->pci66mhz)
b += 0x10;
if (adev->devno & 1) if (adev->devno & 1)
iowrite8(b, dp->slave_piospd); iowrite8(b, dp->slave_piospd);
else else
iowrite8(b, dp->mstr_piospd); iowrite8(b, dp->mstr_piospd);
/* b = atp867x_get_active_clocks_shifted(ap, t.act8b) |
* use the same value for comand timing as for PIO timimg atp867x_get_recover_clocks_shifted(t.rec8b);
*/
iowrite8(b, dp->eightb_piospd); iowrite8(b, dp->eightb_piospd);
} }
static int atp867x_cable_override(struct pci_dev *pdev)
{
if (pdev->subsystem_vendor == PCI_VENDOR_ID_ARTOP &&
(pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867A ||
pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867B)) {
return 1;
}
return 0;
}
static int atp867x_cable_detect(struct ata_port *ap) static int atp867x_cable_detect(struct ata_port *ap)
{ {
return ATA_CBL_PATA40_SHORT; struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (atp867x_cable_override(pdev))
return ATA_CBL_PATA40_SHORT;
return ATA_CBL_PATA_UNK;
} }
static struct scsi_host_template atp867x_sht = { static struct scsi_host_template atp867x_sht = {
...@@ -471,7 +490,6 @@ static int atp867x_init_one(struct pci_dev *pdev, ...@@ -471,7 +490,6 @@ static int atp867x_init_one(struct pci_dev *pdev,
static const struct ata_port_info info_867x = { static const struct ata_port_info info_867x = {
.flags = ATA_FLAG_SLAVE_POSS, .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4, .pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &atp867x_ops, .port_ops = &atp867x_ops,
}; };
...@@ -515,6 +533,23 @@ static int atp867x_init_one(struct pci_dev *pdev, ...@@ -515,6 +533,23 @@ static int atp867x_init_one(struct pci_dev *pdev,
return rc; return rc;
} }
#ifdef CONFIG_PM
static int atp867x_reinit_one(struct pci_dev *pdev)
{
struct ata_host *host = dev_get_drvdata(&pdev->dev);
int rc;
rc = ata_pci_device_do_resume(pdev);
if (rc)
return rc;
atp867x_fixup(host);
ata_host_resume(host);
return 0;
}
#endif
static struct pci_device_id atp867x_pci_tbl[] = { static struct pci_device_id atp867x_pci_tbl[] = {
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A), 0 }, { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A), 0 },
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B), 0 }, { PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B), 0 },
...@@ -526,6 +561,10 @@ static struct pci_driver atp867x_driver = { ...@@ -526,6 +561,10 @@ static struct pci_driver atp867x_driver = {
.id_table = atp867x_pci_tbl, .id_table = atp867x_pci_tbl,
.probe = atp867x_init_one, .probe = atp867x_init_one,
.remove = ata_pci_remove_one, .remove = ata_pci_remove_one,
#ifdef CONFIG_PM
.suspend = ata_pci_device_suspend,
.resume = atp867x_reinit_one,
#endif
}; };
static int __init atp867x_init(void) static int __init atp867x_init(void)
......
...@@ -334,9 +334,12 @@ enum { ...@@ -334,9 +334,12 @@ enum {
SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */ SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */
/* SETFEATURE Sector counts for SATA features */ /* SETFEATURE Sector counts for SATA features */
SATA_AN = 0x05, /* Asynchronous Notification */ SATA_FPDMA_OFFSET = 0x01, /* FPDMA non-zero buffer offsets */
SATA_DIPM = 0x03, /* Device Initiated Power Management */ SATA_FPDMA_AA = 0x02, /* FPDMA Setup FIS Auto-Activate */
SATA_FPDMA_AA = 0x02, /* DMA Setup FIS Auto-Activate */ SATA_DIPM = 0x03, /* Device Initiated Power Management */
SATA_FPDMA_IN_ORDER = 0x04, /* FPDMA in-order data delivery */
SATA_AN = 0x05, /* Asynchronous Notification */
SATA_SSP = 0x06, /* Software Settings Preservation */
/* feature values for SET_MAX */ /* feature values for SET_MAX */
ATA_SET_MAX_ADDR = 0x00, ATA_SET_MAX_ADDR = 0x00,
......
...@@ -418,6 +418,17 @@ enum { ...@@ -418,6 +418,17 @@ enum {
ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER | ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
ATA_TIMING_DMACK_HOLD | ATA_TIMING_CYCLE | ATA_TIMING_DMACK_HOLD | ATA_TIMING_CYCLE |
ATA_TIMING_UDMA, ATA_TIMING_UDMA,
/* ACPI constants */
ATA_ACPI_FILTER_SETXFER = 1 << 0,
ATA_ACPI_FILTER_LOCK = 1 << 1,
ATA_ACPI_FILTER_DIPM = 1 << 2,
ATA_ACPI_FILTER_FPDMA_OFFSET = 1 << 3, /* FPDMA non-zero offset */
ATA_ACPI_FILTER_FPDMA_AA = 1 << 4, /* FPDMA auto activate */
ATA_ACPI_FILTER_DEFAULT = ATA_ACPI_FILTER_SETXFER |
ATA_ACPI_FILTER_LOCK |
ATA_ACPI_FILTER_DIPM,
}; };
enum ata_xfer_mask { enum ata_xfer_mask {
...@@ -587,6 +598,7 @@ struct ata_device { ...@@ -587,6 +598,7 @@ struct ata_device {
#ifdef CONFIG_ATA_ACPI #ifdef CONFIG_ATA_ACPI
acpi_handle acpi_handle; acpi_handle acpi_handle;
union acpi_object *gtf_cache; union acpi_object *gtf_cache;
unsigned int gtf_filter;
#endif #endif
/* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */ /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
u64 n_sectors; /* size of device, if ATA */ u64 n_sectors; /* size of device, if ATA */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment