diff options
| -rw-r--r-- | drivers/ata/ahci.c | 86 |
1 files changed, 66 insertions, 20 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index c95015986c94..a47d309df2f2 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -122,6 +122,7 @@ enum { | |||
| 122 | HOST_VERSION = 0x10, /* AHCI spec. version compliancy */ | 122 | HOST_VERSION = 0x10, /* AHCI spec. version compliancy */ |
| 123 | HOST_EM_LOC = 0x1c, /* Enclosure Management location */ | 123 | HOST_EM_LOC = 0x1c, /* Enclosure Management location */ |
| 124 | HOST_EM_CTL = 0x20, /* Enclosure Management Control */ | 124 | HOST_EM_CTL = 0x20, /* Enclosure Management Control */ |
| 125 | HOST_CAP2 = 0x24, /* host capabilities, extended */ | ||
| 125 | 126 | ||
| 126 | /* HOST_CTL bits */ | 127 | /* HOST_CTL bits */ |
| 127 | HOST_RESET = (1 << 0), /* reset controller; self-clear */ | 128 | HOST_RESET = (1 << 0), /* reset controller; self-clear */ |
| @@ -129,16 +130,29 @@ enum { | |||
| 129 | HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ | 130 | HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ |
| 130 | 131 | ||
| 131 | /* HOST_CAP bits */ | 132 | /* HOST_CAP bits */ |
| 133 | HOST_CAP_SXS = (1 << 5), /* Supports External SATA */ | ||
| 132 | HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */ | 134 | HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */ |
| 133 | HOST_CAP_SSC = (1 << 14), /* Slumber capable */ | 135 | HOST_CAP_CCC = (1 << 7), /* Command Completion Coalescing */ |
| 136 | HOST_CAP_PART = (1 << 13), /* Partial state capable */ | ||
| 137 | HOST_CAP_SSC = (1 << 14), /* Slumber state capable */ | ||
| 138 | HOST_CAP_PIO_MULTI = (1 << 15), /* PIO multiple DRQ support */ | ||
| 139 | HOST_CAP_FBS = (1 << 16), /* FIS-based switching support */ | ||
| 134 | HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ | 140 | HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ |
| 141 | HOST_CAP_ONLY = (1 << 18), /* Supports AHCI mode only */ | ||
| 135 | HOST_CAP_CLO = (1 << 24), /* Command List Override support */ | 142 | HOST_CAP_CLO = (1 << 24), /* Command List Override support */ |
| 143 | HOST_CAP_LED = (1 << 25), /* Supports activity LED */ | ||
| 136 | HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */ | 144 | HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */ |
| 137 | HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ | 145 | HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ |
| 146 | HOST_CAP_MPS = (1 << 28), /* Mechanical presence switch */ | ||
| 138 | HOST_CAP_SNTF = (1 << 29), /* SNotification register */ | 147 | HOST_CAP_SNTF = (1 << 29), /* SNotification register */ |
| 139 | HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ | 148 | HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ |
| 140 | HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ | 149 | HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ |
| 141 | 150 | ||
| 151 | /* HOST_CAP2 bits */ | ||
| 152 | HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */ | ||
| 153 | HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */ | ||
| 154 | HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */ | ||
| 155 | |||
| 142 | /* registers for each SATA port */ | 156 | /* registers for each SATA port */ |
| 143 | PORT_LST_ADDR = 0x00, /* command list DMA addr */ | 157 | PORT_LST_ADDR = 0x00, /* command list DMA addr */ |
| 144 | PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */ | 158 | PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */ |
| @@ -267,8 +281,10 @@ struct ahci_em_priv { | |||
| 267 | struct ahci_host_priv { | 281 | struct ahci_host_priv { |
| 268 | unsigned int flags; /* AHCI_HFLAG_* */ | 282 | unsigned int flags; /* AHCI_HFLAG_* */ |
| 269 | u32 cap; /* cap to use */ | 283 | u32 cap; /* cap to use */ |
| 284 | u32 cap2; /* cap2 to use */ | ||
| 270 | u32 port_map; /* port map to use */ | 285 | u32 port_map; /* port map to use */ |
| 271 | u32 saved_cap; /* saved initial cap */ | 286 | u32 saved_cap; /* saved initial cap */ |
| 287 | u32 saved_cap2; /* saved initial cap2 */ | ||
| 272 | u32 saved_port_map; /* saved initial port_map */ | 288 | u32 saved_port_map; /* saved initial port_map */ |
| 273 | u32 em_loc; /* enclosure management location */ | 289 | u32 em_loc; /* enclosure management location */ |
| 274 | }; | 290 | }; |
| @@ -331,12 +347,15 @@ static void ahci_init_sw_activity(struct ata_link *link); | |||
| 331 | 347 | ||
| 332 | static ssize_t ahci_show_host_caps(struct device *dev, | 348 | static ssize_t ahci_show_host_caps(struct device *dev, |
| 333 | struct device_attribute *attr, char *buf); | 349 | struct device_attribute *attr, char *buf); |
| 350 | static ssize_t ahci_show_host_cap2(struct device *dev, | ||
| 351 | struct device_attribute *attr, char *buf); | ||
| 334 | static ssize_t ahci_show_host_version(struct device *dev, | 352 | static ssize_t ahci_show_host_version(struct device *dev, |
| 335 | struct device_attribute *attr, char *buf); | 353 | struct device_attribute *attr, char *buf); |
| 336 | static ssize_t ahci_show_port_cmd(struct device *dev, | 354 | static ssize_t ahci_show_port_cmd(struct device *dev, |
| 337 | struct device_attribute *attr, char *buf); | 355 | struct device_attribute *attr, char *buf); |
| 338 | 356 | ||
| 339 | DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); | 357 | DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); |
| 358 | DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL); | ||
| 340 | DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); | 359 | DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); |
| 341 | DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); | 360 | DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); |
| 342 | 361 | ||
| @@ -345,6 +364,7 @@ static struct device_attribute *ahci_shost_attrs[] = { | |||
| 345 | &dev_attr_em_message_type, | 364 | &dev_attr_em_message_type, |
| 346 | &dev_attr_em_message, | 365 | &dev_attr_em_message, |
| 347 | &dev_attr_ahci_host_caps, | 366 | &dev_attr_ahci_host_caps, |
| 367 | &dev_attr_ahci_host_cap2, | ||
| 348 | &dev_attr_ahci_host_version, | 368 | &dev_attr_ahci_host_version, |
| 349 | &dev_attr_ahci_port_cmd, | 369 | &dev_attr_ahci_port_cmd, |
| 350 | NULL | 370 | NULL |
| @@ -733,6 +753,16 @@ static ssize_t ahci_show_host_caps(struct device *dev, | |||
| 733 | return sprintf(buf, "%x\n", hpriv->cap); | 753 | return sprintf(buf, "%x\n", hpriv->cap); |
| 734 | } | 754 | } |
| 735 | 755 | ||
| 756 | static ssize_t ahci_show_host_cap2(struct device *dev, | ||
| 757 | struct device_attribute *attr, char *buf) | ||
| 758 | { | ||
| 759 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 760 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 761 | struct ahci_host_priv *hpriv = ap->host->private_data; | ||
| 762 | |||
| 763 | return sprintf(buf, "%x\n", hpriv->cap2); | ||
| 764 | } | ||
| 765 | |||
| 736 | static ssize_t ahci_show_host_version(struct device *dev, | 766 | static ssize_t ahci_show_host_version(struct device *dev, |
| 737 | struct device_attribute *attr, char *buf) | 767 | struct device_attribute *attr, char *buf) |
| 738 | { | 768 | { |
| @@ -772,7 +802,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev, | |||
| 772 | struct ahci_host_priv *hpriv) | 802 | struct ahci_host_priv *hpriv) |
| 773 | { | 803 | { |
| 774 | void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; | 804 | void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; |
| 775 | u32 cap, port_map; | 805 | u32 cap, cap2, vers, port_map; |
| 776 | int i; | 806 | int i; |
| 777 | int mv; | 807 | int mv; |
| 778 | 808 | ||
| @@ -785,6 +815,14 @@ static void ahci_save_initial_config(struct pci_dev *pdev, | |||
| 785 | hpriv->saved_cap = cap = readl(mmio + HOST_CAP); | 815 | hpriv->saved_cap = cap = readl(mmio + HOST_CAP); |
| 786 | hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL); | 816 | hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL); |
| 787 | 817 | ||
| 818 | /* CAP2 register is only defined for AHCI 1.2 and later */ | ||
| 819 | vers = readl(mmio + HOST_VERSION); | ||
| 820 | if ((vers >> 16) > 1 || | ||
| 821 | ((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200)) | ||
| 822 | hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2); | ||
| 823 | else | ||
| 824 | hpriv->saved_cap2 = cap2 = 0; | ||
| 825 | |||
| 788 | /* some chips have errata preventing 64bit use */ | 826 | /* some chips have errata preventing 64bit use */ |
| 789 | if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) { | 827 | if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) { |
| 790 | dev_printk(KERN_INFO, &pdev->dev, | 828 | dev_printk(KERN_INFO, &pdev->dev, |
| @@ -870,6 +908,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev, | |||
| 870 | 908 | ||
| 871 | /* record values to use during operation */ | 909 | /* record values to use during operation */ |
| 872 | hpriv->cap = cap; | 910 | hpriv->cap = cap; |
| 911 | hpriv->cap2 = cap2; | ||
| 873 | hpriv->port_map = port_map; | 912 | hpriv->port_map = port_map; |
| 874 | } | 913 | } |
| 875 | 914 | ||
| @@ -888,6 +927,8 @@ static void ahci_restore_initial_config(struct ata_host *host) | |||
| 888 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; | 927 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; |
| 889 | 928 | ||
| 890 | writel(hpriv->saved_cap, mmio + HOST_CAP); | 929 | writel(hpriv->saved_cap, mmio + HOST_CAP); |
| 930 | if (hpriv->saved_cap2) | ||
| 931 | writel(hpriv->saved_cap2, mmio + HOST_CAP2); | ||
| 891 | writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL); | 932 | writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL); |
| 892 | (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ | 933 | (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ |
| 893 | } | 934 | } |
| @@ -2535,13 +2576,14 @@ static void ahci_print_info(struct ata_host *host) | |||
| 2535 | struct ahci_host_priv *hpriv = host->private_data; | 2576 | struct ahci_host_priv *hpriv = host->private_data; |
| 2536 | struct pci_dev *pdev = to_pci_dev(host->dev); | 2577 | struct pci_dev *pdev = to_pci_dev(host->dev); |
| 2537 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; | 2578 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; |
| 2538 | u32 vers, cap, impl, speed; | 2579 | u32 vers, cap, cap2, impl, speed; |
| 2539 | const char *speed_s; | 2580 | const char *speed_s; |
| 2540 | u16 cc; | 2581 | u16 cc; |
| 2541 | const char *scc_s; | 2582 | const char *scc_s; |
| 2542 | 2583 | ||
| 2543 | vers = readl(mmio + HOST_VERSION); | 2584 | vers = readl(mmio + HOST_VERSION); |
| 2544 | cap = hpriv->cap; | 2585 | cap = hpriv->cap; |
| 2586 | cap2 = hpriv->cap2; | ||
| 2545 | impl = hpriv->port_map; | 2587 | impl = hpriv->port_map; |
| 2546 | 2588 | ||
| 2547 | speed = (cap >> 20) & 0xf; | 2589 | speed = (cap >> 20) & 0xf; |
| @@ -2584,25 +2626,29 @@ static void ahci_print_info(struct ata_host *host) | |||
| 2584 | "flags: " | 2626 | "flags: " |
| 2585 | "%s%s%s%s%s%s%s" | 2627 | "%s%s%s%s%s%s%s" |
| 2586 | "%s%s%s%s%s%s%s" | 2628 | "%s%s%s%s%s%s%s" |
| 2587 | "%s\n" | 2629 | "%s%s%s%s%s%s\n" |
| 2588 | , | 2630 | , |
| 2589 | 2631 | ||
| 2590 | cap & (1 << 31) ? "64bit " : "", | 2632 | cap & HOST_CAP_64 ? "64bit " : "", |
| 2591 | cap & (1 << 30) ? "ncq " : "", | 2633 | cap & HOST_CAP_NCQ ? "ncq " : "", |
| 2592 | cap & (1 << 29) ? "sntf " : "", | 2634 | cap & HOST_CAP_SNTF ? "sntf " : "", |
| 2593 | cap & (1 << 28) ? "ilck " : "", | 2635 | cap & HOST_CAP_MPS ? "ilck " : "", |
| 2594 | cap & (1 << 27) ? "stag " : "", | 2636 | cap & HOST_CAP_SSS ? "stag " : "", |
| 2595 | cap & (1 << 26) ? "pm " : "", | 2637 | cap & HOST_CAP_ALPM ? "pm " : "", |
| 2596 | cap & (1 << 25) ? "led " : "", | 2638 | cap & HOST_CAP_LED ? "led " : "", |
| 2597 | 2639 | cap & HOST_CAP_CLO ? "clo " : "", | |
| 2598 | cap & (1 << 24) ? "clo " : "", | 2640 | cap & HOST_CAP_ONLY ? "only " : "", |
| 2599 | cap & (1 << 19) ? "nz " : "", | 2641 | cap & HOST_CAP_PMP ? "pmp " : "", |
| 2600 | cap & (1 << 18) ? "only " : "", | 2642 | cap & HOST_CAP_FBS ? "fbs " : "", |
| 2601 | cap & (1 << 17) ? "pmp " : "", | 2643 | cap & HOST_CAP_PIO_MULTI ? "pio " : "", |
| 2602 | cap & (1 << 15) ? "pio " : "", | 2644 | cap & HOST_CAP_SSC ? "slum " : "", |
| 2603 | cap & (1 << 14) ? "slum " : "", | 2645 | cap & HOST_CAP_PART ? "part " : "", |
| 2604 | cap & (1 << 13) ? "part " : "", | 2646 | cap & HOST_CAP_CCC ? "ccc " : "", |
| 2605 | cap & (1 << 6) ? "ems ": "" | 2647 | cap & HOST_CAP_EMS ? "ems " : "", |
| 2648 | cap & HOST_CAP_SXS ? "sxs " : "", | ||
| 2649 | cap2 & HOST_CAP2_APST ? "apst " : "", | ||
| 2650 | cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "", | ||
| 2651 | cap2 & HOST_CAP2_BOH ? "boh " : "" | ||
| 2606 | ); | 2652 | ); |
| 2607 | } | 2653 | } |
| 2608 | 2654 | ||
