Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ahci: mcp89: enter AHCI mode under Apple BIOS emulation

Apple's BIOS emulation forcibly disables MCP89 AHCI, eg. on Macbook7,1.
We can re-enable it, replacing the previous workaround of using
ata_generic.

tj: whitespace adjustments, dropped inline from is_mcp89_apple()

Signed-off-by: James Laird <jhl@mafipulation.org>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

James Laird and committed by
Tejun Heo
cb85696d 462098b0

+51 -16
+51 -9
drivers/ata/ahci.c
··· 83 83 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 84 84 static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 85 85 unsigned long deadline); 86 + static void ahci_mcp89_apple_enable(struct pci_dev *pdev); 87 + static bool is_mcp89_apple(struct pci_dev *pdev); 86 88 static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 87 89 unsigned long deadline); 88 90 #ifdef CONFIG_PM ··· 661 659 if (rc) 662 660 return rc; 663 661 662 + /* Apple BIOS helpfully mangles the registers on resume */ 663 + if (is_mcp89_apple(pdev)) 664 + ahci_mcp89_apple_enable(pdev); 665 + 664 666 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 665 667 rc = ahci_pci_reset_controller(host); 666 668 if (rc) ··· 779 773 ap->ops = &ahci_p5wdh_ops; 780 774 ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 781 775 } 776 + } 777 + 778 + /* 779 + * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 780 + * booting in BIOS compatibility mode. We restore the registers but not ID. 781 + */ 782 + static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 783 + { 784 + u32 val; 785 + 786 + printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 787 + 788 + pci_read_config_dword(pdev, 0xf8, &val); 789 + val |= 1 << 0x1b; 790 + /* the following changes the device ID, but appears not to affect function */ 791 + /* val = (val & ~0xf0000000) | 0x80000000; */ 792 + pci_write_config_dword(pdev, 0xf8, val); 793 + 794 + pci_read_config_dword(pdev, 0x54c, &val); 795 + val |= 1 << 0xc; 796 + pci_write_config_dword(pdev, 0x54c, val); 797 + 798 + pci_read_config_dword(pdev, 0x4a4, &val); 799 + val &= 0xff; 800 + val |= 0x01060100; 801 + pci_write_config_dword(pdev, 0x4a4, val); 802 + 803 + pci_read_config_dword(pdev, 0x54c, &val); 804 + val &= ~(1 << 0xc); 805 + pci_write_config_dword(pdev, 0x54c, val); 806 + 807 + pci_read_config_dword(pdev, 0xf8, &val); 808 + val &= ~(1 << 0x1b); 809 + pci_write_config_dword(pdev, 0xf8, val); 810 + } 811 + 812 + static bool is_mcp89_apple(struct pci_dev *pdev) 813 + { 814 + return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 815 + pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 816 + pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 817 + pdev->subsystem_device == 0xcb89; 782 818 } 783 819 784 820 /* only some SB600 ahci controllers can do 64bit DMA */ ··· 1255 1207 if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 1256 1208 return -ENODEV; 1257 1209 1258 - /* 1259 - * For some reason, MCP89 on MacBook 7,1 doesn't work with 1260 - * ahci, use ata_generic instead. 1261 - */ 1262 - if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && 1263 - pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 1264 - pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 1265 - pdev->subsystem_device == 0xcb89) 1266 - return -ENODEV; 1210 + /* Apple BIOS on MCP89 prevents us using AHCI */ 1211 + if (is_mcp89_apple(pdev)) 1212 + ahci_mcp89_apple_enable(pdev); 1267 1213 1268 1214 /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 1269 1215 * At the moment, we can only use the AHCI mode. Let the users know
-7
drivers/ata/ata_generic.c
··· 221 221 { PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), }, 222 222 { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), 223 223 .driver_data = ATA_GEN_FORCE_DMA }, 224 - /* 225 - * For some reason, MCP89 on MacBook 7,1 doesn't work with 226 - * ahci, use ata_generic instead. 227 - */ 228 - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA, 229 - PCI_VENDOR_ID_APPLE, 0xcb89, 230 - .driver_data = ATA_GEN_FORCE_DMA }, 231 224 #if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE) 232 225 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), }, 233 226 { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },