diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_schizo.c')
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 84 |
1 files changed, 37 insertions, 47 deletions
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index e1c565744d3f..67e3640bc69a 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
@@ -358,11 +358,12 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, | |||
358 | spin_unlock_irqrestore(&iommu->lock, flags); | 358 | spin_unlock_irqrestore(&iommu->lock, flags); |
359 | } | 359 | } |
360 | 360 | ||
361 | static void schizo_check_iommu_error(struct pci_controller_info *p, | 361 | static void schizo_check_iommu_error(struct pci_pbm_info *pbm, |
362 | enum schizo_error_type type) | 362 | enum schizo_error_type type) |
363 | { | 363 | { |
364 | schizo_check_iommu_error_pbm(&p->pbm_A, type); | 364 | schizo_check_iommu_error_pbm(pbm, type); |
365 | schizo_check_iommu_error_pbm(&p->pbm_B, type); | 365 | if (pbm->sibling) |
366 | schizo_check_iommu_error_pbm(pbm->sibling, type); | ||
366 | } | 367 | } |
367 | 368 | ||
368 | /* Uncorrectable ECC error status gathering. */ | 369 | /* Uncorrectable ECC error status gathering. */ |
@@ -387,7 +388,6 @@ static void schizo_check_iommu_error(struct pci_controller_info *p, | |||
387 | static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | 388 | static irqreturn_t schizo_ue_intr(int irq, void *dev_id) |
388 | { | 389 | { |
389 | struct pci_pbm_info *pbm = dev_id; | 390 | struct pci_pbm_info *pbm = dev_id; |
390 | struct pci_controller_info *p = pbm->parent; | ||
391 | unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; | 391 | unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; |
392 | unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; | 392 | unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; |
393 | unsigned long afsr, afar, error_bits; | 393 | unsigned long afsr, afar, error_bits; |
@@ -450,7 +450,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | |||
450 | printk("]\n"); | 450 | printk("]\n"); |
451 | 451 | ||
452 | /* Interrogate IOMMU for error status. */ | 452 | /* Interrogate IOMMU for error status. */ |
453 | schizo_check_iommu_error(p, UE_ERR); | 453 | schizo_check_iommu_error(pbm, UE_ERR); |
454 | 454 | ||
455 | return IRQ_HANDLED; | 455 | return IRQ_HANDLED; |
456 | } | 456 | } |
@@ -651,7 +651,6 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) | |||
651 | static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | 651 | static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) |
652 | { | 652 | { |
653 | struct pci_pbm_info *pbm = dev_id; | 653 | struct pci_pbm_info *pbm = dev_id; |
654 | struct pci_controller_info *p = pbm->parent; | ||
655 | unsigned long afsr_reg, afar_reg, base; | 654 | unsigned long afsr_reg, afar_reg, base; |
656 | unsigned long afsr, afar, error_bits; | 655 | unsigned long afsr, afar, error_bits; |
657 | int reported; | 656 | int reported; |
@@ -745,7 +744,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
745 | * a bug in the IOMMU support code or a PCI device driver. | 744 | * a bug in the IOMMU support code or a PCI device driver. |
746 | */ | 745 | */ |
747 | if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { | 746 | if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { |
748 | schizo_check_iommu_error(p, PCI_ERR); | 747 | schizo_check_iommu_error(pbm, PCI_ERR); |
749 | pci_scan_for_target_abort(pbm, pbm->pci_bus); | 748 | pci_scan_for_target_abort(pbm, pbm->pci_bus); |
750 | } | 749 | } |
751 | if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) | 750 | if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) |
@@ -806,7 +805,6 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
806 | static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) | 805 | static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) |
807 | { | 806 | { |
808 | struct pci_pbm_info *pbm = dev_id; | 807 | struct pci_pbm_info *pbm = dev_id; |
809 | struct pci_controller_info *p = pbm->parent; | ||
810 | u64 errlog; | 808 | u64 errlog; |
811 | 809 | ||
812 | errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); | 810 | errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); |
@@ -822,7 +820,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) | |||
822 | 820 | ||
823 | printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", | 821 | printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", |
824 | pbm->name); | 822 | pbm->name); |
825 | schizo_check_iommu_error(p, SAFARI_ERR); | 823 | schizo_check_iommu_error(pbm, SAFARI_ERR); |
826 | 824 | ||
827 | return IRQ_HANDLED; | 825 | return IRQ_HANDLED; |
828 | } | 826 | } |
@@ -1329,13 +1327,12 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | |||
1329 | } | 1327 | } |
1330 | } | 1328 | } |
1331 | 1329 | ||
1332 | static int __devinit schizo_pbm_init(struct pci_controller_info *p, | 1330 | static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, |
1333 | struct of_device *op, u32 portid, | 1331 | struct of_device *op, u32 portid, |
1334 | int chip_type) | 1332 | int chip_type) |
1335 | { | 1333 | { |
1336 | const struct linux_prom64_registers *regs; | 1334 | const struct linux_prom64_registers *regs; |
1337 | struct device_node *dp = op->node; | 1335 | struct device_node *dp = op->node; |
1338 | struct pci_pbm_info *pbm; | ||
1339 | const char *chipset_name; | 1336 | const char *chipset_name; |
1340 | int is_pbm_a, err; | 1337 | int is_pbm_a, err; |
1341 | 1338 | ||
@@ -1368,10 +1365,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, | |||
1368 | regs = of_get_property(dp, "reg", NULL); | 1365 | regs = of_get_property(dp, "reg", NULL); |
1369 | 1366 | ||
1370 | is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); | 1367 | is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); |
1371 | if (is_pbm_a) | ||
1372 | pbm = &p->pbm_A; | ||
1373 | else | ||
1374 | pbm = &p->pbm_B; | ||
1375 | 1368 | ||
1376 | pbm->next = pci_pbm_root; | 1369 | pbm->next = pci_pbm_root; |
1377 | pci_pbm_root = pbm; | 1370 | pci_pbm_root = pbm; |
@@ -1384,7 +1377,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, | |||
1384 | pbm->index = pci_num_pbms++; | 1377 | pbm->index = pci_num_pbms++; |
1385 | 1378 | ||
1386 | pbm->portid = portid; | 1379 | pbm->portid = portid; |
1387 | pbm->parent = p; | ||
1388 | pbm->prom_node = dp; | 1380 | pbm->prom_node = dp; |
1389 | 1381 | ||
1390 | pbm->chip_type = chip_type; | 1382 | pbm->chip_type = chip_type; |
@@ -1430,10 +1422,21 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) | |||
1430 | return (x == y); | 1422 | return (x == y); |
1431 | } | 1423 | } |
1432 | 1424 | ||
1425 | static struct pci_pbm_info * __devinit schizo_find_sibling(u32 portid, | ||
1426 | int chip_type) | ||
1427 | { | ||
1428 | struct pci_pbm_info *pbm; | ||
1429 | |||
1430 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | ||
1431 | if (portid_compare(pbm->portid, portid, chip_type)) | ||
1432 | return pbm; | ||
1433 | } | ||
1434 | return NULL; | ||
1435 | } | ||
1436 | |||
1433 | static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type) | 1437 | static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type) |
1434 | { | 1438 | { |
1435 | struct device_node *dp = op->node; | 1439 | struct device_node *dp = op->node; |
1436 | struct pci_controller_info *p; | ||
1437 | struct pci_pbm_info *pbm; | 1440 | struct pci_pbm_info *pbm; |
1438 | struct iommu *iommu; | 1441 | struct iommu *iommu; |
1439 | u32 portid; | 1442 | u32 portid; |
@@ -1442,50 +1445,37 @@ static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type | |||
1442 | portid = of_getintprop_default(dp, "portid", 0xff); | 1445 | portid = of_getintprop_default(dp, "portid", 0xff); |
1443 | 1446 | ||
1444 | err = -ENOMEM; | 1447 | err = -ENOMEM; |
1445 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 1448 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
1446 | if (portid_compare(pbm->portid, portid, chip_type)) { | 1449 | if (!pbm) { |
1447 | if (schizo_pbm_init(pbm->parent, op, | 1450 | printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); |
1448 | portid, chip_type)) | ||
1449 | goto out_err; | ||
1450 | return 0; | ||
1451 | } | ||
1452 | } | ||
1453 | |||
1454 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | ||
1455 | if (!p) { | ||
1456 | printk(KERN_ERR PFX "Cannot allocate controller info.\n"); | ||
1457 | goto out_err; | 1451 | goto out_err; |
1458 | } | 1452 | } |
1459 | 1453 | ||
1460 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 1454 | pbm->sibling = schizo_find_sibling(portid, chip_type); |
1455 | |||
1456 | iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); | ||
1461 | if (!iommu) { | 1457 | if (!iommu) { |
1462 | printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); | 1458 | printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); |
1463 | goto out_free_controller; | 1459 | goto out_free_pbm; |
1464 | } | 1460 | } |
1465 | 1461 | ||
1466 | p->pbm_A.iommu = iommu; | 1462 | pbm->iommu = iommu; |
1467 | 1463 | ||
1468 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 1464 | if (schizo_pbm_init(pbm, op, portid, chip_type)) |
1469 | if (!iommu) { | 1465 | goto out_free_iommu; |
1470 | printk(KERN_ERR PFX "Cannot allocate PBM B iommu.\n"); | ||
1471 | goto out_free_iommu_A; | ||
1472 | } | ||
1473 | 1466 | ||
1474 | p->pbm_B.iommu = iommu; | 1467 | if (pbm->sibling) |
1468 | pbm->sibling->sibling = pbm; | ||
1475 | 1469 | ||
1476 | if (schizo_pbm_init(p, op, portid, chip_type)) | 1470 | dev_set_drvdata(&op->dev, pbm); |
1477 | goto out_free_iommu_B; | ||
1478 | 1471 | ||
1479 | return 0; | 1472 | return 0; |
1480 | 1473 | ||
1481 | out_free_iommu_B: | 1474 | out_free_iommu: |
1482 | kfree(p->pbm_B.iommu); | 1475 | kfree(pbm->iommu); |
1483 | |||
1484 | out_free_iommu_A: | ||
1485 | kfree(p->pbm_A.iommu); | ||
1486 | 1476 | ||
1487 | out_free_controller: | 1477 | out_free_pbm: |
1488 | kfree(p); | 1478 | kfree(pbm); |
1489 | 1479 | ||
1490 | out_err: | 1480 | out_err: |
1491 | return err; | 1481 | return err; |