aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sparc64/kernel/pci.c12
-rw-r--r--arch/sparc64/kernel/pci_fire.c39
-rw-r--r--arch/sparc64/kernel/pci_impl.h2
-rw-r--r--arch/sparc64/kernel/pci_psycho.c107
-rw-r--r--arch/sparc64/kernel/pci_sabre.c31
-rw-r--r--arch/sparc64/kernel/pci_schizo.c256
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c47
-rw-r--r--include/asm-sparc64/pbm.h8
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);