diff options
-rw-r--r-- | arch/sparc64/kernel/pci.c | 12 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_fire.c | 39 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_impl.h | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 107 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 31 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 256 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 47 | ||||
-rw-r--r-- | include/asm-sparc64/pbm.h | 8 |
8 files changed, 187 insertions, 315 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 966861b212b..c17723fb1c3 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -48,7 +48,7 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, #else /* List of all PCI controllers found in the system. */ -struct pci_controller_info *pci_controller_root = NULL; +struct pci_pbm_info *pci_pbm_root = NULL; /* Each PCI controller found gets a unique index. */ int pci_num_controllers = 0; @@ -291,7 +291,7 @@ extern const struct pci_iommu_ops pci_sun4u_iommu_ops, /* Find each controller in the system, attach and initialize * software state structure for each and link into the - * pci_controller_root. Setup the controller enough such + * pci_pbm_root. Setup the controller enough such * that bus scanning can be done. */ static void __init pci_controller_probe(void) @@ -776,10 +776,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) static void __init pci_scan_each_controller_bus(void) { - struct pci_controller_info *p; + struct pci_pbm_info *pbm; - for (p = pci_controller_root; p; p = p->next) - p->scan_bus(p); + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) + pbm->scan_bus(pbm); } extern void power_init(void); @@ -787,7 +787,7 @@ extern void power_init(void); static int __init pcibios_init(void) { pci_controller_probe(); - if (pci_controller_root == NULL) + if (pci_pbm_root == NULL) return 0; pci_scan_each_controller_bus(); diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 79ee5be948e..f55c08ae0aa 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -160,21 +160,9 @@ static struct pci_ops pci_fire_ops = { .write = fire_write_pci_cfg, }; -static void pbm_scan_bus(struct pci_controller_info *p, - struct pci_pbm_info *pbm) +static void pci_fire_scan_bus(struct pci_pbm_info *pbm) { pbm->pci_bus = pci_scan_one_pbm(pbm); -} - -static void pci_fire_scan_bus(struct pci_controller_info *p) -{ - struct device_node *dp; - - if ((dp = p->pbm_A.prom_node) != NULL) - pbm_scan_bus(p, &p->pbm_A); - - if ((dp = p->pbm_B.prom_node) != NULL) - pbm_scan_bus(p, &p->pbm_B); /* XXX register error interrupt handlers XXX */ } @@ -313,7 +301,7 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) } static void pci_fire_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid) + struct device_node *dp, u32 portid) { const struct linux_prom64_registers *regs; struct pci_pbm_info *pbm; @@ -323,6 +311,11 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, else pbm = &p->pbm_B; + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + + pbm->scan_bus = pci_fire_scan_bus; + pbm->portid = portid; pbm->parent = p; pbm->prom_node = dp; @@ -354,19 +347,11 @@ void fire_pci_init(struct device_node *dp, const char *model_name) struct pci_controller_info *p; u32 portid = of_getintprop_default(dp, "portid", 0xff); struct iommu *iommu; + struct pci_pbm_info *pbm; - for (p = pci_controller_root; p; p = p->next) { - struct pci_pbm_info *pbm; - - if (p->pbm_A.prom_node && p->pbm_B.prom_node) - continue; - - pbm = (p->pbm_A.prom_node ? - &p->pbm_A : - &p->pbm_B); - + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (portid_compare(pbm->portid, portid)) { - pci_fire_pbm_init(p, dp, portid); + pci_fire_pbm_init(pbm->parent, dp, portid); return; } } @@ -387,12 +372,8 @@ void fire_pci_init(struct device_node *dp, const char *model_name) p->pbm_B.iommu = iommu; - p->next = pci_controller_root; - pci_controller_root = p; - p->index = pci_num_controllers++; - p->scan_bus = pci_fire_scan_bus; /* XXX MSI support XXX */ p->pci_ops = &pci_fire_ops; diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 41c3f513730..3dd6d02b2d8 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -11,7 +11,7 @@ #include <asm/io.h> #include <asm/prom.h> -extern struct pci_controller_info *pci_controller_root; +extern struct pci_pbm_info *pci_pbm_root; extern unsigned long pci_memspace_mask; extern int pci_num_controllers; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 0f35135a40c..4801eb44123 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -265,12 +265,12 @@ static unsigned long stc_error_buf[128]; static unsigned long stc_tag_buf[16]; static unsigned long stc_line_buf[16]; -static void __psycho_check_one_stc(struct pci_controller_info *p, - struct pci_pbm_info *pbm, +static void __psycho_check_one_stc(struct pci_pbm_info *pbm, int is_pbm_a) { + struct pci_controller_info *p = pbm->parent; struct strbuf *strbuf = &pbm->stc; - unsigned long regbase = p->pbm_A.controller_regs; + unsigned long regbase = pbm->controller_regs; unsigned long err_base, tag_base, line_base; u64 control; int i; @@ -362,20 +362,13 @@ static void __psycho_check_one_stc(struct pci_controller_info *p, spin_unlock(&stc_buf_lock); } -static void __psycho_check_stc_error(struct pci_controller_info *p, +static void __psycho_check_stc_error(struct pci_pbm_info *pbm, unsigned long afsr, unsigned long afar, enum psycho_error_type type) { - struct pci_pbm_info *pbm; - - pbm = &p->pbm_A; - if (pbm->stc.strbuf_enabled) - __psycho_check_one_stc(p, pbm, 1); - - pbm = &p->pbm_B; - if (pbm->stc.strbuf_enabled) - __psycho_check_one_stc(p, pbm, 0); + __psycho_check_one_stc(pbm, + (pbm == &pbm->parent->pbm_A)); } /* When an Uncorrectable Error or a PCI Error happens, we @@ -413,12 +406,13 @@ static void __psycho_check_stc_error(struct pci_controller_info *p, #define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) #define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) #define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL -static void psycho_check_iommu_error(struct pci_controller_info *p, +static void psycho_check_iommu_error(struct pci_pbm_info *pbm, unsigned long afsr, unsigned long afar, enum psycho_error_type type) { - struct iommu *iommu = p->pbm_A.iommu; + struct pci_controller_info *p = pbm->parent; + struct iommu *iommu = pbm->iommu; unsigned long iommu_tag[16]; unsigned long iommu_data[16]; unsigned long flags; @@ -465,7 +459,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, psycho_write(iommu->iommu_control, control | PSYCHO_IOMMU_CTRL_DENAB); for (i = 0; i < 16; i++) { - unsigned long base = p->pbm_A.controller_regs; + unsigned long base = pbm->controller_regs; iommu_tag[i] = psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); @@ -516,7 +510,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); } } - __psycho_check_stc_error(p, afsr, afar, type); + __psycho_check_stc_error(pbm, afsr, afar, type); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -541,9 +535,10 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, static irqreturn_t psycho_ue_intr(int irq, void *dev_id) { - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFSR; - unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFAR; + struct pci_pbm_info *pbm = dev_id; + struct pci_controller_info *p = pbm->parent; + unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; + unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; unsigned long afsr, afar, error_bits; int reported; @@ -593,8 +588,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) printk("(none)"); printk("]\n"); - /* Interrogate IOMMU for error status. */ - psycho_check_iommu_error(p, afsr, afar, UE_ERR); + /* Interrogate both IOMMUs for error status. */ + psycho_check_iommu_error(&p->pbm_A, afsr, afar, UE_ERR); + psycho_check_iommu_error(&p->pbm_B, afsr, afar, UE_ERR); return IRQ_HANDLED; } @@ -618,9 +614,10 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) static irqreturn_t psycho_ce_intr(int irq, void *dev_id) { - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFSR; - unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFAR; + struct pci_pbm_info *pbm = dev_id; + struct pci_controller_info *p = pbm->parent; + unsigned long afsr_reg = pbm->controller_regs + PSYCHO_CE_AFSR; + unsigned long afar_reg = pbm->controller_regs + PSYCHO_CE_AFAR; unsigned long afsr, afar, error_bits; int reported; @@ -823,11 +820,11 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) * a bug in the IOMMU support code or a PCI device driver. */ if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { - psycho_check_iommu_error(p, afsr, afar, PCI_ERR); - pci_scan_for_target_abort(p, pbm, pbm->pci_bus); + psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); + pci_scan_for_target_abort(pbm->parent, pbm, pbm->pci_bus); } if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) - pci_scan_for_master_abort(p, pbm, pbm->pci_bus); + pci_scan_for_master_abort(pbm->parent, pbm, pbm->pci_bus); /* For excessive retries, PSYCHO/PBM will abort the device * and there is no way to specifically check for excessive @@ -837,7 +834,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) */ if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) - pci_scan_for_parity_error(p, pbm, pbm->pci_bus); + pci_scan_for_parity_error(pbm->parent, pbm, pbm->pci_bus); return IRQ_HANDLED; } @@ -847,34 +844,33 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ #define PSYCHO_ECCCTRL_UE 0x4000000000000000UL /* Enable UE Interrupts */ #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ -static void psycho_register_error_handlers(struct pci_controller_info *p) +static void psycho_register_error_handlers(struct pci_pbm_info *pbm) { - struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ struct of_device *op = of_find_device_by_node(pbm->prom_node); - unsigned long base = p->pbm_A.controller_regs; + unsigned long base = pbm->controller_regs; u64 tmp; if (!op) return; /* Psycho interrupt property order is: - * 0: PCIERR PBM B INO + * 0: PCIERR INO for this PBM * 1: UE ERR * 2: CE ERR * 3: POWER FAIL * 4: SPARE HARDWARE - * 5: PCIERR PBM A INO + * 5: POWER MANAGEMENT */ if (op->num_irqs < 6) return; - request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED, "PSYCHO UE", p); - request_irq(op->irqs[2], psycho_ce_intr, IRQF_SHARED, "PSYCHO CE", p); - request_irq(op->irqs[5], psycho_pcierr_intr, IRQF_SHARED, - "PSYCHO PCIERR-A", &p->pbm_A); - request_irq(op->irqs[0], psycho_pcierr_intr, IRQF_SHARED, - "PSYCHO PCIERR-B", &p->pbm_B); + request_irq(op->irqs[1], psycho_ue_intr, 0, + "PSYCHO_UE", pbm); + request_irq(op->irqs[2], psycho_ce_intr, 0, + "PSYCHO_CE", pbm); + request_irq(op->irqs[0], psycho_pcierr_intr, 0, + "PSYCHO_PCIERR", pbm); /* Enable UE and CE interrupts for controller. */ psycho_write(base + PSYCHO_ECC_CTRL, @@ -918,25 +914,16 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void pbm_scan_bus(struct pci_controller_info *p, - struct pci_pbm_info *pbm) +static void psycho_scan_bus(struct pci_pbm_info *pbm) { + pbm_config_busmastering(pbm); + pbm->is_66mhz_capable = 0; pbm->pci_bus = pci_scan_one_pbm(pbm); -} - -static void psycho_scan_bus(struct pci_controller_info *p) -{ - pbm_config_busmastering(&p->pbm_B); - p->pbm_B.is_66mhz_capable = 0; - pbm_config_busmastering(&p->pbm_A); - p->pbm_A.is_66mhz_capable = 1; - pbm_scan_bus(p, &p->pbm_B); - pbm_scan_bus(p, &p->pbm_A); /* After the PCI bus scan is complete, we can register * the error interrupt handlers. */ - psycho_register_error_handlers(p); + psycho_register_error_handlers(pbm); } static void psycho_iommu_init(struct pci_controller_info *p) @@ -1096,6 +1083,11 @@ static void psycho_pbm_init(struct pci_controller_info *p, else pbm = &p->pbm_B; + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + + pbm->scan_bus = psycho_scan_bus; + pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; pbm->chip_version = 0; prop = of_find_property(dp, "version#", NULL); @@ -1127,6 +1119,7 @@ void psycho_init(struct device_node *dp, char *model_name) { struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; + struct pci_pbm_info *pbm; struct iommu *iommu; struct property *prop; u32 upa_portid; @@ -1137,7 +1130,9 @@ void psycho_init(struct device_node *dp, char *model_name) if (prop) upa_portid = *(u32 *) prop->value; - for(p = pci_controller_root; p; p = p->next) { + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + struct pci_controller_info *p = pbm->parent; + if (p->pbm_A.portid == upa_portid) { is_pbm_a = (p->pbm_A.prom_node == NULL); psycho_pbm_init(p, dp, is_pbm_a); @@ -1157,13 +1152,9 @@ void psycho_init(struct device_node *dp, char *model_name) } p->pbm_A.iommu = p->pbm_B.iommu = iommu; - p->next = pci_controller_root; - pci_controller_root = p; - p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; p->index = pci_num_controllers++; - p->scan_bus = psycho_scan_bus; p->pci_ops = &psycho_ops; prop = of_find_property(dp, "reg", NULL); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 9e706013d11..024dbd8ad02 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -825,9 +825,9 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) return IRQ_HANDLED; } -static void sabre_register_error_handlers(struct pci_controller_info *p) +static void sabre_register_error_handlers(struct pci_pbm_info *pbm) { - struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ + struct pci_controller_info *p = pbm->parent; struct device_node *dp = pbm->prom_node; struct of_device *op; unsigned long base = pbm->controller_regs; @@ -858,22 +858,22 @@ static void sabre_register_error_handlers(struct pci_controller_info *p) SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); - request_irq(op->irqs[1], sabre_ue_intr, IRQF_SHARED, "SABRE UE", p); + request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", p); sabre_write(base + SABRE_CE_AFSR, (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR)); - request_irq(op->irqs[2], sabre_ce_intr, IRQF_SHARED, "SABRE CE", p); - request_irq(op->irqs[0], sabre_pcierr_intr, IRQF_SHARED, - "SABRE PCIERR", p); + request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", p); + request_irq(op->irqs[0], sabre_pcierr_intr, 0, + "SABRE_PCIERR", p); tmp = sabre_read(base + SABRE_PCICTRL); tmp |= SABRE_PCICTRL_ERREN; sabre_write(base + SABRE_PCICTRL, tmp); } -static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) +static void apb_init(struct pci_bus *sabre_bus) { struct pci_dev *pdev; @@ -909,7 +909,7 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) } } -static void sabre_scan_bus(struct pci_controller_info *p) +static void sabre_scan_bus(struct pci_pbm_info *pbm) { static int once; struct pci_bus *pbus; @@ -918,7 +918,7 @@ static void sabre_scan_bus(struct pci_controller_info *p) * at 66Mhz, but the front side of APB runs at 33Mhz * for both segments. */ - p->pbm_A.is_66mhz_capable = 0; + pbm->is_66mhz_capable = 0; /* This driver has not been verified to handle * multiple SABREs yet, so trap this. @@ -932,15 +932,15 @@ static void sabre_scan_bus(struct pci_controller_info *p) } once++; - pbus = pci_scan_one_pbm(&p->pbm_A); + pbus = pci_scan_one_pbm(pbm); if (!pbus) return; sabre_root_bus = pbus; - apb_init(p, pbus); + apb_init(pbus); - sabre_register_error_handlers(p); + sabre_register_error_handlers(pbm); } static void sabre_iommu_init(struct pci_controller_info *p, @@ -1003,6 +1003,8 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp pbm->name = dp->full_name; printk("%s: SABRE PCI Bus Module\n", pbm->name); + pbm->scan_bus = sabre_scan_bus; + pbm->chip_type = PBM_CHIP_TYPE_SABRE; pbm->parent = p; pbm->prom_node = dp; @@ -1055,12 +1057,11 @@ void sabre_init(struct device_node *dp, char *model_name) upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); - p->next = pci_controller_root; - pci_controller_root = p; + p->pbm_A.next = pci_pbm_root; + pci_pbm_root = &p->pbm_A; p->pbm_A.portid = upa_portid; p->index = pci_num_controllers++; - p->scan_bus = sabre_scan_bus; p->pci_ops = &sabre_ops; /* diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index c0a6a3866e2..4ebdcbd5262 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -238,25 +238,6 @@ static unsigned long stc_line_buf[16]; #define SCHIZO_PCIERR_B_INO 0x33 /* PBM B PCI bus error */ #define SCHIZO_SERR_INO 0x34 /* Safari interface error */ -struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) -{ - ino &= IMAP_INO; - if (p->pbm_A.ino_bitmap & (1UL << ino)) - return &p->pbm_A; - if (p->pbm_B.ino_bitmap & (1UL << ino)) - return &p->pbm_B; - - printk("PCI%d: No ino_bitmap entry for ino[%x], bitmaps " - "PBM_A[%016lx] PBM_B[%016lx]", - p->index, ino, - p->pbm_A.ino_bitmap, - p->pbm_B.ino_bitmap); - printk("PCI%d: Using PBM_A, report this problem immediately.\n", - p->index); - - return &p->pbm_A; -} - #define SCHIZO_STC_ERR 0xb800UL /* --> 0xba00 */ #define SCHIZO_STC_TAG 0xba00UL /* --> 0xba80 */ #define SCHIZO_STC_LINE 0xbb00UL /* --> 0xbb80 */ @@ -522,9 +503,10 @@ static void schizo_check_iommu_error(struct pci_controller_info *p, static irqreturn_t schizo_ue_intr(int irq, void *dev_id) { - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFSR; - unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_UE_AFAR; + 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; int reported, limit; @@ -610,9 +592,10 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) static irqreturn_t schizo_ce_intr(int irq, void *dev_id) { - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFSR; - unsigned long afar_reg = p->pbm_B.controller_regs + SCHIZO_CE_AFAR; + struct pci_pbm_info *pbm = dev_id; + struct pci_controller_info *p = pbm->parent; + unsigned long afsr_reg = pbm->controller_regs + SCHIZO_CE_AFSR; + unsigned long afar_reg = pbm->controller_regs + SCHIZO_CE_AFAR; unsigned long afsr, afar, error_bits; int reported, limit; @@ -940,11 +923,12 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) */ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) { - struct pci_controller_info *p = dev_id; + struct pci_pbm_info *pbm = dev_id; + struct pci_controller_info *p = pbm->parent; u64 errlog; - errlog = schizo_read(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG); - schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRLOG, + errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); + schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG, errlog & ~(SAFARI_ERRLOG_ERROUT)); if (!(errlog & BUS_ERROR_UNMAP)) { @@ -972,6 +956,16 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) #define SCHIZO_SAFARI_IRQCTRL 0x10010UL #define SCHIZO_SAFIRQCTRL_EN 0x8000000000000000UL +static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino) +{ + ino &= IMAP_INO; + + if (pbm->ino_bitmap & (1UL << ino)) + return 1; + + return 0; +} + /* How the Tomatillo IRQs are routed around is pure guesswork here. * * All the Tomatillo devices I see in prtconf dumps seem to have only @@ -986,10 +980,9 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) * PCI bus units of the same Tomatillo. I still have not really * figured this out... */ -static void tomatillo_register_error_handlers(struct pci_controller_info *p) +static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) { - struct pci_pbm_info *pbm; - struct of_device *op; + struct of_device *op = of_find_device_by_node(pbm->prom_node); u64 tmp, err_mask, err_no_mask; /* Tomatillo IRQ property layout is: @@ -1000,44 +993,27 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) * 4: POWER FAIL? */ - pbm = pbm_for_ino(p, SCHIZO_UE_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[1], schizo_ue_intr, IRQF_SHARED, - "TOMATILLO_UE", p); - - pbm = pbm_for_ino(p, SCHIZO_CE_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[2], schizo_ce_intr, IRQF_SHARED, - "TOMATILLO CE", p); - - pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, - "TOMATILLO PCIERR-A", pbm); - - - pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, - "TOMATILLO PCIERR-B", pbm); - - pbm = pbm_for_ino(p, SCHIZO_SERR_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[3], schizo_safarierr_intr, IRQF_SHARED, - "TOMATILLO SERR", p); + if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) + request_irq(op->irqs[1], schizo_ue_intr, 0, + "TOMATILLO_UE", pbm); - /* Enable UE and CE interrupts for controller. */ - schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, - (SCHIZO_ECCCTRL_EE | - SCHIZO_ECCCTRL_UE | - SCHIZO_ECCCTRL_CE)); + if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) + request_irq(op->irqs[2], schizo_ce_intr, 0, + "TOMATILLO_CE", pbm); + + if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) + request_irq(op->irqs[0], schizo_pcierr_intr, 0, + "TOMATILLO_PCIERR", pbm); + else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) + request_irq(op->irqs[0], schizo_pcierr_intr, 0, + "TOMATILLO_PCIERR", pbm); - schizo_write(p->pbm_B.controller_regs + SCHIZO_ECC_CTRL, + if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) + request_irq(op->irqs[3], schizo_safarierr_intr, 0, + "TOMATILLO_SERR", pbm); + + /* Enable UE and CE interrupts for controller. */ + schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, (SCHIZO_ECCCTRL_EE | SCHIZO_ECCCTRL_UE | SCHIZO_ECCCTRL_CE)); @@ -1053,15 +1029,10 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) err_no_mask = SCHIZO_PCICTRL_DTO_ERR; - tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL); - tmp |= err_mask; - tmp &= ~err_no_mask; - schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp); - - tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL); + tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); tmp |= err_mask; tmp &= ~err_no_mask; - schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp); + schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | @@ -1070,8 +1041,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | SCHIZO_PCIAFSR_STTO); - schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR, err_mask); - schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR, err_mask); + schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, err_mask); err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR | BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | @@ -1083,21 +1053,16 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) BUS_ERROR_APERR | BUS_ERROR_UNMAP | BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); - schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL, - (SCHIZO_SAFERRCTRL_EN | err_mask)); - schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRCTRL, + schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, (SCHIZO_SAFERRCTRL_EN | err_mask)); - schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL, - (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); - schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_IRQCTRL, + schizo_write(pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL, (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); } -static void schizo_register_error_handlers(struct pci_controller_info *p) +static void schizo_register_error_handlers(struct pci_pbm_info *pbm) { - struct pci_pbm_info *pbm; - struct of_device *op; + struct of_device *op = of_find_device_by_node(pbm->prom_node); u64 tmp, err_mask, err_no_mask; /* Schizo IRQ property layout is: @@ -1108,39 +1073,27 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) * 4: POWER FAIL? */ - pbm = pbm_for_ino(p, SCHIZO_UE_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[1], schizo_ue_intr, IRQF_SHARED, - "SCHIZO_UE", p); - - pbm = pbm_for_ino(p, SCHIZO_CE_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[2], schizo_ce_intr, IRQF_SHARED, - "SCHIZO CE", p); - - pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, - "SCHIZO PCIERR-A", pbm); - - - pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, - "SCHIZO PCIERR-B", pbm); - - pbm = pbm_for_ino(p, SCHIZO_SERR_INO); - op = of_find_device_by_node(pbm->prom_node); - if (op) - request_irq(op->irqs[3], schizo_safarierr_intr, IRQF_SHARED, - "SCHIZO SERR", p); + if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) + request_irq(op->irqs[1], schizo_ue_intr, 0, + "SCHIZO_UE", pbm); + + if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) + request_irq(op->irqs[2], schizo_ce_intr, 0, + "SCHIZO_CE", pbm); + + if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) + request_irq(op->irqs[0], schizo_pcierr_intr, 0, + "SCHIZO_PCIERR", pbm); + else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) + request_irq(op->irqs[0], schizo_pcierr_intr, 0, + "SCHIZO_PCIERR", pbm); + + if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) + request_irq(op->irqs[3], schizo_safarierr_intr, 0, + "SCHIZO_SERR", pbm); /* Enable UE and CE interrupts for controller. */ - schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL, + schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, (SCHIZO_ECCCTRL_EE | SCHIZO_ECCCTRL_UE | SCHIZO_ECCCTRL_CE)); @@ -1159,25 +1112,12 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) /* Enable PCI Error interrupts and clear error * bits for each PBM. */ - tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL); - tmp |= err_mask; - tmp &= ~err_no_mask; - schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp); - - schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR, - (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | - SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | - SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | - SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | - SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | - SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS)); - - tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL); + tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); tmp |= err_mask; tmp &= ~err_no_mask; - schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp); + schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); - schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR, + schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | @@ -1210,11 +1150,8 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); #endif - schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL, + schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, (SCHIZO_SAFERRCTRL_EN | err_mask)); - - schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL, - (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); } static void pbm_config_busmastering(struct pci_pbm_info *pbm) @@ -1234,27 +1171,19 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void schizo_scan_bus(struct pci_controller_info *p) +static void schizo_scan_bus(struct pci_pbm_info *pbm) { - pbm_config_busmastering(&p->pbm_B); - p->pbm_B.is_66mhz_capable = - (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL) - != NULL); - pbm_config_busmastering(&p->pbm_A); - p->pbm_A.is_66mhz_capable = - (of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL) + pbm_config_busmastering(pbm); + pbm->is_66mhz_capable = + (of_find_property(pbm->prom_node, "66mhz-capable", NULL) != NULL); - p->pbm_B.pci_bus = pci_scan_one_pbm(&p->pbm_B); - p->pbm_A.pci_bus = pci_scan_one_pbm(&p->pbm_A); + pbm->pci_bus = pci_scan_one_pbm(pbm); - /* After the PCI bus scan is complete, we can register - * the error interrupt handlers. - */ - if (p->pbm_B.chip_type == PBM_CHIP_TYPE_TOMATILLO) - tomatillo_register_error_handlers(p); + if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) + tomatillo_register_error_handlers(pbm); else - schizo_register_error_handlers(p); + schizo_register_error_handlers(pbm); } #define SCHIZO_STRBUF_CONTROL (0x02800UL) @@ -1529,6 +1458,11 @@ static void schizo_pbm_init(struct pci_controller_info *p, else pbm = &p->pbm_B; + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + + pbm->scan_bus = schizo_scan_bus; + pbm->portid = portid; pbm->parent = p; pbm->prom_node = dp; @@ -1572,23 +1506,15 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) static void __schizo_init(struct device_node *dp, char *model_name, int chip_type) { struct pci_controller_info *p; + struct pci_pbm_info *pbm; struct iommu *iommu; u32 portid; portid = of_getintprop_default(dp, "portid", 0xff); - for (p = pci_controller_root; p; p = p->next) { - struct pci_pbm_info *pbm; - - if (p->pbm_A.prom_node && p->pbm_B.prom_node) - continue; - - pbm = (p->pbm_A.prom_node ? - &p->pbm_A : - &p->pbm_B); - + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (portid_compare(pbm->portid, portid, chip_type)) { - schizo_pbm_init(p, dp, portid, chip_type); + schizo_pbm_init(pbm->parent, dp, portid, chip_type); return; } } @@ -1609,11 +1535,7 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ p->pbm_B.iommu = iommu; - p->next = pci_controller_root; - pci_controller_root = p; - p->index = pci_num_controllers++; - p->scan_bus = schizo_scan_bus; p->pci_ops = &schizo_ops; /* Like PSYCHO we have a 2GB aligned area for memory space. */ diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 1491ba33058..0a101cb2232 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -677,29 +677,15 @@ static struct pci_ops pci_sun4v_ops = { }; -static void pbm_scan_bus(struct pci_controller_info *p, - struct pci_pbm_info *pbm) -{ - pbm->pci_bus = pci_scan_one_pbm(pbm); -} - -static void pci_sun4v_scan_bus(struct pci_controller_info *p) +static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) { struct property *prop; struct device_node *dp; - if ((dp = p->pbm_A.prom_node) != NULL) { - prop = of_find_property(dp, "66mhz-capable", NULL); - p->pbm_A.is_66mhz_capable = (prop != NULL); - - pbm_scan_bus(p, &p->pbm_A); - } - if ((dp = p->pbm_B.prom_node) != NULL) { - prop = of_find_property(dp, "66mhz-capable", NULL); - p->pbm_B.is_66mhz_capable = (prop != NULL); - - pbm_scan_bus(p, &p->pbm_B); - } + dp = pbm->prom_node; + prop = of_find_property(dp, "66mhz-capable", NULL); + pbm->is_66mhz_capable = (prop != NULL); + pbm->pci_bus = pci_scan_one_pbm(pbm); /* XXX register error interrupt handlers XXX */ } @@ -1246,6 +1232,11 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node else pbm = &p->pbm_A; + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + + pbm->scan_bus = pci_sun4v_scan_bus; + pbm->parent = p; pbm->prom_node = dp; @@ -1265,6 +1256,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node void sun4v_pci_init(struct device_node *dp, char *model_name) { struct pci_controller_info *p; + struct pci_pbm_info *pbm; struct iommu *iommu; struct property *prop; struct linux_prom64_registers *regs; @@ -1276,18 +1268,9 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; - for (p = pci_controller_root; p; p = p->next) { - struct pci_pbm_info *pbm; - - if (p->pbm_A.prom_node && p->pbm_B.prom_node) - continue; - - pbm = (p->pbm_A.prom_node ? - &p->pbm_A : - &p->pbm_B); - + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (pbm->devhandle == (devhandle ^ 0x40)) { - pci_sun4v_pbm_init(p, dp, devhandle); + pci_sun4v_pbm_init(pbm->parent, dp, devhandle); return; } } @@ -1317,12 +1300,8 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) p->pbm_B.iommu = iommu; - p->next = pci_controller_root; - pci_controller_root = p; - p->index = pci_num_controllers++; - p->scan_bus = pci_sun4v_scan_bus; #ifdef CONFIG_PCI_MSI p->setup_msi_irq = pci_sun4v_setup_msi_irq; p->teardown_msi_irq = pci_sun4v_teardown_msi_irq; diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index c8868babc4f..cc0e2677773 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -39,6 +39,8 @@ extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offse struct pci_controller_info; struct pci_pbm_info { + struct pci_pbm_info *next; + /* PCI controller we sit under. */ struct pci_controller_info *parent; @@ -113,12 +115,10 @@ struct pci_pbm_info { unsigned int pci_first_busno; unsigned int pci_last_busno; struct pci_bus *pci_bus; + void (*scan_bus)(struct pci_pbm_info *); }; struct pci_controller_info { - /* List of all PCI controllers. */ - struct pci_controller_info *next; - /* Each controller gets a unique index, used mostly for * error logging purposes. */ @@ -129,8 +129,6 @@ struct pci_controller_info { struct pci_pbm_info pbm_B; /* Operations which are controller specific. */ - void (*scan_bus)(struct pci_controller_info *); - #ifdef CONFIG_PCI_MSI int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, struct msi_desc *entry); |