diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 132 |
1 files changed, 102 insertions, 30 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index e3a92a6da39a..c81d809c111b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -61,6 +61,7 @@ enum board_ids { | |||
61 | /* board IDs by feature in alphabetical order */ | 61 | /* board IDs by feature in alphabetical order */ |
62 | board_ahci, | 62 | board_ahci, |
63 | board_ahci_ign_iferr, | 63 | board_ahci_ign_iferr, |
64 | board_ahci_noncq, | ||
64 | board_ahci_nosntf, | 65 | board_ahci_nosntf, |
65 | board_ahci_yes_fbs, | 66 | board_ahci_yes_fbs, |
66 | 67 | ||
@@ -83,6 +84,8 @@ enum board_ids { | |||
83 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 84 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
84 | static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, | 85 | static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, |
85 | unsigned long deadline); | 86 | unsigned long deadline); |
87 | static void ahci_mcp89_apple_enable(struct pci_dev *pdev); | ||
88 | static bool is_mcp89_apple(struct pci_dev *pdev); | ||
86 | static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, | 89 | static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, |
87 | unsigned long deadline); | 90 | unsigned long deadline); |
88 | #ifdef CONFIG_PM | 91 | #ifdef CONFIG_PM |
@@ -119,6 +122,13 @@ static const struct ata_port_info ahci_port_info[] = { | |||
119 | .udma_mask = ATA_UDMA6, | 122 | .udma_mask = ATA_UDMA6, |
120 | .port_ops = &ahci_ops, | 123 | .port_ops = &ahci_ops, |
121 | }, | 124 | }, |
125 | [board_ahci_noncq] = { | ||
126 | AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), | ||
127 | .flags = AHCI_FLAG_COMMON, | ||
128 | .pio_mask = ATA_PIO4, | ||
129 | .udma_mask = ATA_UDMA6, | ||
130 | .port_ops = &ahci_ops, | ||
131 | }, | ||
122 | [board_ahci_nosntf] = { | 132 | [board_ahci_nosntf] = { |
123 | AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), | 133 | AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), |
124 | .flags = AHCI_FLAG_COMMON, | 134 | .flags = AHCI_FLAG_COMMON, |
@@ -450,6 +460,12 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
450 | { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ | 460 | { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ |
451 | { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ | 461 | { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ |
452 | 462 | ||
463 | /* | ||
464 | * Samsung SSDs found on some macbooks. NCQ times out. | ||
465 | * https://bugzilla.kernel.org/show_bug.cgi?id=60731 | ||
466 | */ | ||
467 | { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq }, | ||
468 | |||
453 | /* Enmotus */ | 469 | /* Enmotus */ |
454 | { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, | 470 | { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, |
455 | 471 | ||
@@ -664,6 +680,10 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) | |||
664 | if (rc) | 680 | if (rc) |
665 | return rc; | 681 | return rc; |
666 | 682 | ||
683 | /* Apple BIOS helpfully mangles the registers on resume */ | ||
684 | if (is_mcp89_apple(pdev)) | ||
685 | ahci_mcp89_apple_enable(pdev); | ||
686 | |||
667 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { | 687 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { |
668 | rc = ahci_pci_reset_controller(host); | 688 | rc = ahci_pci_reset_controller(host); |
669 | if (rc) | 689 | if (rc) |
@@ -780,6 +800,48 @@ static void ahci_p5wdh_workaround(struct ata_host *host) | |||
780 | } | 800 | } |
781 | } | 801 | } |
782 | 802 | ||
803 | /* | ||
804 | * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when | ||
805 | * booting in BIOS compatibility mode. We restore the registers but not ID. | ||
806 | */ | ||
807 | static void ahci_mcp89_apple_enable(struct pci_dev *pdev) | ||
808 | { | ||
809 | u32 val; | ||
810 | |||
811 | printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); | ||
812 | |||
813 | pci_read_config_dword(pdev, 0xf8, &val); | ||
814 | val |= 1 << 0x1b; | ||
815 | /* the following changes the device ID, but appears not to affect function */ | ||
816 | /* val = (val & ~0xf0000000) | 0x80000000; */ | ||
817 | pci_write_config_dword(pdev, 0xf8, val); | ||
818 | |||
819 | pci_read_config_dword(pdev, 0x54c, &val); | ||
820 | val |= 1 << 0xc; | ||
821 | pci_write_config_dword(pdev, 0x54c, val); | ||
822 | |||
823 | pci_read_config_dword(pdev, 0x4a4, &val); | ||
824 | val &= 0xff; | ||
825 | val |= 0x01060100; | ||
826 | pci_write_config_dword(pdev, 0x4a4, val); | ||
827 | |||
828 | pci_read_config_dword(pdev, 0x54c, &val); | ||
829 | val &= ~(1 << 0xc); | ||
830 | pci_write_config_dword(pdev, 0x54c, val); | ||
831 | |||
832 | pci_read_config_dword(pdev, 0xf8, &val); | ||
833 | val &= ~(1 << 0x1b); | ||
834 | pci_write_config_dword(pdev, 0xf8, val); | ||
835 | } | ||
836 | |||
837 | static bool is_mcp89_apple(struct pci_dev *pdev) | ||
838 | { | ||
839 | return pdev->vendor == PCI_VENDOR_ID_NVIDIA && | ||
840 | pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && | ||
841 | pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && | ||
842 | pdev->subsystem_device == 0xcb89; | ||
843 | } | ||
844 | |||
783 | /* only some SB600 ahci controllers can do 64bit DMA */ | 845 | /* only some SB600 ahci controllers can do 64bit DMA */ |
784 | static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) | 846 | static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) |
785 | { | 847 | { |
@@ -1100,26 +1162,42 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) | |||
1100 | {} | 1162 | {} |
1101 | #endif | 1163 | #endif |
1102 | 1164 | ||
1103 | int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv) | 1165 | static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, |
1166 | struct ahci_host_priv *hpriv) | ||
1104 | { | 1167 | { |
1105 | int rc; | 1168 | int rc, nvec; |
1106 | unsigned int maxvec; | ||
1107 | 1169 | ||
1108 | if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) { | 1170 | if (hpriv->flags & AHCI_HFLAG_NO_MSI) |
1109 | rc = pci_enable_msi_block_auto(pdev, &maxvec); | 1171 | goto intx; |
1110 | if (rc > 0) { | 1172 | |
1111 | if ((rc == maxvec) || (rc == 1)) | 1173 | rc = pci_msi_vec_count(pdev); |
1112 | return rc; | 1174 | if (rc < 0) |
1113 | /* | 1175 | goto intx; |
1114 | * Assume that advantage of multipe MSIs is negated, | 1176 | |
1115 | * so fallback to single MSI mode to save resources | 1177 | /* |
1116 | */ | 1178 | * If number of MSIs is less than number of ports then Sharing Last |
1117 | pci_disable_msi(pdev); | 1179 | * Message mode could be enforced. In this case assume that advantage |
1118 | if (!pci_enable_msi(pdev)) | 1180 | * of multipe MSIs is negated and use single MSI mode instead. |
1119 | return 1; | 1181 | */ |
1120 | } | 1182 | if (rc < n_ports) |
1121 | } | 1183 | goto single_msi; |
1184 | |||
1185 | nvec = rc; | ||
1186 | rc = pci_enable_msi_block(pdev, nvec); | ||
1187 | if (rc < 0) | ||
1188 | goto intx; | ||
1189 | else if (rc > 0) | ||
1190 | goto single_msi; | ||
1191 | |||
1192 | return nvec; | ||
1122 | 1193 | ||
1194 | single_msi: | ||
1195 | rc = pci_enable_msi(pdev); | ||
1196 | if (rc) | ||
1197 | goto intx; | ||
1198 | return 1; | ||
1199 | |||
1200 | intx: | ||
1123 | pci_intx(pdev, 1); | 1201 | pci_intx(pdev, 1); |
1124 | return 0; | 1202 | return 0; |
1125 | } | 1203 | } |
@@ -1212,15 +1290,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1212 | if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) | 1290 | if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) |
1213 | return -ENODEV; | 1291 | return -ENODEV; |
1214 | 1292 | ||
1215 | /* | 1293 | /* Apple BIOS on MCP89 prevents us using AHCI */ |
1216 | * For some reason, MCP89 on MacBook 7,1 doesn't work with | 1294 | if (is_mcp89_apple(pdev)) |
1217 | * ahci, use ata_generic instead. | 1295 | ahci_mcp89_apple_enable(pdev); |
1218 | */ | ||
1219 | if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && | ||
1220 | pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && | ||
1221 | pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && | ||
1222 | pdev->subsystem_device == 0xcb89) | ||
1223 | return -ENODEV; | ||
1224 | 1296 | ||
1225 | /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. | 1297 | /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. |
1226 | * At the moment, we can only use the AHCI mode. Let the users know | 1298 | * At the moment, we can only use the AHCI mode. Let the users know |
@@ -1286,10 +1358,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1286 | 1358 | ||
1287 | hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; | 1359 | hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; |
1288 | 1360 | ||
1289 | n_msis = ahci_init_interrupts(pdev, hpriv); | ||
1290 | if (n_msis > 1) | ||
1291 | hpriv->flags |= AHCI_HFLAG_MULTI_MSI; | ||
1292 | |||
1293 | /* save initial config */ | 1361 | /* save initial config */ |
1294 | ahci_pci_save_initial_config(pdev, hpriv); | 1362 | ahci_pci_save_initial_config(pdev, hpriv); |
1295 | 1363 | ||
@@ -1344,6 +1412,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1344 | */ | 1412 | */ |
1345 | n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); | 1413 | n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); |
1346 | 1414 | ||
1415 | n_msis = ahci_init_interrupts(pdev, n_ports, hpriv); | ||
1416 | if (n_msis > 1) | ||
1417 | hpriv->flags |= AHCI_HFLAG_MULTI_MSI; | ||
1418 | |||
1347 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); | 1419 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); |
1348 | if (!host) | 1420 | if (!host) |
1349 | return -ENOMEM; | 1421 | return -ENOMEM; |