From cfa0652c4eb4ca37f88fcdd7d871cf98d9d98c0e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 May 2007 21:51:41 -0700 Subject: [PATCH 01/14] [SPARC64] PCI: Use common routine to fetch PBM properties. Namely bus-range and ino-bitmap. This allows us also to eliminate pci_controller_info's pci_{first,last}_busno fields as only the pbm ones are used now. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_common.c | 14 ++++++++++++++ arch/sparc64/kernel/pci_fire.c | 10 +--------- arch/sparc64/kernel/pci_impl.h | 1 + arch/sparc64/kernel/pci_psycho.c | 6 +----- arch/sparc64/kernel/pci_sabre.c | 8 +------- arch/sparc64/kernel/pci_schizo.c | 10 +--------- arch/sparc64/kernel/pci_sun4v.c | 16 +--------------- include/asm-sparc64/pbm.h | 2 -- 8 files changed, 20 insertions(+), 47 deletions(-) diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 1e6aeedf43c4..b1168bfa16fb 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -15,6 +15,20 @@ #include "pci_impl.h" +void pci_get_pbm_props(struct pci_pbm_info *pbm) +{ + const u32 *val = of_get_property(pbm->prom_node, "bus-range", NULL); + + pbm->pci_first_busno = val[0]; + pbm->pci_last_busno = val[1]; + + val = of_get_property(pbm->prom_node, "ino-bitmap", NULL); + if (val) { + pbm->ino_bitmap = (((u64)val[1] << 32UL) | + ((u64)val[0] << 0UL)); + } +} + static void pci_register_legacy_regions(struct resource *io_res, struct resource *mem_res) { diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 0fe626631e12..79ee5be948eb 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -317,8 +317,6 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, { const struct linux_prom64_registers *regs; struct pci_pbm_info *pbm; - const u32 *ino_bitmap; - const unsigned int *busrange; if ((portid & 1) == 0) pbm = &p->pbm_A; @@ -338,13 +336,7 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); - ino_bitmap = of_get_property(dp, "ino-bitmap", NULL); - pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | - ((u64)ino_bitmap[0] << 0UL)); - - busrange = of_get_property(dp, "bus-range", NULL); - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; + pci_get_pbm_props(pbm); pci_fire_hw_init(pbm); pci_fire_pbm_iommu_init(pbm); diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 1208583fcb83..41c3f5137306 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -17,6 +17,7 @@ extern unsigned long pci_memspace_mask; extern int pci_num_controllers; /* PCI bus scanning and fixup support. */ +extern void pci_get_pbm_props(struct pci_pbm_info *pbm); extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 253d40ec2245..0f35135a40c5 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1088,7 +1088,6 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p, static void psycho_pbm_init(struct pci_controller_info *p, struct device_node *dp, int is_pbm_a) { - unsigned int *busrange; struct property *prop; struct pci_pbm_info *pbm; @@ -1117,10 +1116,7 @@ static void psycho_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); - prop = of_find_property(dp, "bus-range", NULL); - busrange = prop->value; - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; + pci_get_pbm_props(pbm); psycho_pbm_strbuf_init(p, pbm, is_pbm_a); } diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 397862fbd9e1..9e706013d11a 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1006,8 +1006,7 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp pbm->chip_type = PBM_CHIP_TYPE_SABRE; pbm->parent = p; pbm->prom_node = dp; - pbm->pci_first_busno = p->pci_first_busno; - pbm->pci_last_busno = p->pci_last_busno; + pci_get_pbm_props(pbm); pci_determine_mem_io_space(pbm); } @@ -1018,7 +1017,6 @@ void sabre_init(struct device_node *dp, char *model_name) struct pci_controller_info *p; struct iommu *iommu; int tsbsize; - const u32 *busrange; const u32 *vdma; u32 upa_portid, dma_mask; u64 clear_irq; @@ -1119,10 +1117,6 @@ void sabre_init(struct device_node *dp, char *model_name) sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); - busrange = of_get_property(dp, "bus-range", NULL); - p->pci_first_busno = busrange[0]; - p->pci_last_busno = busrange[1]; - /* * Look for APB underneath. */ diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 91a7385e5d32..c0a6a3866e2f 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1491,10 +1491,8 @@ static void schizo_pbm_init(struct pci_controller_info *p, int chip_type) { const struct linux_prom64_registers *regs; - const unsigned int *busrange; struct pci_pbm_info *pbm; const char *chipset_name; - const u32 *ino_bitmap; int is_pbm_a; switch (chip_type) { @@ -1555,13 +1553,7 @@ static void schizo_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); - ino_bitmap = of_get_property(dp, "ino-bitmap", NULL); - pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | - ((u64)ino_bitmap[0] << 0UL)); - - busrange = of_get_property(dp, "bus-range", NULL); - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; + pci_get_pbm_props(pbm); schizo_pbm_iommu_init(pbm); schizo_pbm_strbuf_init(pbm); diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 1ccf4c9a9a43..1491ba330583 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -802,20 +802,6 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) pbm->name, sz); } -static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) -{ - struct property *prop; - unsigned int *busrange; - - prop = of_find_property(pbm->prom_node, "bus-range", NULL); - - busrange = prop->value; - - pbm->pci_first_busno = busrange[0]; - pbm->pci_last_busno = busrange[1]; - -} - #ifdef CONFIG_PCI_MSI struct pci_sun4v_msiq_entry { u64 version_type; @@ -1271,7 +1257,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pci_determine_mem_io_space(pbm); - pci_sun4v_get_bus_range(pbm); + pci_get_pbm_props(pbm); pci_sun4v_iommu_init(pbm); pci_sun4v_msi_init(pbm); } diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index c008cecca149..43b7270ec02e 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -145,8 +145,6 @@ struct pci_controller_info { /* Now things for the actual PCI bus probes. */ struct pci_ops *pci_ops; - unsigned int pci_first_busno; - unsigned int pci_last_busno; }; #endif /* !(__SPARC64_PBM_H) */ From 5a4a3e592d0d66653297049373caa7ac5b4febe0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 May 2007 21:54:28 -0700 Subject: [PATCH 02/14] [SPARC64] PCI: Kill PROM_PCIRNG_MAX and PROM_PCIIMAP_MAX. They are totally unused. Signed-off-by: David S. Miller --- include/asm-sparc64/pbm.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 43b7270ec02e..c8868babc4fe 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -36,12 +36,6 @@ extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offse #define PCI_STC_FLUSHFLAG_SET(STC) \ (*((STC)->strbuf_flushflag) != 0UL) -/* There can be quite a few ranges and interrupt maps on a PCI - * segment. Thus... - */ -#define PROM_PCIRNG_MAX 64 -#define PROM_PCIIMAP_MAX 64 - struct pci_controller_info; struct pci_pbm_info { From 34768bc8329194b14e42ee408a84edfa40059046 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 May 2007 23:06:27 -0700 Subject: [PATCH 03/14] [SPARC64] PCI: Use root list of pbm's instead of pci_controller_info's The idea is to move more and more things into the pbm, with the eventual goal of eliminating the pci_controller_info entirely as there really isn't any need for it. This stage of the transformations requires some reworking of the PCI error interrupt handling. It might be tricky to get rid of the pci_controller_info parenting for a few reasons: 1) When we get an uncorrectable or correctable error we want to interrogate the IOMMU and streaming cache of both PBMs for error status. These errors come from the UPA front-end which is shared between the two PBM PCI bus segments. Historically speaking this is why I choose the datastructure hierarchy of pci_controller_info-->pci_pbm_info 2) The probing does a portid/devhandle match to look for the 'other' pbm, but this is entirely an artifact and can be eliminated trivially. What we could do to solve #1 is to have a "buddy" pointer from one pbm to another. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 12 +- arch/sparc64/kernel/pci_fire.c | 39 ++--- arch/sparc64/kernel/pci_impl.h | 2 +- arch/sparc64/kernel/pci_psycho.c | 107 +++++++------- arch/sparc64/kernel/pci_sabre.c | 31 ++-- arch/sparc64/kernel/pci_schizo.c | 244 +++++++++++-------------------- arch/sparc64/kernel/pci_sun4v.c | 47 ++---- include/asm-sparc64/pbm.h | 8 +- 8 files changed, 181 insertions(+), 309 deletions(-) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 966861b212be..c17723fb1c31 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 79ee5be948eb..f55c08ae0aa0 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 41c3f5137306..3dd6d02b2d81 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -11,7 +11,7 @@ #include #include -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 0f35135a40c5..4801eb441236 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 9e706013d11a..024dbd8ad025 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 c0a6a3866e2f..4ebdcbd5262a 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); + if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) + request_irq(op->irqs[1], schizo_ue_intr, 0, + "TOMATILLO_UE", pbm); - 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); + if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) + request_irq(op->irqs[2], schizo_ce_intr, 0, + "TOMATILLO_CE", pbm); - 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); + 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); - - 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_SERR_INO)) + request_irq(op->irqs[3], schizo_safarierr_intr, 0, + "TOMATILLO_SERR", 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)); - - schizo_write(p->pbm_B.controller_regs + SCHIZO_ECC_CTRL, + 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 = schizo_read(pbm->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 |= 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); + if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) + request_irq(op->irqs[1], schizo_ue_intr, 0, + "SCHIZO_UE", pbm); - 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); + if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) + request_irq(op->irqs[2], schizo_ce_intr, 0, + "SCHIZO_CE", pbm); - 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); + 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); - - 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_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 = schizo_read(pbm->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(pbm->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 |= err_mask; - tmp &= ~err_no_mask; - schizo_write(p->pbm_B.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 1491ba330583..0a101cb22320 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 c8868babc4fe..cc0e2677773f 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); From 96a496fd49fb2c3178128237ae4691b7c7df3a3d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 May 2007 23:08:39 -0700 Subject: [PATCH 04/14] [SPARC64] SBUS: Error interrupt registry cleanups. Do not use IRQF_SHARED, these interrupt numbers should all be unique. Also use name strings without spaces in them just like PCI controller drivers do, for consistency. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sbus.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 3b05428cc909..91f6e2a74ad5 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -1002,24 +1002,24 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) u64 control; irq = sbus_build_irq(sbus, SYSIO_UE_INO); - if (request_irq(irq, sysio_ue_handler, - IRQF_SHARED, "SYSIO UE", sbus) < 0) { + if (request_irq(irq, sysio_ue_handler, 0, + "SYSIO_UE", sbus) < 0) { prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", sbus->portid); prom_halt(); } irq = sbus_build_irq(sbus, SYSIO_CE_INO); - if (request_irq(irq, sysio_ce_handler, - IRQF_SHARED, "SYSIO CE", sbus) < 0) { + if (request_irq(irq, sysio_ce_handler, 0, + "SYSIO_CE", sbus) < 0) { prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", sbus->portid); prom_halt(); } irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); - if (request_irq(irq, sysio_sbus_error_handler, - IRQF_SHARED, "SYSIO SBUS Error", sbus) < 0) { + if (request_irq(irq, sysio_sbus_error_handler, 0, + "SYSIO_SBERR", sbus) < 0) { prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", sbus->portid); prom_halt(); From f1cd8de2c951e206b57fd76aff279cf13ea25815 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 May 2007 23:24:05 -0700 Subject: [PATCH 05/14] [SPARC64]: Move pci_ops into pci_pbm_info. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 3 +-- arch/sparc64/kernel/pci_fire.c | 2 +- arch/sparc64/kernel/pci_psycho.c | 2 +- arch/sparc64/kernel/pci_sabre.c | 2 +- arch/sparc64/kernel/pci_schizo.c | 2 +- arch/sparc64/kernel/pci_sun4v.c | 2 +- include/asm-sparc64/pbm.h | 4 +--- 7 files changed, 7 insertions(+), 10 deletions(-) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index c17723fb1c31..b583deb05062 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -743,7 +743,6 @@ int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) { - struct pci_controller_info *p = pbm->parent; struct device_node *node = pbm->prom_node; struct pci_dev *host_pdev; struct pci_bus *bus; @@ -751,7 +750,7 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) printk("PCI: Scanning PBM %s\n", node->full_name); /* XXX parent device? XXX */ - bus = pci_create_bus(NULL, pbm->pci_first_busno, p->pci_ops, pbm); + bus = pci_create_bus(NULL, pbm->pci_first_busno, pbm->pci_ops, pbm); if (!bus) { printk(KERN_ERR "Failed to create bus for %s\n", node->full_name); diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index f55c08ae0aa0..ac40529a5721 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -315,6 +315,7 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, pci_pbm_root = pbm; pbm->scan_bus = pci_fire_scan_bus; + pbm->pci_ops = &pci_fire_ops; pbm->portid = portid; pbm->parent = p; @@ -375,7 +376,6 @@ void fire_pci_init(struct device_node *dp, const char *model_name) p->index = pci_num_controllers++; /* XXX MSI support XXX */ - p->pci_ops = &pci_fire_ops; /* Like PSYCHO and SCHIZO we have a 2GB aligned area * for memory space. diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 4801eb441236..405c1dba781b 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1087,6 +1087,7 @@ static void psycho_pbm_init(struct pci_controller_info *p, pci_pbm_root = pbm; pbm->scan_bus = psycho_scan_bus; + pbm->pci_ops = &psycho_ops; pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; pbm->chip_version = 0; @@ -1155,7 +1156,6 @@ void psycho_init(struct device_node *dp, char *model_name) p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; p->index = pci_num_controllers++; - p->pci_ops = &psycho_ops; prop = of_find_property(dp, "reg", NULL); pr_regs = prop->value; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 024dbd8ad025..ec265a30af43 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1004,6 +1004,7 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp printk("%s: SABRE PCI Bus Module\n", pbm->name); pbm->scan_bus = sabre_scan_bus; + pbm->pci_ops = &sabre_ops; pbm->chip_type = PBM_CHIP_TYPE_SABRE; pbm->parent = p; @@ -1062,7 +1063,6 @@ void sabre_init(struct device_node *dp, char *model_name) p->pbm_A.portid = upa_portid; p->index = pci_num_controllers++; - p->pci_ops = &sabre_ops; /* * Map in SABRE register set and report the presence of this SABRE. diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 4ebdcbd5262a..a0da7f2c344e 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1462,6 +1462,7 @@ static void schizo_pbm_init(struct pci_controller_info *p, pci_pbm_root = pbm; pbm->scan_bus = schizo_scan_bus; + pbm->pci_ops = &schizo_ops; pbm->portid = portid; pbm->parent = p; @@ -1536,7 +1537,6 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ p->pbm_B.iommu = iommu; p->index = pci_num_controllers++; - p->pci_ops = &schizo_ops; /* Like PSYCHO we have a 2GB aligned area for memory space. */ pci_memspace_mask = 0x7fffffffUL; diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 0a101cb22320..ea61fec206a7 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -1236,6 +1236,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pci_pbm_root = pbm; pbm->scan_bus = pci_sun4v_scan_bus; + pbm->pci_ops = &pci_sun4v_ops; pbm->parent = p; pbm->prom_node = dp; @@ -1306,7 +1307,6 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) p->setup_msi_irq = pci_sun4v_setup_msi_irq; p->teardown_msi_irq = pci_sun4v_teardown_msi_irq; #endif - p->pci_ops = &pci_sun4v_ops; /* Like PSYCHO and SCHIZO we have a 2GB aligned area * for memory space. diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index cc0e2677773f..1f4de53dcd03 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -116,6 +116,7 @@ struct pci_pbm_info { unsigned int pci_last_busno; struct pci_bus *pci_bus; void (*scan_bus)(struct pci_pbm_info *); + struct pci_ops *pci_ops; }; struct pci_controller_info { @@ -134,9 +135,6 @@ struct pci_controller_info { struct msi_desc *entry); void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); #endif - - /* Now things for the actual PCI bus probes. */ - struct pci_ops *pci_ops; }; #endif /* !(__SPARC64_PBM_H) */ From e9870c4c0aef94580e28be11a1c6246dcabbe528 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 May 2007 23:28:50 -0700 Subject: [PATCH 06/14] [SPARC64]: Move {setup,teardown}_msi_irq into pci_pbm_info. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 16 +-- arch/sparc64/kernel/pci_sun4v.c | 224 ++++++++++++++++---------------- include/asm-sparc64/pbm.h | 10 +- 3 files changed, 119 insertions(+), 131 deletions(-) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index b583deb05062..4d30d57c4619 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -1092,17 +1092,12 @@ EXPORT_SYMBOL(pci_domain_nr); int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) { struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - struct pci_controller_info *p = pbm->parent; - int virt_irq, err; + int virt_irq; - if (!pbm->msi_num || !p->setup_msi_irq) + if (!pbm->setup_msi_irq) return -EINVAL; - err = p->setup_msi_irq(&virt_irq, pdev, desc); - if (err) - return err; - - return 0; + return pbm->setup_msi_irq(&virt_irq, pdev, desc); } void arch_teardown_msi_irq(unsigned int virt_irq) @@ -1110,12 +1105,11 @@ void arch_teardown_msi_irq(unsigned int virt_irq) struct msi_desc *entry = get_irq_msi(virt_irq); struct pci_dev *pdev = entry->dev; struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - struct pci_controller_info *p = pbm->parent; - if (!pbm->msi_num || !p->setup_msi_irq) + if (!pbm->teardown_msi_irq) return; - return p->teardown_msi_irq(virt_irq, pdev); + return pbm->teardown_msi_irq(virt_irq, pdev); } #endif /* !(CONFIG_PCI_MSI) */ diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index ea61fec206a7..7ebc04f9a880 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -991,114 +991,6 @@ h_error: return -EINVAL; } -static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) -{ - const u32 *val; - int len; - - val = of_get_property(pbm->prom_node, "#msi-eqs", &len); - if (!val || len != 4) - goto no_msi; - pbm->msiq_num = *val; - if (pbm->msiq_num) { - const struct msiq_prop { - u32 first_msiq; - u32 num_msiq; - u32 first_devino; - } *mqp; - const struct msi_range_prop { - u32 first_msi; - u32 num_msi; - } *mrng; - const struct addr_range_prop { - u32 msi32_high; - u32 msi32_low; - u32 msi32_len; - u32 msi64_high; - u32 msi64_low; - u32 msi64_len; - } *arng; - - val = of_get_property(pbm->prom_node, "msi-eq-size", &len); - if (!val || len != 4) - goto no_msi; - - pbm->msiq_ent_count = *val; - - mqp = of_get_property(pbm->prom_node, - "msi-eq-to-devino", &len); - if (!mqp || len != sizeof(struct msiq_prop)) - goto no_msi; - - pbm->msiq_first = mqp->first_msiq; - pbm->msiq_first_devino = mqp->first_devino; - - val = of_get_property(pbm->prom_node, "#msi", &len); - if (!val || len != 4) - goto no_msi; - pbm->msi_num = *val; - - mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); - if (!mrng || len != sizeof(struct msi_range_prop)) - goto no_msi; - pbm->msi_first = mrng->first_msi; - - val = of_get_property(pbm->prom_node, "msi-data-mask", &len); - if (!val || len != 4) - goto no_msi; - pbm->msi_data_mask = *val; - - val = of_get_property(pbm->prom_node, "msix-data-width", &len); - if (!val || len != 4) - goto no_msi; - pbm->msix_data_width = *val; - - arng = of_get_property(pbm->prom_node, "msi-address-ranges", - &len); - if (!arng || len != sizeof(struct addr_range_prop)) - goto no_msi; - pbm->msi32_start = ((u64)arng->msi32_high << 32) | - (u64) arng->msi32_low; - pbm->msi64_start = ((u64)arng->msi64_high << 32) | - (u64) arng->msi64_low; - pbm->msi32_len = arng->msi32_len; - pbm->msi64_len = arng->msi64_len; - - if (msi_bitmap_alloc(pbm)) - goto no_msi; - - if (msi_queue_alloc(pbm)) { - msi_bitmap_free(pbm); - goto no_msi; - } - - printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " - "devino[0x%x]\n", - pbm->name, - pbm->msiq_first, pbm->msiq_num, - pbm->msiq_ent_count, - pbm->msiq_first_devino); - printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " - "width[%u]\n", - pbm->name, - pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, - pbm->msix_data_width); - printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " - "addr64[0x%lx:0x%x]\n", - pbm->name, - pbm->msi32_start, pbm->msi32_len, - pbm->msi64_start, pbm->msi64_len); - printk(KERN_INFO "%s: MSI queues at RA [%p]\n", - pbm->name, - pbm->msi_queues); - } - - return; - -no_msi: - pbm->msiq_num = 0; - printk(KERN_INFO "%s: No MSI support.\n", pbm->name); -} static int alloc_msi(struct pci_pbm_info *pbm) { @@ -1217,6 +1109,117 @@ static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, */ sun4v_destroy_msi(virt_irq); } + +static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) +{ + const u32 *val; + int len; + + val = of_get_property(pbm->prom_node, "#msi-eqs", &len); + if (!val || len != 4) + goto no_msi; + pbm->msiq_num = *val; + if (pbm->msiq_num) { + const struct msiq_prop { + u32 first_msiq; + u32 num_msiq; + u32 first_devino; + } *mqp; + const struct msi_range_prop { + u32 first_msi; + u32 num_msi; + } *mrng; + const struct addr_range_prop { + u32 msi32_high; + u32 msi32_low; + u32 msi32_len; + u32 msi64_high; + u32 msi64_low; + u32 msi64_len; + } *arng; + + val = of_get_property(pbm->prom_node, "msi-eq-size", &len); + if (!val || len != 4) + goto no_msi; + + pbm->msiq_ent_count = *val; + + mqp = of_get_property(pbm->prom_node, + "msi-eq-to-devino", &len); + if (!mqp || len != sizeof(struct msiq_prop)) + goto no_msi; + + pbm->msiq_first = mqp->first_msiq; + pbm->msiq_first_devino = mqp->first_devino; + + val = of_get_property(pbm->prom_node, "#msi", &len); + if (!val || len != 4) + goto no_msi; + pbm->msi_num = *val; + + mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); + if (!mrng || len != sizeof(struct msi_range_prop)) + goto no_msi; + pbm->msi_first = mrng->first_msi; + + val = of_get_property(pbm->prom_node, "msi-data-mask", &len); + if (!val || len != 4) + goto no_msi; + pbm->msi_data_mask = *val; + + val = of_get_property(pbm->prom_node, "msix-data-width", &len); + if (!val || len != 4) + goto no_msi; + pbm->msix_data_width = *val; + + arng = of_get_property(pbm->prom_node, "msi-address-ranges", + &len); + if (!arng || len != sizeof(struct addr_range_prop)) + goto no_msi; + pbm->msi32_start = ((u64)arng->msi32_high << 32) | + (u64) arng->msi32_low; + pbm->msi64_start = ((u64)arng->msi64_high << 32) | + (u64) arng->msi64_low; + pbm->msi32_len = arng->msi32_len; + pbm->msi64_len = arng->msi64_len; + + if (msi_bitmap_alloc(pbm)) + goto no_msi; + + if (msi_queue_alloc(pbm)) { + msi_bitmap_free(pbm); + goto no_msi; + } + + printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " + "devino[0x%x]\n", + pbm->name, + pbm->msiq_first, pbm->msiq_num, + pbm->msiq_ent_count, + pbm->msiq_first_devino); + printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " + "width[%u]\n", + pbm->name, + pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, + pbm->msix_data_width); + printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " + "addr64[0x%lx:0x%x]\n", + pbm->name, + pbm->msi32_start, pbm->msi32_len, + pbm->msi64_start, pbm->msi64_len); + printk(KERN_INFO "%s: MSI queues at RA [%p]\n", + pbm->name, + pbm->msi_queues); + } + pbm->setup_msi_irq = pci_sun4v_setup_msi_irq; + pbm->teardown_msi_irq = pci_sun4v_teardown_msi_irq; + + return; + +no_msi: + pbm->msiq_num = 0; + printk(KERN_INFO "%s: No MSI support.\n", pbm->name); +} #else /* CONFIG_PCI_MSI */ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) { @@ -1303,11 +1306,6 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) p->index = pci_num_controllers++; -#ifdef CONFIG_PCI_MSI - p->setup_msi_irq = pci_sun4v_setup_msi_irq; - p->teardown_msi_irq = pci_sun4v_teardown_msi_irq; -#endif - /* Like PSYCHO and SCHIZO we have a 2GB aligned area * for memory space. */ diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 1f4de53dcd03..1d5dcfe133a2 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -103,6 +103,9 @@ struct pci_pbm_info { u32 msi64_len; void *msi_queues; unsigned long *msi_bitmap; + int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, + struct msi_desc *entry); + void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); #endif /* !(CONFIG_PCI_MSI) */ /* This PBM's streaming buffer. */ @@ -128,13 +131,6 @@ struct pci_controller_info { /* The PCI bus modules controlled by us. */ struct pci_pbm_info pbm_A; struct pci_pbm_info pbm_B; - - /* Operations which are controller specific. */ -#ifdef CONFIG_PCI_MSI - int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, - struct msi_desc *entry); - void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); -#endif }; #endif /* !(__SPARC64_PBM_H) */ From 6c108f1299754877bb5f73ccac5621eb603b97eb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 May 2007 23:49:01 -0700 Subject: [PATCH 07/14] [SPARC64]: Move index info pci_pbm_info. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 10 +-- arch/sparc64/kernel/pci_common.c | 30 ++++----- arch/sparc64/kernel/pci_fire.c | 4 +- arch/sparc64/kernel/pci_impl.h | 8 +-- arch/sparc64/kernel/pci_psycho.c | 77 ++++++++++------------ arch/sparc64/kernel/pci_sabre.c | 106 +++++++++++++++---------------- arch/sparc64/kernel/pci_schizo.c | 51 ++++++++------- arch/sparc64/kernel/pci_sun4v.c | 4 +- include/asm-sparc64/pbm.h | 6 +- 9 files changed, 137 insertions(+), 159 deletions(-) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 4d30d57c4619..b8a48db3d82d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -50,8 +50,8 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, /* List of all PCI controllers found in the system. */ struct pci_pbm_info *pci_pbm_root = NULL; -/* Each PCI controller found gets a unique index. */ -int pci_num_controllers = 0; +/* Each PBM found gets a unique index. */ +int pci_num_pbms = 0; volatile int pci_poke_in_progress; volatile int pci_poke_cpu = -1; @@ -1077,11 +1077,7 @@ int pci_domain_nr(struct pci_bus *pbus) if (pbm == NULL || pbm->parent == NULL) { ret = -ENXIO; } else { - struct pci_controller_info *p = pbm->parent; - - ret = p->index; - ret = ((ret << 1) + - ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); + ret = pbm->index; } return ret; diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index b1168bfa16fb..8dcc7cc4ec71 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -163,8 +163,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) } /* Generic helper routines for PCI error reporting. */ -void pci_scan_for_target_abort(struct pci_controller_info *p, - struct pci_pbm_info *pbm, +void pci_scan_for_target_abort(struct pci_pbm_info *pbm, struct pci_bus *pbus) { struct pci_dev *pdev; @@ -179,18 +178,16 @@ void pci_scan_for_target_abort(struct pci_controller_info *p, PCI_STATUS_REC_TARGET_ABORT)); if (error_bits) { pci_write_config_word(pdev, PCI_STATUS, error_bits); - printk("PCI%d(PBM%c): Device [%s] saw Target Abort [%016x]\n", - p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), - pci_name(pdev), status); + printk("%s: Device %s saw Target Abort [%016x]\n", + pbm->name, pci_name(pdev), status); } } list_for_each_entry(bus, &pbus->children, node) - pci_scan_for_target_abort(p, pbm, bus); + pci_scan_for_target_abort(pbm, bus); } -void pci_scan_for_master_abort(struct pci_controller_info *p, - struct pci_pbm_info *pbm, +void pci_scan_for_master_abort(struct pci_pbm_info *pbm, struct pci_bus *pbus) { struct pci_dev *pdev; @@ -204,18 +201,16 @@ void pci_scan_for_master_abort(struct pci_controller_info *p, (status & (PCI_STATUS_REC_MASTER_ABORT)); if (error_bits) { pci_write_config_word(pdev, PCI_STATUS, error_bits); - printk("PCI%d(PBM%c): Device [%s] received Master Abort [%016x]\n", - p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), - pci_name(pdev), status); + printk("%s: Device %s received Master Abort [%016x]\n", + pbm->name, pci_name(pdev), status); } } list_for_each_entry(bus, &pbus->children, node) - pci_scan_for_master_abort(p, pbm, bus); + pci_scan_for_master_abort(pbm, bus); } -void pci_scan_for_parity_error(struct pci_controller_info *p, - struct pci_pbm_info *pbm, +void pci_scan_for_parity_error(struct pci_pbm_info *pbm, struct pci_bus *pbus) { struct pci_dev *pdev; @@ -230,12 +225,11 @@ void pci_scan_for_parity_error(struct pci_controller_info *p, PCI_STATUS_DETECTED_PARITY)); if (error_bits) { pci_write_config_word(pdev, PCI_STATUS, error_bits); - printk("PCI%d(PBM%c): Device [%s] saw Parity Error [%016x]\n", - p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'), - pci_name(pdev), status); + printk("%s: Device %s saw Parity Error [%016x]\n", + pbm->name, pci_name(pdev), status); } } list_for_each_entry(bus, &pbus->children, node) - pci_scan_for_parity_error(p, pbm, bus); + pci_scan_for_parity_error(pbm, bus); } diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index ac40529a5721..5df31300b4d9 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -317,6 +317,8 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, pbm->scan_bus = pci_fire_scan_bus; pbm->pci_ops = &pci_fire_ops; + pbm->index = pci_num_pbms++; + pbm->portid = portid; pbm->parent = p; pbm->prom_node = dp; @@ -373,8 +375,6 @@ void fire_pci_init(struct device_node *dp, const char *model_name) p->pbm_B.iommu = iommu; - p->index = pci_num_controllers++; - /* XXX MSI support XXX */ /* Like PSYCHO and SCHIZO we have a 2GB aligned area diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 3dd6d02b2d81..61505c19fd1e 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -14,7 +14,7 @@ extern struct pci_pbm_info *pci_pbm_root; extern unsigned long pci_memspace_mask; -extern int pci_num_controllers; +extern int pci_num_pbms; /* PCI bus scanning and fixup support. */ extern void pci_get_pbm_props(struct pci_pbm_info *pbm); @@ -31,9 +31,9 @@ extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, u32 value); /* Error reporting support. */ -extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); -extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); -extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); +extern void pci_scan_for_target_abort(struct pci_pbm_info *, struct pci_bus *); +extern void pci_scan_for_master_abort(struct pci_pbm_info *, struct pci_bus *); +extern void pci_scan_for_parity_error(struct pci_pbm_info *, struct pci_bus *); /* Configuration space access. */ extern void pci_config_read8(u8 *addr, u8 *ret); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 405c1dba781b..b6f073ed31d4 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -268,7 +268,6 @@ static unsigned long stc_line_buf[16]; 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 = pbm->controller_regs; unsigned long err_base, tag_base, line_base; @@ -326,9 +325,8 @@ static void __psycho_check_one_stc(struct pci_pbm_info *pbm, unsigned long errval = stc_error_buf[j]; if (errval != 0) { saw_error++; - printk("PSYCHO%d(PBM%c): STC_ERR(%d)[wr(%d)rd(%d)]\n", - p->index, - (is_pbm_a ? 'A' : 'B'), + printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n", + pbm->name, j, (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, (errval & PSYCHO_STCERR_READ) ? 1 : 0); @@ -337,18 +335,16 @@ static void __psycho_check_one_stc(struct pci_pbm_info *pbm, if (saw_error != 0) { unsigned long tagval = stc_tag_buf[i]; unsigned long lineval = stc_line_buf[i]; - printk("PSYCHO%d(PBM%c): STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n", - p->index, - (is_pbm_a ? 'A' : 'B'), + printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n", + pbm->name, i, ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), (tagval & PSYCHO_STCTAG_VPN), ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); - printk("PSYCHO%d(PBM%c): STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" + printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" "V(%d)FOFN(%d)]\n", - p->index, - (is_pbm_a ? 'A' : 'B'), + pbm->name, i, ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), @@ -411,7 +407,6 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, unsigned long afar, enum psycho_error_type type) { - struct pci_controller_info *p = pbm->parent; struct iommu *iommu = pbm->iommu; unsigned long iommu_tag[16]; unsigned long iommu_data[16]; @@ -443,8 +438,8 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, type_string = "ECC Error"; break; }; - printk("PSYCHO%d: IOMMU Error, type[%s]\n", - p->index, type_string); + printk("%s: IOMMU Error, type[%s]\n", + pbm->name, type_string); /* Put the IOMMU into diagnostic mode and probe * it's TLB for entries with error status. @@ -497,14 +492,14 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, type_string = "ECC Error"; break; }; - printk("PSYCHO%d: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n", - p->index, i, type_string, + printk("%s: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n", + pbm->name, i, type_string, ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); - printk("PSYCHO%d: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", - p->index, i, + printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", + pbm->name, i, ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); @@ -555,22 +550,22 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) psycho_write(afsr_reg, error_bits); /* Log the error. */ - printk("PSYCHO%d: Uncorrectable Error, primary error type[%s]\n", - p->index, + printk("%s: Uncorrectable Error, primary error type[%s]\n", + pbm->name, (((error_bits & PSYCHO_UEAFSR_PPIO) ? "PIO" : ((error_bits & PSYCHO_UEAFSR_PDRD) ? "DMA Read" : ((error_bits & PSYCHO_UEAFSR_PDWR) ? "DMA Write" : "???"))))); - printk("PSYCHO%d: bytemask[%04lx] dword_offset[%lx] UPA_MID[%02lx] was_block(%d)\n", - p->index, + printk("%s: bytemask[%04lx] dword_offset[%lx] UPA_MID[%02lx] was_block(%d)\n", + pbm->name, (afsr & PSYCHO_UEAFSR_BMSK) >> 32UL, (afsr & PSYCHO_UEAFSR_DOFF) >> 29UL, (afsr & PSYCHO_UEAFSR_MID) >> 24UL, ((afsr & PSYCHO_UEAFSR_BLK) ? 1 : 0)); - printk("PSYCHO%d: UE AFAR [%016lx]\n", p->index, afar); - printk("PSYCHO%d: UE Secondary errors [", p->index); + printk("%s: UE AFAR [%016lx]\n", pbm->name, afar); + printk("%s: UE Secondary errors [", pbm->name); reported = 0; if (afsr & PSYCHO_UEAFSR_SPIO) { reported++; @@ -615,7 +610,6 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) static irqreturn_t psycho_ce_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 + PSYCHO_CE_AFSR; unsigned long afar_reg = pbm->controller_regs + PSYCHO_CE_AFAR; unsigned long afsr, afar, error_bits; @@ -634,8 +628,8 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) psycho_write(afsr_reg, error_bits); /* Log the error. */ - printk("PSYCHO%d: Correctable Error, primary error type[%s]\n", - p->index, + printk("%s: Correctable Error, primary error type[%s]\n", + pbm->name, (((error_bits & PSYCHO_CEAFSR_PPIO) ? "PIO" : ((error_bits & PSYCHO_CEAFSR_PDRD) ? @@ -646,16 +640,16 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) /* XXX Use syndrome and afar to print out module string just like * XXX UDB CE trap handler does... -DaveM */ - printk("PSYCHO%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " + printk("%s: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " "UPA_MID[%02lx] was_block(%d)\n", - p->index, + pbm->name, (afsr & PSYCHO_CEAFSR_ESYND) >> 48UL, (afsr & PSYCHO_CEAFSR_BMSK) >> 32UL, (afsr & PSYCHO_CEAFSR_DOFF) >> 29UL, (afsr & PSYCHO_CEAFSR_MID) >> 24UL, ((afsr & PSYCHO_CEAFSR_BLK) ? 1 : 0)); - printk("PSYCHO%d: CE AFAR [%016lx]\n", p->index, afar); - printk("PSYCHO%d: CE Secondary errors [", p->index); + printk("%s: CE AFAR [%016lx]\n", pbm->name, afar); + printk("%s: CE Secondary errors [", pbm->name); reported = 0; if (afsr & PSYCHO_CEAFSR_SPIO) { reported++; @@ -770,8 +764,8 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) psycho_write(afsr_reg, error_bits); /* Log the error. */ - printk("PSYCHO%d(PBM%c): PCI Error, primary error type[%s]\n", - p->index, (is_pbm_a ? 'A' : 'B'), + printk("%s: PCI Error, primary error type[%s]\n", + pbm->name, (((error_bits & PSYCHO_PCIAFSR_PMA) ? "Master Abort" : ((error_bits & PSYCHO_PCIAFSR_PTA) ? @@ -780,15 +774,13 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) "Excessive Retries" : ((error_bits & PSYCHO_PCIAFSR_PPERR) ? "Parity Error" : "???")))))); - printk("PSYCHO%d(PBM%c): bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", - p->index, (is_pbm_a ? 'A' : 'B'), + printk("%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", + pbm->name, (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); - printk("PSYCHO%d(PBM%c): PCI AFAR [%016lx]\n", - p->index, (is_pbm_a ? 'A' : 'B'), afar); - printk("PSYCHO%d(PBM%c): PCI Secondary errors [", - p->index, (is_pbm_a ? 'A' : 'B')); + printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); + printk("%s: PCI Secondary errors [", pbm->name); reported = 0; if (afsr & PSYCHO_PCIAFSR_SMA) { reported++; @@ -821,10 +813,10 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) */ if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); - pci_scan_for_target_abort(pbm->parent, pbm, pbm->pci_bus); + pci_scan_for_target_abort(pbm, pbm->pci_bus); } if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) - pci_scan_for_master_abort(pbm->parent, pbm, pbm->pci_bus); + pci_scan_for_master_abort(pbm, pbm->pci_bus); /* For excessive retries, PSYCHO/PBM will abort the device * and there is no way to specifically check for excessive @@ -834,7 +826,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(pbm->parent, pbm, pbm->pci_bus); + pci_scan_for_parity_error(pbm, pbm->pci_bus); return IRQ_HANDLED; } @@ -1089,6 +1081,8 @@ static void psycho_pbm_init(struct pci_controller_info *p, pbm->scan_bus = psycho_scan_bus; pbm->pci_ops = &psycho_ops; + pbm->index = pci_num_pbms++; + pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; pbm->chip_version = 0; prop = of_find_property(dp, "version#", NULL); @@ -1155,7 +1149,6 @@ void psycho_init(struct device_node *dp, char *model_name) p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; - p->index = pci_num_controllers++; prop = of_find_property(dp, "reg", NULL); pr_regs = prop->value; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index ec265a30af43..422485bc67f0 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -494,11 +494,11 @@ static struct pci_ops sabre_ops = { }; /* SABRE error handling support. */ -static void sabre_check_iommu_error(struct pci_controller_info *p, +static void sabre_check_iommu_error(struct pci_pbm_info *pbm, unsigned long afsr, unsigned long afar) { - struct iommu *iommu = p->pbm_A.iommu; + struct iommu *iommu = pbm->iommu; unsigned long iommu_tag[16]; unsigned long iommu_data[16]; unsigned long flags; @@ -526,8 +526,8 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, type_string = "Unknown"; break; }; - printk("SABRE%d: IOMMU Error, type[%s]\n", - p->index, type_string); + printk("%s: IOMMU Error, type[%s]\n", + pbm->name, type_string); /* Enter diagnostic mode and probe for error'd * entries in the IOTLB. @@ -536,7 +536,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, sabre_write(iommu->iommu_control, (control | SABRE_IOMMUCTRL_DENAB)); for (i = 0; i < 16; i++) { - unsigned long base = p->pbm_A.controller_regs; + unsigned long base = pbm->controller_regs; iommu_tag[i] = sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL)); @@ -566,13 +566,13 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, type_string = "Unknown"; break; }; - printk("SABRE%d: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", - p->index, i, tag, type_string, + printk("%s: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", + pbm->name, i, tag, type_string, ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT)); - printk("SABRE%d: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", - p->index, i, data, + printk("%s: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", + pbm->name, i, data, ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), @@ -584,9 +584,9 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, static irqreturn_t sabre_ue_intr(int irq, void *dev_id) { - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_UE_AFSR; - unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR; + struct pci_pbm_info *pbm = dev_id; + unsigned long afsr_reg = pbm->controller_regs + SABRE_UE_AFSR; + unsigned long afar_reg = pbm->controller_regs + SABRE_UECE_AFAR; unsigned long afsr, afar, error_bits; int reported; @@ -604,21 +604,21 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) sabre_write(afsr_reg, error_bits); /* Log the error. */ - printk("SABRE%d: Uncorrectable Error, primary error type[%s%s]\n", - p->index, + printk("%s: Uncorrectable Error, primary error type[%s%s]\n", + pbm->name, ((error_bits & SABRE_UEAFSR_PDRD) ? "DMA Read" : ((error_bits & SABRE_UEAFSR_PDWR) ? "DMA Write" : "???")), ((error_bits & SABRE_UEAFSR_PDTE) ? ":Translation Error" : "")); - printk("SABRE%d: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n", - p->index, + printk("%s: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n", + pbm->name, (afsr & SABRE_UEAFSR_BMSK) >> 32UL, (afsr & SABRE_UEAFSR_OFF) >> 29UL, ((afsr & SABRE_UEAFSR_BLK) ? 1 : 0)); - printk("SABRE%d: UE AFAR [%016lx]\n", p->index, afar); - printk("SABRE%d: UE Secondary errors [", p->index); + printk("%s: UE AFAR [%016lx]\n", pbm->name, afar); + printk("%s: UE Secondary errors [", pbm->name); reported = 0; if (afsr & SABRE_UEAFSR_SDRD) { reported++; @@ -637,16 +637,16 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) printk("]\n"); /* Interrogate IOMMU for error status. */ - sabre_check_iommu_error(p, afsr, afar); + sabre_check_iommu_error(pbm, afsr, afar); return IRQ_HANDLED; } static irqreturn_t sabre_ce_intr(int irq, void *dev_id) { - struct pci_controller_info *p = dev_id; - unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_CE_AFSR; - unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR; + struct pci_pbm_info *pbm = dev_id; + unsigned long afsr_reg = pbm->controller_regs + SABRE_CE_AFSR; + unsigned long afar_reg = pbm->controller_regs + SABRE_UECE_AFAR; unsigned long afsr, afar, error_bits; int reported; @@ -663,8 +663,8 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) sabre_write(afsr_reg, error_bits); /* Log the error. */ - printk("SABRE%d: Correctable Error, primary error type[%s]\n", - p->index, + printk("%s: Correctable Error, primary error type[%s]\n", + pbm->name, ((error_bits & SABRE_CEAFSR_PDRD) ? "DMA Read" : ((error_bits & SABRE_CEAFSR_PDWR) ? @@ -673,15 +673,15 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) /* XXX Use syndrome and afar to print out module string just like * XXX UDB CE trap handler does... -DaveM */ - printk("SABRE%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " + printk("%s: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " "was_block(%d)\n", - p->index, + pbm->name, (afsr & SABRE_CEAFSR_ESYND) >> 48UL, (afsr & SABRE_CEAFSR_BMSK) >> 32UL, (afsr & SABRE_CEAFSR_OFF) >> 29UL, ((afsr & SABRE_CEAFSR_BLK) ? 1 : 0)); - printk("SABRE%d: CE AFAR [%016lx]\n", p->index, afar); - printk("SABRE%d: CE Secondary errors [", p->index); + printk("%s: CE AFAR [%016lx]\n", pbm->name, afar); + printk("%s: CE Secondary errors [", pbm->name); reported = 0; if (afsr & SABRE_CEAFSR_SDRD) { reported++; @@ -698,13 +698,13 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) +static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm) { unsigned long csr_reg, csr, csr_error_bits; irqreturn_t ret = IRQ_NONE; u16 stat; - csr_reg = p->pbm_A.controller_regs + SABRE_PCICTRL; + csr_reg = pbm->controller_regs + SABRE_PCICTRL; csr = sabre_read(csr_reg); csr_error_bits = csr & SABRE_PCICTRL_SERR; @@ -714,8 +714,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) /* Log 'em. */ if (csr_error_bits & SABRE_PCICTRL_SERR) - printk("SABRE%d: PCI SERR signal asserted.\n", - p->index); + printk("%s: PCI SERR signal asserted.\n", + pbm->name); ret = IRQ_HANDLED; } pci_bus_read_config_word(sabre_root_bus, 0, @@ -725,8 +725,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_SIG_SYSTEM_ERROR)) { - printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n", - p->index, stat); + printk("%s: PCI bus error, PCI_STATUS[%04x]\n", + pbm->name, stat); pci_bus_write_config_word(sabre_root_bus, 0, PCI_STATUS, 0xffff); ret = IRQ_HANDLED; @@ -736,13 +736,13 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) { - struct pci_controller_info *p = dev_id; + struct pci_pbm_info *pbm = dev_id; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; int reported; - afsr_reg = p->pbm_A.controller_regs + SABRE_PIOAFSR; - afar_reg = p->pbm_A.controller_regs + SABRE_PIOAFAR; + afsr_reg = pbm->controller_regs + SABRE_PIOAFSR; + afar_reg = pbm->controller_regs + SABRE_PIOAFAR; /* Latch error status. */ afar = sabre_read(afar_reg); @@ -755,12 +755,12 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA | SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR); if (!error_bits) - return sabre_pcierr_intr_other(p); + return sabre_pcierr_intr_other(pbm); sabre_write(afsr_reg, error_bits); /* Log the error. */ - printk("SABRE%d: PCI Error, primary error type[%s]\n", - p->index, + printk("%s: PCI Error, primary error type[%s]\n", + pbm->name, (((error_bits & SABRE_PIOAFSR_PMA) ? "Master Abort" : ((error_bits & SABRE_PIOAFSR_PTA) ? @@ -769,12 +769,12 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) "Excessive Retries" : ((error_bits & SABRE_PIOAFSR_PPERR) ? "Parity Error" : "???")))))); - printk("SABRE%d: bytemask[%04lx] was_block(%d)\n", - p->index, + printk("%s: bytemask[%04lx] was_block(%d)\n", + pbm->name, (afsr & SABRE_PIOAFSR_BMSK) >> 32UL, (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0); - printk("SABRE%d: PCI AFAR [%016lx]\n", p->index, afar); - printk("SABRE%d: PCI Secondary errors [", p->index); + printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); + printk("%s: PCI Secondary errors [", pbm->name); reported = 0; if (afsr & SABRE_PIOAFSR_SMA) { reported++; @@ -806,11 +806,11 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) * a bug in the IOMMU support code or a PCI device driver. */ if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { - sabre_check_iommu_error(p, afsr, afar); - pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus); + sabre_check_iommu_error(pbm, afsr, afar); + pci_scan_for_target_abort(pbm, pbm->pci_bus); } if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) - pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus); + pci_scan_for_master_abort(pbm, pbm->pci_bus); /* For excessive retries, SABRE/PBM will abort the device * and there is no way to specifically check for excessive @@ -820,14 +820,13 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) */ if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) - pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus); + pci_scan_for_parity_error(pbm, pbm->pci_bus); return IRQ_HANDLED; } static void sabre_register_error_handlers(struct pci_pbm_info *pbm) { - 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,15 +857,15 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); - request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", p); + request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); 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, 0, "SABRE_CE", p); + request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); request_irq(op->irqs[0], sabre_pcierr_intr, 0, - "SABRE_PCIERR", p); + "SABRE_PCIERR", pbm); tmp = sabre_read(base + SABRE_PCICTRL); tmp |= SABRE_PCICTRL_ERREN; @@ -1006,6 +1005,8 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp pbm->scan_bus = sabre_scan_bus; pbm->pci_ops = &sabre_ops; + pbm->index = pci_num_pbms++; + pbm->chip_type = PBM_CHIP_TYPE_SABRE; pbm->parent = p; pbm->prom_node = dp; @@ -1062,7 +1063,6 @@ void sabre_init(struct device_node *dp, char *model_name) pci_pbm_root = &p->pbm_A; p->pbm_A.portid = upa_portid; - p->index = pci_num_controllers++; /* * Map in SABRE register set and report the presence of this SABRE. diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index a0da7f2c344e..72743acecbc0 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -531,28 +531,28 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) schizo_write(afsr_reg, error_bits); /* Log the error. */ - printk("PCI%d: Uncorrectable Error, primary error type[%s]\n", - p->index, + printk("%s: Uncorrectable Error, primary error type[%s]\n", + pbm->name, (((error_bits & SCHIZO_UEAFSR_PPIO) ? "PIO" : ((error_bits & SCHIZO_UEAFSR_PDRD) ? "DMA Read" : ((error_bits & SCHIZO_UEAFSR_PDWR) ? "DMA Write" : "???"))))); - printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", - p->index, + printk("%s: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", + pbm->name, (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL, (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL, (afsr & SCHIZO_UEAFSR_AID) >> 24UL); - printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", - p->index, + printk("%s: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", + pbm->name, (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0, (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0, (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL, (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL, (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL); - printk("PCI%d: UE AFAR [%016lx]\n", p->index, afar); - printk("PCI%d: UE Secondary errors [", p->index); + printk("%s: UE AFAR [%016lx]\n", pbm->name, afar); + printk("%s: UE Secondary errors [", pbm->name); reported = 0; if (afsr & SCHIZO_UEAFSR_SPIO) { reported++; @@ -593,7 +593,6 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) static irqreturn_t schizo_ce_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_CE_AFSR; unsigned long afar_reg = pbm->controller_regs + SCHIZO_CE_AFAR; unsigned long afsr, afar, error_bits; @@ -620,8 +619,8 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) schizo_write(afsr_reg, error_bits); /* Log the error. */ - printk("PCI%d: Correctable Error, primary error type[%s]\n", - p->index, + printk("%s: Correctable Error, primary error type[%s]\n", + pbm->name, (((error_bits & SCHIZO_CEAFSR_PPIO) ? "PIO" : ((error_bits & SCHIZO_CEAFSR_PDRD) ? @@ -632,20 +631,20 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) /* XXX Use syndrome and afar to print out module string just like * XXX UDB CE trap handler does... -DaveM */ - printk("PCI%d: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", - p->index, + printk("%s: bytemask[%04lx] qword_offset[%lx] SAFARI_AID[%02lx]\n", + pbm->name, (afsr & SCHIZO_UEAFSR_BMSK) >> 32UL, (afsr & SCHIZO_UEAFSR_QOFF) >> 30UL, (afsr & SCHIZO_UEAFSR_AID) >> 24UL); - printk("PCI%d: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", - p->index, + printk("%s: partial[%d] owned_in[%d] mtag[%lx] mtag_synd[%lx] ecc_sync[%lx]\n", + pbm->name, (afsr & SCHIZO_UEAFSR_PARTIAL) ? 1 : 0, (afsr & SCHIZO_UEAFSR_OWNEDIN) ? 1 : 0, (afsr & SCHIZO_UEAFSR_MTAG) >> 13UL, (afsr & SCHIZO_UEAFSR_MTAGSYND) >> 16UL, (afsr & SCHIZO_UEAFSR_ECCSYND) >> 0UL); - printk("PCI%d: CE AFAR [%016lx]\n", p->index, afar); - printk("PCI%d: CE Secondary errors [", p->index); + printk("%s: CE AFAR [%016lx]\n", pbm->name, afar); + printk("%s: CE Secondary errors [", pbm->name); reported = 0; if (afsr & SCHIZO_CEAFSR_SPIO) { reported++; @@ -864,10 +863,10 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) */ if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { schizo_check_iommu_error(p, PCI_ERR); - pci_scan_for_target_abort(p, pbm, pbm->pci_bus); + pci_scan_for_target_abort(pbm, pbm->pci_bus); } if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) - pci_scan_for_master_abort(p, pbm, pbm->pci_bus); + pci_scan_for_master_abort(pbm, pbm->pci_bus); /* For excessive retries, PSYCHO/PBM will abort the device * and there is no way to specifically check for excessive @@ -877,7 +876,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) */ if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR)) - pci_scan_for_parity_error(p, pbm, pbm->pci_bus); + pci_scan_for_parity_error(pbm, pbm->pci_bus); return IRQ_HANDLED; } @@ -932,14 +931,14 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) errlog & ~(SAFARI_ERRLOG_ERROUT)); if (!(errlog & BUS_ERROR_UNMAP)) { - printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", - p->index, errlog); + printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", + pbm->name, errlog); return IRQ_HANDLED; } - printk("PCI%d: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", - p->index); + printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", + pbm->name); schizo_check_iommu_error(p, SAFARI_ERR); return IRQ_HANDLED; @@ -1464,6 +1463,8 @@ static void schizo_pbm_init(struct pci_controller_info *p, pbm->scan_bus = schizo_scan_bus; pbm->pci_ops = &schizo_ops; + pbm->index = pci_num_pbms++; + pbm->portid = portid; pbm->parent = p; pbm->prom_node = dp; @@ -1536,8 +1537,6 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ p->pbm_B.iommu = iommu; - p->index = pci_num_controllers++; - /* Like PSYCHO we have a 2GB aligned area for memory space. */ pci_memspace_mask = 0x7fffffffUL; diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 7ebc04f9a880..ce46b0471693 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -1241,6 +1241,8 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pbm->scan_bus = pci_sun4v_scan_bus; pbm->pci_ops = &pci_sun4v_ops; + pbm->index = pci_num_pbms++; + pbm->parent = p; pbm->prom_node = dp; @@ -1304,8 +1306,6 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) p->pbm_B.iommu = iommu; - p->index = pci_num_controllers++; - /* Like PSYCHO and SCHIZO we have a 2GB aligned area * for memory space. */ diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 1d5dcfe133a2..d99e0468c7e4 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -40,6 +40,7 @@ struct pci_controller_info; struct pci_pbm_info { struct pci_pbm_info *next; + int index; /* PCI controller we sit under. */ struct pci_controller_info *parent; @@ -123,11 +124,6 @@ struct pci_pbm_info { }; struct pci_controller_info { - /* Each controller gets a unique index, used mostly for - * error logging purposes. - */ - int index; - /* The PCI bus modules controlled by us. */ struct pci_pbm_info pbm_A; struct pci_pbm_info pbm_B; From 28113a9941c8cb6ca90ab4a66876db84342a084b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 May 2007 00:19:02 -0700 Subject: [PATCH 08/14] [SPARC64]: Removal of trivial pci_controller_info uses. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 2 - arch/sparc64/kernel/pci_psycho.c | 66 +++++++++++++++----------------- arch/sparc64/kernel/pci_sabre.c | 57 ++++++++++++++------------- 3 files changed, 58 insertions(+), 67 deletions(-) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index b8a48db3d82d..ca290d6de64d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -921,10 +921,8 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc enum pci_mmap_state mmap_state) { struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - struct pci_controller_info *p; unsigned long space_size, user_offset, user_size; - p = pbm->parent; if (mmap_state == pci_mmap_io) { space_size = (pbm->io_space.end - pbm->io_space.start) + 1; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index b6f073ed31d4..8ef808348993 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -98,13 +98,8 @@ static int psycho_out_of_range(struct pci_pbm_info *pbm, unsigned char bus, unsigned char devfn) { - return ((pbm->parent == 0) || - ((pbm == &pbm->parent->pbm_B) && - (bus == pbm->pci_first_busno) && - PCI_SLOT(devfn) > 8) || - ((pbm == &pbm->parent->pbm_A) && - (bus == pbm->pci_first_busno) && - PCI_SLOT(devfn) > 8)); + return ((bus == pbm->pci_first_busno) && + PCI_SLOT(devfn) > 8); } /* PSYCHO PCI configuration space accessors. */ @@ -918,33 +913,33 @@ static void psycho_scan_bus(struct pci_pbm_info *pbm) psycho_register_error_handlers(pbm); } -static void psycho_iommu_init(struct pci_controller_info *p) +static void psycho_iommu_init(struct pci_pbm_info *pbm) { - struct iommu *iommu = p->pbm_A.iommu; + struct iommu *iommu = pbm->iommu; unsigned long i; u64 control; /* Register addresses. */ - iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; - iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE; - iommu->iommu_flush = p->pbm_A.controller_regs + PSYCHO_IOMMU_FLUSH; + iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; + iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; + iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; /* PSYCHO's IOMMU lacks ctx flushing. */ iommu->iommu_ctxflush = 0; /* We use the main control register of PSYCHO as the write * completion register. */ - iommu->write_complete_reg = p->pbm_A.controller_regs + PSYCHO_CONTROL; + iommu->write_complete_reg = pbm->controller_regs + PSYCHO_CONTROL; /* * Invalidate TLB Entries. */ - control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL); + control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); control |= PSYCHO_IOMMU_CTRL_DENAB; - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control); + psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); for(i = 0; i < 16; i++) { - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); + psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); + psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); } /* Leave diag mode enabled for full-flushing done @@ -952,17 +947,17 @@ static void psycho_iommu_init(struct pci_controller_info *p) */ pci_iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff); - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, + psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(iommu->page_table)); - control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL); + control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB); - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control); + psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); /* If necessary, hook us up for starfire IRQ translations. */ if (this_is_starfire) - starfire_hookup(p->pbm_A.portid); + starfire_hookup(pbm->portid); } #define PSYCHO_IRQ_RETRY 0x1a00UL @@ -977,36 +972,35 @@ static void psycho_iommu_init(struct pci_controller_info *p) #define PSYCHO_PCIDIAG_IPAPAR 0x0000000000000002UL /* Invert PIO address parity */ #define PSYCHO_PCIDIAG_LPBACK 0x0000000000000001UL /* Enable loopback mode */ -static void psycho_controller_hwinit(struct pci_controller_info *p) +static void psycho_controller_hwinit(struct pci_pbm_info *pbm) { u64 tmp; - psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 5); + psycho_write(pbm->controller_regs + PSYCHO_IRQ_RETRY, 5); /* Enable arbiter for all PCI slots. */ - tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL); + tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_CTRL); tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL, tmp); + psycho_write(pbm->controller_regs + PSYCHO_PCIA_CTRL, tmp); - tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL); + tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_CTRL); tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL, tmp); + psycho_write(pbm->controller_regs + PSYCHO_PCIB_CTRL, tmp); /* Disable DMA write / PIO read synchronization on * both PCI bus segments. * [ U2P Erratum 1243770, STP2223BGA data sheet ] */ - tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG); + tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_DIAG); tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG, tmp); + psycho_write(pbm->controller_regs + PSYCHO_PCIA_DIAG, tmp); - tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG); + tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_DIAG); tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp); + psycho_write(pbm->controller_regs + PSYCHO_PCIB_DIAG, tmp); } -static void psycho_pbm_strbuf_init(struct pci_controller_info *p, - struct pci_pbm_info *pbm, +static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, int is_pbm_a) { unsigned long base = pbm->controller_regs; @@ -1105,7 +1099,7 @@ static void psycho_pbm_init(struct pci_controller_info *p, pci_get_pbm_props(pbm); - psycho_pbm_strbuf_init(p, pbm, is_pbm_a); + psycho_pbm_strbuf_init(pbm, is_pbm_a); } #define PSYCHO_CONFIGSPACE 0x001000000UL @@ -1165,9 +1159,9 @@ void psycho_init(struct device_node *dp, char *model_name) */ pci_memspace_mask = 0x7fffffffUL; - psycho_controller_hwinit(p); + psycho_controller_hwinit(&p->pbm_A); - psycho_iommu_init(p); + psycho_iommu_init(&p->pbm_A); is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); psycho_pbm_init(p, dp, is_pbm_a); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 422485bc67f0..733ab366a3d4 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -942,30 +942,30 @@ static void sabre_scan_bus(struct pci_pbm_info *pbm) sabre_register_error_handlers(pbm); } -static void sabre_iommu_init(struct pci_controller_info *p, +static void sabre_iommu_init(struct pci_pbm_info *pbm, int tsbsize, unsigned long dvma_offset, u32 dma_mask) { - struct iommu *iommu = p->pbm_A.iommu; + struct iommu *iommu = pbm->iommu; unsigned long i; u64 control; /* Register addresses. */ - iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; - iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE; - iommu->iommu_flush = p->pbm_A.controller_regs + SABRE_IOMMU_FLUSH; - iommu->write_complete_reg = p->pbm_A.controller_regs + SABRE_WRSYNC; + iommu->iommu_control = pbm->controller_regs + SABRE_IOMMU_CONTROL; + iommu->iommu_tsbbase = pbm->controller_regs + SABRE_IOMMU_TSBBASE; + iommu->iommu_flush = pbm->controller_regs + SABRE_IOMMU_FLUSH; + iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC; /* Sabre's IOMMU lacks ctx flushing. */ iommu->iommu_ctxflush = 0; /* Invalidate TLB Entries. */ - control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL); + control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); control |= SABRE_IOMMUCTRL_DENAB; - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); + sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); for(i = 0; i < 16; i++) { - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); + sabre_write(pbm->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); + sabre_write(pbm->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); } /* Leave diag mode enabled for full-flushing done @@ -973,10 +973,10 @@ static void sabre_iommu_init(struct pci_controller_info *p, */ pci_iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask); - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, + sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE, __pa(iommu->page_table)); - control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL); + control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); control |= SABRE_IOMMUCTRL_ENAB; switch(tsbsize) { @@ -991,14 +991,11 @@ static void sabre_iommu_init(struct pci_controller_info *p, prom_halt(); break; } - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); + sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); } -static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp) +static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *pbm, struct device_node *dp) { - struct pci_pbm_info *pbm; - - pbm = &p->pbm_A; pbm->name = dp->full_name; printk("%s: SABRE PCI Bus Module\n", pbm->name); @@ -1019,6 +1016,7 @@ void sabre_init(struct device_node *dp, char *model_name) { const struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; + struct pci_pbm_info *pbm; struct iommu *iommu; int tsbsize; const u32 *vdma; @@ -1055,14 +1053,15 @@ void sabre_init(struct device_node *dp, char *model_name) prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n"); prom_halt(); } - p->pbm_A.iommu = iommu; + pbm = &p->pbm_A; + pbm->iommu = iommu; upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); - p->pbm_A.next = pci_pbm_root; - pci_pbm_root = &p->pbm_A; + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; - p->pbm_A.portid = upa_portid; + pbm->portid = upa_portid; /* * Map in SABRE register set and report the presence of this SABRE. @@ -1073,26 +1072,26 @@ void sabre_init(struct device_node *dp, char *model_name) /* * First REG in property is base of entire SABRE register space. */ - p->pbm_A.controller_regs = pr_regs[0].phys_addr; + pbm->controller_regs = pr_regs[0].phys_addr; /* Clear interrupts */ /* PCI first */ for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) - sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL); + sabre_write(pbm->controller_regs + clear_irq, 0x0UL); /* Then OBIO */ for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) - sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL); + sabre_write(pbm->controller_regs + clear_irq, 0x0UL); /* Error interrupts are enabled later after the bus scan. */ - sabre_write(p->pbm_A.controller_regs + SABRE_PCICTRL, + sabre_write(pbm->controller_regs + SABRE_PCICTRL, (SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); /* Now map in PCI config space for entire SABRE. */ - p->pbm_A.config_space = - (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); + pbm->config_space = + (pbm->controller_regs + SABRE_CONFIGSPACE); vdma = of_get_property(dp, "virtual-dma", NULL); @@ -1116,10 +1115,10 @@ void sabre_init(struct device_node *dp, char *model_name) prom_halt(); } - sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); + sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask); /* * Look for APB underneath. */ - sabre_pbm_init(p, dp); + sabre_pbm_init(p, pbm, dp); } From 15576bc8adb33d58867942385ae849cc48379610 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 May 2007 00:36:49 -0700 Subject: [PATCH 09/14] [QLA2XXX]: Fix build on sparc. We now use pci_device_to_OF_node() to get properties and of_get_property() returns const pointers. Signed-off-by: David S. Miller --- drivers/scsi/qla2xxx/qla_init.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3e296ab845b6..089fc7940d8b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -13,7 +13,6 @@ #ifdef CONFIG_SPARC #include -#include #endif /* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */ @@ -1400,9 +1399,8 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv) { #ifdef CONFIG_SPARC struct pci_dev *pdev = ha->pdev; - struct pcidev_cookie *pcp = pdev->sysdata; - struct device_node *dp = pcp->prom_node; - u8 *val; + struct device_node *dp = pci_device_to_OF_node(pdev); + const u8 *val; int len; val = of_get_property(dp, "port-wwn", &len); @@ -3373,9 +3371,8 @@ static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *n { #ifdef CONFIG_SPARC struct pci_dev *pdev = ha->pdev; - struct pcidev_cookie *pcp = pdev->sysdata; - struct device_node *dp = pcp->prom_node; - u8 *val; + struct device_node *dp = pci_device_to_OF_node(pdev); + const u8 *val; int len; val = of_get_property(dp, "port-wwn", &len); From 63c3f460cb47c2e06f1726e18534d0e1fe8652a7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 May 2007 00:37:23 -0700 Subject: [PATCH 10/14] [ATYFB]: Fix sparc includes. No need to use asm/pbm.h here. Signed-off-by: David S. Miller --- drivers/video/aty/atyfb_base.c | 3 ++- drivers/video/aty/mach64_cursor.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index ea67dd902d4e..8d3455da663a 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -80,8 +80,9 @@ #include "../macmodes.h" #endif #ifdef __sparc__ -#include #include +#include +#include #endif #ifdef CONFIG_ADB_PMU diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c index 2a7f381c330f..fe2c6ad01a8d 100644 --- a/drivers/video/aty/mach64_cursor.c +++ b/drivers/video/aty/mach64_cursor.c @@ -11,7 +11,6 @@ #include #ifdef __sparc__ -#include #include #endif From c57c2ffb153a99769a15a2ff1729371ddee5601a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 May 2007 00:43:56 -0700 Subject: [PATCH 11/14] [SPARC64]: Kill asm-sparc64/pbm.h Everything it contains can be hidden in pci_impl.h Signed-off-by: David S. Miller --- arch/sparc64/kernel/ebus.c | 3 +- arch/sparc64/kernel/pci.c | 2 +- arch/sparc64/kernel/pci_common.c | 2 +- arch/sparc64/kernel/pci_fire.c | 1 - arch/sparc64/kernel/pci_impl.h | 113 ++++++++++++++++++++++++++ arch/sparc64/kernel/pci_iommu.c | 4 +- arch/sparc64/kernel/pci_psycho.c | 2 +- arch/sparc64/kernel/pci_sabre.c | 2 +- arch/sparc64/kernel/pci_schizo.c | 3 +- arch/sparc64/kernel/pci_sun4v.c | 1 - include/asm-sparc64/pbm.h | 132 ------------------------------- 11 files changed, 124 insertions(+), 141 deletions(-) delete mode 100644 include/asm-sparc64/pbm.h diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 0ace17bafba4..ad55a9bb50dd 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -13,16 +13,17 @@ #include #include #include +#include #include #include -#include #include #include #include #include #include #include +#include /* EBUS dma library. */ diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index ca290d6de64d..d85e1ed7c3e4 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -14,12 +14,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 8dcc7cc4ec71..76faaa8135dd 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -9,9 +9,9 @@ #include #include -#include #include #include +#include #include "pci_impl.h" diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 5df31300b4d9..2e0eb4ee8f71 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -7,7 +7,6 @@ #include #include -#include #include #include diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 61505c19fd1e..8e38023868aa 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -8,8 +8,119 @@ #include #include +#include +#include #include #include +#include + +/* The abstraction used here is that there are PCI controllers, + * each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules + * underneath. Each PCI bus module uses an IOMMU (shared by both + * PBMs of a controller, or per-PBM), and if a streaming buffer + * is present, each PCI bus module has it's own. (ie. the IOMMU + * might be shared between PBMs, the STC is never shared) + * Furthermore, each PCI bus module controls it's own autonomous + * PCI bus. + */ + +#define PCI_STC_FLUSHFLAG_INIT(STC) \ + (*((STC)->strbuf_flushflag) = 0UL) +#define PCI_STC_FLUSHFLAG_SET(STC) \ + (*((STC)->strbuf_flushflag) != 0UL) + +struct pci_controller_info; + +struct pci_pbm_info { + struct pci_pbm_info *next; + int index; + + /* PCI controller we sit under. */ + struct pci_controller_info *parent; + + /* Physical address base of controller registers. */ + unsigned long controller_regs; + + /* Physical address base of PBM registers. */ + unsigned long pbm_regs; + + /* Physical address of DMA sync register, if any. */ + unsigned long sync_reg; + + /* Opaque 32-bit system bus Port ID. */ + u32 portid; + + /* Opaque 32-bit handle used for hypervisor calls. */ + u32 devhandle; + + /* Chipset version information. */ + int chip_type; +#define PBM_CHIP_TYPE_SABRE 1 +#define PBM_CHIP_TYPE_PSYCHO 2 +#define PBM_CHIP_TYPE_SCHIZO 3 +#define PBM_CHIP_TYPE_SCHIZO_PLUS 4 +#define PBM_CHIP_TYPE_TOMATILLO 5 + int chip_version; + int chip_revision; + + /* Name used for top-level resources. */ + char *name; + + /* OBP specific information. */ + struct device_node *prom_node; + u64 ino_bitmap; + + /* PBM I/O and Memory space resources. */ + struct resource io_space; + struct resource mem_space; + + /* Base of PCI Config space, can be per-PBM or shared. */ + unsigned long config_space; + + /* State of 66MHz capabilities on this PBM. */ + int is_66mhz_capable; + int all_devs_66mhz; + +#ifdef CONFIG_PCI_MSI + /* MSI info. */ + u32 msiq_num; + u32 msiq_ent_count; + u32 msiq_first; + u32 msiq_first_devino; + u32 msi_num; + u32 msi_first; + u32 msi_data_mask; + u32 msix_data_width; + u64 msi32_start; + u64 msi64_start; + u32 msi32_len; + u32 msi64_len; + void *msi_queues; + unsigned long *msi_bitmap; + int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, + struct msi_desc *entry); + void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); +#endif /* !(CONFIG_PCI_MSI) */ + + /* This PBM's streaming buffer. */ + struct strbuf stc; + + /* IOMMU state, potentially shared by both PBM segments. */ + struct iommu *iommu; + + /* Now things for the actual PCI bus probes. */ + unsigned int pci_first_busno; + unsigned int pci_last_busno; + struct pci_bus *pci_bus; + void (*scan_bus)(struct pci_pbm_info *); + struct pci_ops *pci_ops; +}; + +struct pci_controller_info { + /* The PCI bus modules controlled by us. */ + struct pci_pbm_info pbm_A; + struct pci_pbm_info pbm_B; +}; extern struct pci_pbm_info *pci_pbm_root; extern unsigned long pci_memspace_mask; @@ -17,6 +128,8 @@ extern unsigned long pci_memspace_mask; extern int pci_num_pbms; /* PCI bus scanning and fixup support. */ +extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize, + u32 dma_offset, u32 dma_addr_mask); extern void pci_get_pbm_props(struct pci_pbm_info *pbm); extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 9e405cbbcb0d..dfd6f9f4790b 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -8,10 +8,12 @@ #include #include #include +#include -#include +#include #include "iommu_common.h" +#include "pci_impl.h" #define PCI_STC_CTXMATCH_ADDR(STC, CTX) \ ((STC)->strbuf_ctxmatch_base + ((CTX) << 3)) diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 8ef808348993..401e5dfe9bd5 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -12,12 +12,12 @@ #include #include -#include #include #include #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 733ab366a3d4..863308c8955d 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -13,12 +13,12 @@ #include #include -#include #include #include #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 72743acecbc0..312f3e4f2ed4 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -10,12 +10,13 @@ #include #include -#include #include #include #include #include #include +#include +#include #include "pci_impl.h" #include "iommu_common.h" diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index ce46b0471693..0c76a8891a96 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h deleted file mode 100644 index d99e0468c7e4..000000000000 --- a/include/asm-sparc64/pbm.h +++ /dev/null @@ -1,132 +0,0 @@ -/* pbm.h: UltraSparc PCI controller software state. - * - * Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net) - */ - -#ifndef __SPARC64_PBM_H -#define __SPARC64_PBM_H - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* The abstraction used here is that there are PCI controllers, - * each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules - * underneath. Each PCI bus module uses an IOMMU (shared by both - * PBMs of a controller, or per-PBM), and if a streaming buffer - * is present, each PCI bus module has it's own. (ie. the IOMMU - * might be shared between PBMs, the STC is never shared) - * Furthermore, each PCI bus module controls it's own autonomous - * PCI bus. - */ - -extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask); - -#define PCI_STC_FLUSHFLAG_INIT(STC) \ - (*((STC)->strbuf_flushflag) = 0UL) -#define PCI_STC_FLUSHFLAG_SET(STC) \ - (*((STC)->strbuf_flushflag) != 0UL) - -struct pci_controller_info; - -struct pci_pbm_info { - struct pci_pbm_info *next; - int index; - - /* PCI controller we sit under. */ - struct pci_controller_info *parent; - - /* Physical address base of controller registers. */ - unsigned long controller_regs; - - /* Physical address base of PBM registers. */ - unsigned long pbm_regs; - - /* Physical address of DMA sync register, if any. */ - unsigned long sync_reg; - - /* Opaque 32-bit system bus Port ID. */ - u32 portid; - - /* Opaque 32-bit handle used for hypervisor calls. */ - u32 devhandle; - - /* Chipset version information. */ - int chip_type; -#define PBM_CHIP_TYPE_SABRE 1 -#define PBM_CHIP_TYPE_PSYCHO 2 -#define PBM_CHIP_TYPE_SCHIZO 3 -#define PBM_CHIP_TYPE_SCHIZO_PLUS 4 -#define PBM_CHIP_TYPE_TOMATILLO 5 - int chip_version; - int chip_revision; - - /* Name used for top-level resources. */ - char *name; - - /* OBP specific information. */ - struct device_node *prom_node; - u64 ino_bitmap; - - /* PBM I/O and Memory space resources. */ - struct resource io_space; - struct resource mem_space; - - /* Base of PCI Config space, can be per-PBM or shared. */ - unsigned long config_space; - - /* State of 66MHz capabilities on this PBM. */ - int is_66mhz_capable; - int all_devs_66mhz; - -#ifdef CONFIG_PCI_MSI - /* MSI info. */ - u32 msiq_num; - u32 msiq_ent_count; - u32 msiq_first; - u32 msiq_first_devino; - u32 msi_num; - u32 msi_first; - u32 msi_data_mask; - u32 msix_data_width; - u64 msi32_start; - u64 msi64_start; - u32 msi32_len; - u32 msi64_len; - void *msi_queues; - unsigned long *msi_bitmap; - int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, - struct msi_desc *entry); - void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); -#endif /* !(CONFIG_PCI_MSI) */ - - /* This PBM's streaming buffer. */ - struct strbuf stc; - - /* IOMMU state, potentially shared by both PBM segments. */ - struct iommu *iommu; - - /* Now things for the actual PCI bus probes. */ - unsigned int pci_first_busno; - unsigned int pci_last_busno; - struct pci_bus *pci_bus; - void (*scan_bus)(struct pci_pbm_info *); - struct pci_ops *pci_ops; -}; - -struct pci_controller_info { - /* The PCI bus modules controlled by us. */ - struct pci_pbm_info pbm_A; - struct pci_pbm_info pbm_B; -}; - -#endif /* !(__SPARC64_PBM_H) */ From af80318eb71e234a59957cd1d2d7c3fa2ea27313 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 May 2007 17:23:31 -0700 Subject: [PATCH 12/14] [SPARC64]: Fix request_irq() ignored result warnings in PCI controller code. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 28 +++++++-- arch/sparc64/kernel/pci_sabre.c | 18 ++++-- arch/sparc64/kernel/pci_schizo.c | 100 ++++++++++++++++++++----------- 3 files changed, 102 insertions(+), 44 deletions(-) diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 401e5dfe9bd5..2edcb1dd13c3 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -836,6 +836,7 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) struct of_device *op = of_find_device_by_node(pbm->prom_node); unsigned long base = pbm->controller_regs; u64 tmp; + int err; if (!op) return; @@ -852,12 +853,27 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) if (op->num_irqs < 6) return; - 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); + /* We really mean to ignore the return result here. Two + * PCI controller share the same interrupt numbers and + * drive the same front-end hardware. Whichever of the + * two get in here first will register the IRQ handler + * the second will just error out since we do not pass in + * IRQF_SHARED. + */ + err = request_irq(op->irqs[1], psycho_ue_intr, 0, + "PSYCHO_UE", pbm); + err = request_irq(op->irqs[2], psycho_ce_intr, 0, + "PSYCHO_CE", pbm); + + /* This one, however, ought not to fail. We can just warn + * about it since the system can still operate properly even + * if this fails. + */ + err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, + "PSYCHO_PCIERR", pbm); + if (err) + printk(KERN_WARNING "%s: Could not register PCIERR, " + "err=%d\n", pbm->name, err); /* Enable UE and CE interrupts for controller. */ psycho_write(base + PSYCHO_ECC_CTRL, diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 863308c8955d..4cefe6e83b24 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -831,6 +831,7 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) struct of_device *op; unsigned long base = pbm->controller_regs; u64 tmp; + int err; if (pbm->chip_type == PBM_CHIP_TYPE_SABRE) dp = dp->parent; @@ -857,15 +858,24 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); - request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); + err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); + if (err) + printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", + pbm->name, err); 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, 0, "SABRE_CE", pbm); - request_irq(op->irqs[0], sabre_pcierr_intr, 0, - "SABRE_PCIERR", pbm); + err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); + if (err) + printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", + pbm->name, err); + err = request_irq(op->irqs[0], sabre_pcierr_intr, 0, + "SABRE_PCIERR", pbm); + if (err) + printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", + pbm->name, err); tmp = sabre_read(base + SABRE_PCICTRL); tmp |= SABRE_PCICTRL_ERREN; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 312f3e4f2ed4..e375d72b8eed 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -984,6 +984,7 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) { struct of_device *op = of_find_device_by_node(pbm->prom_node); u64 tmp, err_mask, err_no_mask; + int err; /* Tomatillo IRQ property layout is: * 0: PCIERR @@ -993,24 +994,39 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) * 4: POWER FAIL? */ - if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) - request_irq(op->irqs[1], schizo_ue_intr, 0, - "TOMATILLO_UE", pbm); + if (pbm_routes_this_ino(pbm, SCHIZO_UE_INO)) { + err = request_irq(op->irqs[1], schizo_ue_intr, 0, + "TOMATILLO_UE", pbm); + if (err) + printk(KERN_WARNING "%s: Could not register UE, " + "err=%d\n", pbm->name, err); + } + if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) { + err = request_irq(op->irqs[2], schizo_ce_intr, 0, + "TOMATILLO_CE", pbm); + if (err) + printk(KERN_WARNING "%s: Could not register CE, " + "err=%d\n", pbm->name, err); + } + err = 0; + if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) { + err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, + "TOMATILLO_PCIERR", pbm); + } else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) { + err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, + "TOMATILLO_PCIERR", pbm); + } + if (err) + printk(KERN_WARNING "%s: Could not register PCIERR, " + "err=%d\n", pbm->name, err); - 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); - - if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) - request_irq(op->irqs[3], schizo_safarierr_intr, 0, - "TOMATILLO_SERR", pbm); + if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) { + err = request_irq(op->irqs[3], schizo_safarierr_intr, 0, + "TOMATILLO_SERR", pbm); + if (err) + printk(KERN_WARNING "%s: Could not register SERR, " + "err=%d\n", pbm->name, err); + } /* Enable UE and CE interrupts for controller. */ schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, @@ -1064,6 +1080,7 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) { struct of_device *op = of_find_device_by_node(pbm->prom_node); u64 tmp, err_mask, err_no_mask; + int err; /* Schizo IRQ property layout is: * 0: PCIERR @@ -1073,24 +1090,39 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) * 4: POWER FAIL? */ - 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_UE_INO)) { + err = request_irq(op->irqs[1], schizo_ue_intr, 0, + "SCHIZO_UE", pbm); + if (err) + printk(KERN_WARNING "%s: Could not register UE, " + "err=%d\n", pbm->name, err); + } + if (pbm_routes_this_ino(pbm, SCHIZO_CE_INO)) { + err = request_irq(op->irqs[2], schizo_ce_intr, 0, + "SCHIZO_CE", pbm); + if (err) + printk(KERN_WARNING "%s: Could not register CE, " + "err=%d\n", pbm->name, err); + } + err = 0; + if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_A_INO)) { + err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, + "SCHIZO_PCIERR", pbm); + } else if (pbm_routes_this_ino(pbm, SCHIZO_PCIERR_B_INO)) { + err = request_irq(op->irqs[0], schizo_pcierr_intr, 0, + "SCHIZO_PCIERR", pbm); + } + if (err) + printk(KERN_WARNING "%s: Could not register PCIERR, " + "err=%d\n", pbm->name, err); - 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); + if (pbm_routes_this_ino(pbm, SCHIZO_SERR_INO)) { + err = request_irq(op->irqs[3], schizo_safarierr_intr, 0, + "SCHIZO_SERR", pbm); + if (err) + printk(KERN_WARNING "%s: Could not register SERR, " + "err=%d\n", pbm->name, err); + } /* Enable UE and CE interrupts for controller. */ schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, From 6c1142602c9c8faedbc1321892a169652a173fc7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 May 2007 17:50:14 -0700 Subject: [PATCH 13/14] [SPARC]: Wire up utimensat syscall. Signed-off-by: David S. Miller --- arch/sparc/kernel/systbls.S | 2 ++ arch/sparc64/kernel/sys_sparc32.c | 2 +- arch/sparc64/kernel/systbls.S | 3 +++ include/asm-sparc/unistd.h | 3 ++- include/asm-sparc64/unistd.h | 3 ++- 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 3a69778c8366..e3f5b8ed4c52 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -80,6 +80,7 @@ sys_call_table: /*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare /*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy /*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait +/*310*/ .long sys_utimensat #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -196,5 +197,6 @@ sunos_sys_table: .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys +/*310*/ .long sunos_nosys #endif diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 692e46a6b8da..abd83129b2e7 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -793,7 +793,7 @@ asmlinkage long sys32_utimes(char __user *filename, tv[1].tv_nsec = 1000 * ktvs[1].tv_usec; } - return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL); + return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0); } /* These are here just in case some old sparc32 binary calls it. */ diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 48c36fe6dc62..5fe7f9ad4a92 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -81,6 +81,7 @@ sys_call_table32: .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare /*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait +/*310*/ .word compat_sys_utimensat #endif /* CONFIG_COMPAT */ @@ -152,6 +153,7 @@ sys_call_table: .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare /*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait +/*310*/ .word sys_utimensat #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -269,5 +271,6 @@ sunos_sys_table: .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys +/*310*/ .long sunos_nosys #endif diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h index e43ed1d63a9d..da9bdc5e5526 100644 --- a/include/asm-sparc/unistd.h +++ b/include/asm-sparc/unistd.h @@ -326,8 +326,9 @@ #define __NR_move_pages 307 #define __NR_getcpu 308 #define __NR_epoll_pwait 309 +#define __NR_utimensat 310 -#define NR_SYSCALLS 310 +#define NR_SYSCALLS 311 #ifdef __KERNEL__ #define __ARCH_WANT_IPC_PARSE_VERSION diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h index e2dcb87e0c62..fcd627594f4c 100644 --- a/include/asm-sparc64/unistd.h +++ b/include/asm-sparc64/unistd.h @@ -328,8 +328,9 @@ #define __NR_move_pages 307 #define __NR_getcpu 308 #define __NR_epoll_pwait 309 +#define __NR_utimensat 310 -#define NR_SYSCALLS 310 +#define NR_SYSCALLS 311 #ifdef __KERNEL__ /* sysconf options, for SunOS compatibility */ From 127cda1e8cc282de1ca7a9dcc3866841977b9fcc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 May 2007 18:25:14 -0700 Subject: [PATCH 14/14] [SPARC64]: Optimize fault kprobe handling just like powerpc. And eliminate DIE_GPF while we're at it. Signed-off-by: David S. Miller --- arch/sparc64/kernel/kprobes.c | 11 +-------- arch/sparc64/mm/fault.c | 43 +++++++++++------------------------ include/asm-sparc64/kdebug.h | 16 ++++++++++--- include/asm-sparc64/kprobes.h | 1 + 4 files changed, 28 insertions(+), 43 deletions(-) diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index a44fe47a3c2b..c93a15b785fa 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -313,7 +313,7 @@ out: return 1; } -static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); @@ -403,15 +403,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, if (post_kprobe_handler(args->regs)) ret = NOTIFY_STOP; break; - case DIE_GPF: - case DIE_PAGE_FAULT: - /* kprobe_running() needs smp_processor_id() */ - preempt_disable(); - if (kprobe_running() && - kprobe_fault_handler(args->regs, args->trapnr)) - ret = NOTIFY_STOP; - preempt_enable(); - break; default: break; } diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index c32e309f7788..b582024d2199 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -32,36 +32,23 @@ #include #ifdef CONFIG_KPROBES -ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); - -/* Hook to register for page fault notifications */ -int register_page_fault_notifier(struct notifier_block *nb) +static inline int notify_page_fault(struct pt_regs *regs) { - return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); -} + int ret = 0; -int unregister_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); -} - -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) -{ - struct die_args args = { - .regs = regs, - .str = str, - .err = err, - .trapnr = trap, - .signr = sig - }; - return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); + /* kprobe_running() needs smp_processor_id() */ + if (!user_mode(regs)) { + preempt_disable(); + if (kprobe_running() && kprobe_fault_handler(regs, 0)) + ret = 1; + preempt_enable(); + } + return ret; } #else -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) +static inline int notify_page_fault(struct pt_regs *regs) { - return NOTIFY_DONE; + return 0; } #endif @@ -120,9 +107,6 @@ static void __kprobes unhandled_fault(unsigned long address, printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n", (tsk->mm ? (unsigned long) tsk->mm->pgd : (unsigned long) tsk->active_mm->pgd)); - if (notify_die(DIE_GPF, "general protection fault", regs, - 0, 0, SIGSEGV) == NOTIFY_STOP) - return; die_if_kernel("Oops", regs); } @@ -299,8 +283,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) fault_code = get_thread_fault_code(); - if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, - fault_code, 0, SIGSEGV) == NOTIFY_STOP) + if (notify_page_fault(regs)) return; si_code = SEGV_MAPERR; diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h index f8032e73f384..627e3396a5f0 100644 --- a/include/asm-sparc64/kdebug.h +++ b/include/asm-sparc64/kdebug.h @@ -7,8 +7,19 @@ struct pt_regs; -extern int register_page_fault_notifier(struct notifier_block *); -extern int unregister_page_fault_notifier(struct notifier_block *); +/* + * These are only here because kprobes.c wants them to implement a + * blatant layering violation. Will hopefully go away soon once all + * architectures are updated. + */ +static inline int register_page_fault_notifier(struct notifier_block *nb) +{ + return 0; +} +static inline int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return 0; +} extern void bad_trap(struct pt_regs *, long); @@ -20,7 +31,6 @@ enum die_val { DIE_DIE, DIE_TRAP, DIE_TRAP_TL1, - DIE_GPF, DIE_CALL, DIE_PAGE_FAULT, }; diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h index becc38fa06c5..a331b7b0dff2 100644 --- a/include/asm-sparc64/kprobes.h +++ b/include/asm-sparc64/kprobes.h @@ -43,4 +43,5 @@ struct kprobe_ctlblk { extern int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); +extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); #endif /* _SPARC64_KPROBES_H */