Commit 5b66c829 authored by Alan Cox's avatar Alan Cox Committed by Jeff Garzik

ahci, pata_marvell: play nicely together

I've been chasing Jeff about this for months.  Jeff added the Marvell
device identifiers to the ahci driver without making the AHCI driver
handle the PATA port. This means a lot of users can't use current
kernels and in most distro cases can't even install.

This has been going on since March 2008 for the 6121 Marvell, and late 2007
for the 6145!!!

This was all pointed out at the time and repeatedly ignored. Bugs assigned
to Jeff about this are ignored also.

To quote Jeff in email

> "Just switch the order of 'ahci' and 'pata_marvell' in
> /etc/modprobe.conf, then use Fedora's tools regenerate the initrd.

> See?  It's not rocket science, and the current configuration can be
> easily made to work for Fedora users."

(Which isn't trivial, isn't end user, shouldn't be needed, and as it usually
breaks at install time is in fact impossible)

To quote Jeff in August 2007

> "   mv-ahci-pata
> Marvell 6121/6141 PATA support.  Needs fixing in the 'PATA controller
> command' area before it is usable, and can go upstream."

Only he add the ids anyway later and caused regressions, adding a further
id in March causing more regresions.

The actual fix for the moment is very simple. If the user has included
the pata_marvell driver let it drive the ports. If they've only selected
for SATA support give them the AHCI driver which will run the port a fraction
faster. Allow the user to control this decision via ahci.marvell_enable as
a module parameter so that distributions can ship 'it works' defaults and
smarter users (or config tools) can then flip it over it desired.
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 7686ad56
...@@ -448,8 +448,10 @@ config PATA_MARVELL ...@@ -448,8 +448,10 @@ config PATA_MARVELL
tristate "Marvell PATA support via legacy mode" tristate "Marvell PATA support via legacy mode"
depends on PCI depends on PCI
help help
This option enables limited support for the Marvell 88SE6145 ATA This option enables limited support for the Marvell 88SE61xx ATA
controller. controllers. If you wish to use only the SATA ports then select
the AHCI driver alone. If you wish to the use the PATA port or
both SATA and PATA include this driver.
If unsure, say N. If unsure, say N.
......
...@@ -610,6 +610,15 @@ module_param(ahci_em_messages, int, 0444); ...@@ -610,6 +610,15 @@ module_param(ahci_em_messages, int, 0444);
MODULE_PARM_DESC(ahci_em_messages, MODULE_PARM_DESC(ahci_em_messages,
"Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED"); "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
static int marvell_enable;
#else
static int marvell_enable = 1;
#endif
module_param(marvell_enable, int, 0644);
MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
static inline int ahci_nr_ports(u32 cap) static inline int ahci_nr_ports(u32 cap)
{ {
return (cap & 0x1f) + 1; return (cap & 0x1f) + 1;
...@@ -732,6 +741,8 @@ static void ahci_save_initial_config(struct pci_dev *pdev, ...@@ -732,6 +741,8 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
"MV_AHCI HACK: port_map %x -> %x\n", "MV_AHCI HACK: port_map %x -> %x\n",
port_map, port_map,
port_map & mv); port_map & mv);
dev_printk(KERN_ERR, &pdev->dev,
"Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
port_map &= mv; port_map &= mv;
} }
...@@ -2533,6 +2544,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2533,6 +2544,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
/* The AHCI driver can only drive the SATA ports, the PATA driver
can drive them all so if both drivers are selected make sure
AHCI stays out of the way */
if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
return -ENODEV;
/* acquire resources */ /* acquire resources */
rc = pcim_enable_device(pdev); rc = pcim_enable_device(pdev);
if (rc) if (rc)
......
...@@ -20,29 +20,30 @@ ...@@ -20,29 +20,30 @@
#include <linux/ata.h> #include <linux/ata.h>
#define DRV_NAME "pata_marvell" #define DRV_NAME "pata_marvell"
#define DRV_VERSION "0.1.4" #define DRV_VERSION "0.1.6"
/** /**
* marvell_pre_reset - check for 40/80 pin * marvell_pata_active - check if PATA is active
* @link: link * @pdev: PCI device
* @deadline: deadline jiffies for the operation
* *
* Perform the PATA port setup we need. * Returns 1 if the PATA port may be active. We know how to check this
* for the 6145 but not the other devices
*/ */
static int marvell_pre_reset(struct ata_link *link, unsigned long deadline) static int marvell_pata_active(struct pci_dev *pdev)
{ {
struct ata_port *ap = link->ap; int i;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 devices; u32 devices;
void __iomem *barp; void __iomem *barp;
int i;
/* Check if our port is enabled */ /* We don't yet know how to do this for other devices */
if (pdev->device != 0x6145)
return 1;
barp = pci_iomap(pdev, 5, 0x10); barp = pci_iomap(pdev, 5, 0x10);
if (barp == NULL) if (barp == NULL)
return -ENOMEM; return -ENOMEM;
printk("BAR5:"); printk("BAR5:");
for(i = 0; i <= 0x0F; i++) for(i = 0; i <= 0x0F; i++)
printk("%02X:%02X ", i, ioread8(barp + i)); printk("%02X:%02X ", i, ioread8(barp + i));
...@@ -51,9 +52,27 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline) ...@@ -51,9 +52,27 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
devices = ioread32(barp + 0x0C); devices = ioread32(barp + 0x0C);
pci_iounmap(pdev, barp); pci_iounmap(pdev, barp);
if ((pdev->device == 0x6145) && (ap->port_no == 0) && if (devices & 0x10)
(!(devices & 0x10))) /* PATA enable ? */ return 1;
return -ENOENT; return 0;
}
/**
* marvell_pre_reset - check for 40/80 pin
* @link: link
* @deadline: deadline jiffies for the operation
*
* Perform the PATA port setup we need.
*/
static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
{
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (pdev->device == 0x6145 && ap->port_no == 0 &&
!marvell_pata_active(pdev)) /* PATA enable ? */
return -ENOENT;
return ata_sff_prereset(link, deadline); return ata_sff_prereset(link, deadline);
} }
...@@ -128,6 +147,12 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i ...@@ -128,6 +147,12 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
if (pdev->device == 0x6101) if (pdev->device == 0x6101)
ppi[1] = &ata_dummy_port_info; ppi[1] = &ata_dummy_port_info;
#if defined(CONFIG_AHCI) || defined(CONFIG_AHCI_MODULE)
if (!marvell_pata_active(pdev)) {
printk(KERN_INFO DRV_NAME ": PATA port not active, deferring to AHCI driver.\n");
return -ENODEV;
}
#endif
return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL); return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
} }
......
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