summaryrefslogtreecommitdiff
path: root/arch/sparc64/kernel/pci_schizo.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/pci_schizo.c')
-rw-r--r--arch/sparc64/kernel/pci_schizo.c84
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,
spin_unlock_irqrestore(&iommu->lock, flags);
}
-static void schizo_check_iommu_error(struct pci_controller_info *p,
+static void schizo_check_iommu_error(struct pci_pbm_info *pbm,
enum schizo_error_type type)
{
- schizo_check_iommu_error_pbm(&p->pbm_A, type);
- schizo_check_iommu_error_pbm(&p->pbm_B, type);
+ schizo_check_iommu_error_pbm(pbm, type);
+ if (pbm->sibling)
+ schizo_check_iommu_error_pbm(pbm->sibling, type);
}
/* Uncorrectable ECC error status gathering. */
@@ -387,7 +388,6 @@ static void schizo_check_iommu_error(struct pci_controller_info *p,
static irqreturn_t schizo_ue_intr(int irq, void *dev_id)
{
struct pci_pbm_info *pbm = dev_id;
- struct pci_controller_info *p = pbm->parent;
unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR;
unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR;
unsigned long afsr, afar, error_bits;
@@ -450,7 +450,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id)
printk("]\n");
/* Interrogate IOMMU for error status. */
- schizo_check_iommu_error(p, UE_ERR);
+ schizo_check_iommu_error(pbm, UE_ERR);
return IRQ_HANDLED;
}
@@ -651,7 +651,6 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
{
struct pci_pbm_info *pbm = dev_id;
- struct pci_controller_info *p = pbm->parent;
unsigned long afsr_reg, afar_reg, base;
unsigned long afsr, afar, error_bits;
int reported;
@@ -745,7 +744,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
* a bug in the IOMMU support code or a PCI device driver.
*/
if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) {
- schizo_check_iommu_error(p, PCI_ERR);
+ schizo_check_iommu_error(pbm, PCI_ERR);
pci_scan_for_target_abort(pbm, pbm->pci_bus);
}
if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA))
@@ -806,7 +805,6 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
{
struct pci_pbm_info *pbm = dev_id;
- struct pci_controller_info *p = pbm->parent;
u64 errlog;
errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG);
@@ -822,7 +820,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n",
pbm->name);
- schizo_check_iommu_error(p, SAFARI_ERR);
+ schizo_check_iommu_error(pbm, SAFARI_ERR);
return IRQ_HANDLED;
}
@@ -1329,13 +1327,12 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
}
}
-static int __devinit schizo_pbm_init(struct pci_controller_info *p,
+static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm,
struct of_device *op, u32 portid,
int chip_type)
{
const struct linux_prom64_registers *regs;
struct device_node *dp = op->node;
- struct pci_pbm_info *pbm;
const char *chipset_name;
int is_pbm_a, err;
@@ -1368,10 +1365,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p,
regs = of_get_property(dp, "reg", NULL);
is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
- if (is_pbm_a)
- pbm = &p->pbm_A;
- else
- pbm = &p->pbm_B;
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
@@ -1384,7 +1377,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p,
pbm->index = pci_num_pbms++;
pbm->portid = portid;
- pbm->parent = p;
pbm->prom_node = dp;
pbm->chip_type = chip_type;
@@ -1430,10 +1422,21 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
return (x == y);
}
+static struct pci_pbm_info * __devinit schizo_find_sibling(u32 portid,
+ int chip_type)
+{
+ struct pci_pbm_info *pbm;
+
+ for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
+ if (portid_compare(pbm->portid, portid, chip_type))
+ return pbm;
+ }
+ return NULL;
+}
+
static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type)
{
struct device_node *dp = op->node;
- struct pci_controller_info *p;
struct pci_pbm_info *pbm;
struct iommu *iommu;
u32 portid;
@@ -1442,50 +1445,37 @@ static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type
portid = of_getintprop_default(dp, "portid", 0xff);
err = -ENOMEM;
- for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
- if (portid_compare(pbm->portid, portid, chip_type)) {
- if (schizo_pbm_init(pbm->parent, op,
- portid, chip_type))
- goto out_err;
- return 0;
- }
- }
-
- p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
- if (!p) {
- printk(KERN_ERR PFX "Cannot allocate controller info.\n");
+ pbm = kzalloc(sizeof(*pbm), GFP_KERNEL);
+ if (!pbm) {
+ printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n");
goto out_err;
}
- iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
+ pbm->sibling = schizo_find_sibling(portid, chip_type);
+
+ iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL);
if (!iommu) {
printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n");
- goto out_free_controller;
+ goto out_free_pbm;
}
- p->pbm_A.iommu = iommu;
+ pbm->iommu = iommu;
- iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
- if (!iommu) {
- printk(KERN_ERR PFX "Cannot allocate PBM B iommu.\n");
- goto out_free_iommu_A;
- }
+ if (schizo_pbm_init(pbm, op, portid, chip_type))
+ goto out_free_iommu;
- p->pbm_B.iommu = iommu;
+ if (pbm->sibling)
+ pbm->sibling->sibling = pbm;
- if (schizo_pbm_init(p, op, portid, chip_type))
- goto out_free_iommu_B;
+ dev_set_drvdata(&op->dev, pbm);
return 0;
-out_free_iommu_B:
- kfree(p->pbm_B.iommu);
-
-out_free_iommu_A:
- kfree(p->pbm_A.iommu);
+out_free_iommu:
+ kfree(pbm->iommu);
-out_free_controller:
- kfree(p);
+out_free_pbm:
+ kfree(pbm);
out_err:
return err;