Comment 3 for bug 817017

Greg White (gwhite-kupulau) wrote :

This is in drivers/pci/quirks.c. Note that to activate it, you use mbp_force_ahci=1 on the kernel command line. Also note that, IIRC, earlier MBP's required a 0x40 instead of a 0x60 written to config word 0x90.

static bool mbp_force_ahci;
module_param(mbp_force_ahci, bool, 0444);
MODULE_PARM_DESC(mbp_force_ahci, "AHCI mode for MacBook Pro");

static bool quirk_mbp_sata_dev(struct pci_dev *pdev)
{
 printk(KERN_INFO "Quirking ahci device %04x:%04x\n", pdev->vendor, pdev->device);
 pci_write_config_word(pdev, 0x90, 0x60); /* AHCI - 6 ports enabled */
 pdev->class = PCI_CLASS_STORAGE_SATA_AHCI;
 // pci_write_config_dword(pdev, 0x9c, 0);
 pci_write_config_byte(pdev, PCI_CLASS_PROG, 0x01);
 pci_write_config_byte(pdev, PCI_CLASS_DEVICE, 0x06);
   /* The PCI device ID will have been changed */
 pci_read_config_word(pdev, PCI_DEVICE_ID, &pdev->device);
 printk(KERN_DEBUG "ICH AHCI quirk: SATA AHCI controller has device ID %04x:%04x\n", pdev->vendor, pdev->device);
 return false;
}

static void quirk_mbp_sata(struct pci_dev *pdev)
{
 int ret = 0;

 if (!mbp_force_ahci)
  return;

 if (quirk_mbp_sata_dev(pdev))
  return; /* nothing to do */

 /* Try to allocate the resource on BAR 5.
  * If we have a bad alignment, don't even try,
  * thus neatly avoiding a scary warning.
  */
 if (pci_resource_alignment(pdev, &pdev->resource[5]))
  ret = pci_assign_resource(pdev, 5);
 if (!ret) {
  printk (KERN_INFO "Quirked ICH SATA controller to AHCI mode\n");
  return;
 }
 mbp_force_ahci = 0;
 printk (KERN_ERR "MBP ICH AHCI quirk: pci_assign_resource returned %d\n", ret);
}

/* On resume, the device will have been reset to IDE mode, so we need to re-quirk */
static void quirk_mbp_sata_resume(struct pci_dev *pdev)
{
 if (mbp_force_ahci && !quirk_mbp_sata_dev(pdev)) {
  pci_update_resource(pdev, 5);
  printk (KERN_INFO "Re-quirked ICH SATA controller to AHCI mode\n");
 }
}

DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3b28, quirk_mbp_sata); /* MacBook Pro (6,1) force AHCI */
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x3b29, quirk_mbp_sata_resume); /* MacBook Pro (6,1) force AHCI on resume. Note that the original quirk will have changed the device ID */

DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3b20, quirk_mbp_sata); /* iMac 11,1 force AHCI */
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x3b22, quirk_mbp_sata_resume); /* iMac 11,1 force AHCI on resume. Note that the original quirk will have changed the device ID */

DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1c01, quirk_mbp_sata); /* iMac 8,1 force AHCI */
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x1c03, quirk_mbp_sata_resume); /* iMac 8,1 force AHCI on resume. Note that the original quirk will have changed the device ID */

--------------------------------------------------------------------------------------------------------------------------------- CUT HERE ------------------------------------------

And this is in drivers/pci/pci-driver.c. Note that I have swapped the fixup and resume.

static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
{
        pci_fixup_device(pci_fixup_resume_early, pci_dev);
        pci_restore_standard_config(pci_dev);
}