aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@suse.de>2011-04-24 15:30:14 -0400
committerJeff Garzik <jgarzik@pobox.com>2011-05-14 14:59:15 -0400
commit9281b16caac1276817b77033c5b8a1f5ca30102c (patch)
tree73c554e4ab9e9dcfe1b610f2f65e0ae1713341b5
parent5f6f12ccf3aa42cfc0c5bde9228df0c843dd63f7 (diff)
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: James Bottomley <James.Bottomley@suse.de> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r--drivers/ata/pata_cmd64x.c42
-rw-r--r--include/linux/pci_ids.h2
2 files changed, 40 insertions, 4 deletions
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 905ff76d3cbb..7bafc16cf5e0 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -41,6 +41,9 @@
41enum { 41enum {
42 CFR = 0x50, 42 CFR = 0x50,
43 CFR_INTR_CH0 = 0x04, 43 CFR_INTR_CH0 = 0x04,
44 CNTRL = 0x51,
45 CNTRL_CH0 = 0x04,
46 CNTRL_CH1 = 0x08,
44 CMDTIM = 0x52, 47 CMDTIM = 0x52,
45 ARTTIM0 = 0x53, 48 ARTTIM0 = 0x53,
46 DRWTIM0 = 0x54, 49 DRWTIM0 = 0x54,
@@ -328,9 +331,19 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
328 .port_ops = &cmd648_port_ops 331 .port_ops = &cmd648_port_ops
329 } 332 }
330 }; 333 };
331 const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL }; 334 const struct ata_port_info *ppi[] = {
332 u8 mrdmode; 335 &cmd_info[id->driver_data],
336 &cmd_info[id->driver_data],
337 NULL
338 };
339 u8 mrdmode, reg;
333 int rc; 340 int rc;
341 struct pci_dev *bridge = pdev->bus->self;
342 /* mobility split bridges don't report enabled ports correctly */
343 int port_ok = !(bridge && bridge->vendor ==
344 PCI_VENDOR_ID_MOBILITY_ELECTRONICS);
345 /* all (with exceptions below) apart from 643 have CNTRL_CH0 bit */
346 int cntrl_ch0_ok = (id->driver_data != 0);
334 347
335 rc = pcim_enable_device(pdev); 348 rc = pcim_enable_device(pdev);
336 if (rc) 349 if (rc)
@@ -341,11 +354,18 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
341 354
342 if (pdev->device == PCI_DEVICE_ID_CMD_646) { 355 if (pdev->device == PCI_DEVICE_ID_CMD_646) {
343 /* Does UDMA work ? */ 356 /* Does UDMA work ? */
344 if (pdev->revision > 4) 357 if (pdev->revision > 4) {
345 ppi[0] = &cmd_info[2]; 358 ppi[0] = &cmd_info[2];
359 ppi[1] = &cmd_info[2];
360 }
346 /* Early rev with other problems ? */ 361 /* Early rev with other problems ? */
347 else if (pdev->revision == 1) 362 else if (pdev->revision == 1) {
348 ppi[0] = &cmd_info[3]; 363 ppi[0] = &cmd_info[3];
364 ppi[1] = &cmd_info[3];
365 }
366 /* revs 1,2 have no CNTRL_CH0 */
367 if (pdev->revision < 3)
368 cntrl_ch0_ok = 0;
349 } 369 }
350 370
351 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); 371 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)
354 mrdmode |= 0x02; /* Memory read line enable */ 374 mrdmode |= 0x02; /* Memory read line enable */
355 pci_write_config_byte(pdev, MRDMODE, mrdmode); 375 pci_write_config_byte(pdev, MRDMODE, mrdmode);
356 376
377 /* check for enabled ports */
378 pci_read_config_byte(pdev, CNTRL, &reg);
379 if (!port_ok)
380 dev_printk(KERN_NOTICE, &pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
381 if (port_ok && cntrl_ch0_ok && !(reg & CNTRL_CH0)) {
382 dev_printk(KERN_NOTICE, &pdev->dev, "Primary port is disabled\n");
383 ppi[0] = &ata_dummy_port_info;
384
385 }
386 if (port_ok && !(reg & CNTRL_CH1)) {
387 dev_printk(KERN_NOTICE, &pdev->dev, "Secondary port is disabled\n");
388 ppi[1] = &ata_dummy_port_info;
389 }
390
357 /* Force PIO 0 here.. */ 391 /* Force PIO 0 here.. */
358 392
359 /* PPC specific fixup copied from old driver */ 393 /* PPC specific fixup copied from old driver */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 8abe8d78c4bf..8652a4fa3fe2 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -608,6 +608,8 @@
608#define PCI_DEVICE_ID_MATROX_G550 0x2527 608#define PCI_DEVICE_ID_MATROX_G550 0x2527
609#define PCI_DEVICE_ID_MATROX_VIA 0x4536 609#define PCI_DEVICE_ID_MATROX_VIA 0x4536
610 610
611#define PCI_VENDOR_ID_MOBILITY_ELECTRONICS 0x14f2
612
611#define PCI_VENDOR_ID_CT 0x102c 613#define PCI_VENDOR_ID_CT 0x102c
612#define PCI_DEVICE_ID_CT_69000 0x00c0 614#define PCI_DEVICE_ID_CT_69000 0x00c0
613#define PCI_DEVICE_ID_CT_65545 0x00d8 615#define PCI_DEVICE_ID_CT_65545 0x00d8