Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9281b16c authored by James Bottomley's avatar James Bottomley Committed by Jeff Garzik
Browse files

pata_cm64x: fix boot crash on parisc



The old IDE cmd64x checks the status of the CNTRL register to see if
the ports are enabled before probing them.  pata_cmd64x doesn't do
this, which causes a HPMC on parisc when it tries to poke at the
secondary port because apparently the BAR isn't wired up (and a
non-responding piece of memory causes a HPMC).

Fix this by porting the CNTRL register port detection logic from IDE
cmd64x.  In addition, following converns from Alan Cox, add a check to
see if a mobility electronics bridge is the immediate parent and forgo
the check if it is (prevents problems on hotplug controllers).

Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 5f6f12cc
Loading
Loading
Loading
Loading
+38 −4
Original line number Diff line number Diff line
@@ -41,6 +41,9 @@
enum {
	CFR 		= 0x50,
		CFR_INTR_CH0  = 0x04,
	CNTRL		= 0x51,
		CNTRL_CH0     = 0x04,
		CNTRL_CH1     = 0x08,
	CMDTIM 		= 0x52,
	ARTTIM0 	= 0x53,
	DRWTIM0 	= 0x54,
@@ -328,9 +331,19 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
			.port_ops = &cmd648_port_ops
		}
	};
	const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
	u8 mrdmode;
	const struct ata_port_info *ppi[] = { 
		&cmd_info[id->driver_data],
		&cmd_info[id->driver_data],
		NULL
	};
	u8 mrdmode, reg;
	int rc;
	struct pci_dev *bridge = pdev->bus->self;
	/* mobility split bridges don't report enabled ports correctly */
	int port_ok = !(bridge && bridge->vendor ==
			PCI_VENDOR_ID_MOBILITY_ELECTRONICS);
	/* all (with exceptions below) apart from 643 have CNTRL_CH0 bit */
	int cntrl_ch0_ok = (id->driver_data != 0);

	rc = pcim_enable_device(pdev);
	if (rc)
@@ -341,11 +354,18 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)

	if (pdev->device == PCI_DEVICE_ID_CMD_646) {
		/* Does UDMA work ? */
		if (pdev->revision > 4)
		if (pdev->revision > 4) {
			ppi[0] = &cmd_info[2];
			ppi[1] = &cmd_info[2];
		}
		/* Early rev with other problems ? */
		else if (pdev->revision == 1)
		else if (pdev->revision == 1) {
			ppi[0] = &cmd_info[3];
			ppi[1] = &cmd_info[3];
		}
		/* revs 1,2 have no CNTRL_CH0 */
		if (pdev->revision < 3)
			cntrl_ch0_ok = 0;
	}

	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
@@ -354,6 +374,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
	mrdmode |= 0x02;	/* Memory read line enable */
	pci_write_config_byte(pdev, MRDMODE, mrdmode);

	/* check for enabled ports */
	pci_read_config_byte(pdev, CNTRL, &reg);
	if (!port_ok)
		dev_printk(KERN_NOTICE, &pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
	if (port_ok && cntrl_ch0_ok && !(reg & CNTRL_CH0)) {
		dev_printk(KERN_NOTICE, &pdev->dev, "Primary port is disabled\n");
		ppi[0] = &ata_dummy_port_info;
		
	}
	if (port_ok && !(reg & CNTRL_CH1)) {
		dev_printk(KERN_NOTICE, &pdev->dev, "Secondary port is disabled\n");
		ppi[1] = &ata_dummy_port_info;
	}

	/* Force PIO 0 here.. */

	/* PPC specific fixup copied from old driver */
+2 −0
Original line number Diff line number Diff line
@@ -608,6 +608,8 @@
#define PCI_DEVICE_ID_MATROX_G550	0x2527
#define PCI_DEVICE_ID_MATROX_VIA	0x4536

#define PCI_VENDOR_ID_MOBILITY_ELECTRONICS	0x14f2

#define PCI_VENDOR_ID_CT		0x102c
#define PCI_DEVICE_ID_CT_69000		0x00c0
#define PCI_DEVICE_ID_CT_65545		0x00d8