From patchwork Thu Jan 24 17:47:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Bogendoerfer X-Patchwork-Id: 10779691 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7E0FE91E for ; Thu, 24 Jan 2019 17:48:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 709D73220D for ; Thu, 24 Jan 2019 17:48:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 63B813269E; Thu, 24 Jan 2019 17:48:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.4 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,SORTED_RECIPS autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3A7803220D for ; Thu, 24 Jan 2019 17:48:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729193AbfAXRsH (ORCPT ); Thu, 24 Jan 2019 12:48:07 -0500 Received: from mx2.suse.de ([195.135.220.15]:51320 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728408AbfAXRrt (ORCPT ); Thu, 24 Jan 2019 12:47:49 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 31866B0D9; Thu, 24 Jan 2019 17:47:45 +0000 (UTC) From: Thomas Bogendoerfer To: Bjorn Helgaas , James Hogan , linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org, linux-pci@vger.kernel.org, Lorenzo Pieralisi , Paul Burton , Ralf Baechle Subject: [PATCH 1/7] MIPS: SGI-IP27: get rid of volatile and hubreg_t Date: Thu, 24 Jan 2019 18:47:22 +0100 Message-Id: <20190124174728.28812-2-tbogendoerfer@suse.de> X-Mailer: git-send-email 2.13.7 In-Reply-To: <20190124174728.28812-1-tbogendoerfer@suse.de> References: <20190124174728.28812-1-tbogendoerfer@suse.de> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Replace hub register access with __raw_readq/__raw_writeq and get rid of hubreg_t completely. Also remove no longer (probably never) used defines Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/sn/addrs.h | 63 +++------------------------------------- arch/mips/include/asm/sn/arch.h | 2 -- arch/mips/sgi-ip27/ip27-hubio.c | 2 +- arch/mips/sgi-ip27/ip27-init.c | 2 +- arch/mips/sgi-ip27/ip27-irq.c | 4 +-- arch/mips/sgi-ip27/ip27-memory.c | 6 ++-- arch/mips/sgi-ip27/ip27-nmi.c | 2 +- 7 files changed, 12 insertions(+), 69 deletions(-) diff --git a/arch/mips/include/asm/sn/addrs.h b/arch/mips/include/asm/sn/addrs.h index 66814f8ba8e8..3eb81e30a568 100644 --- a/arch/mips/include/asm/sn/addrs.h +++ b/arch/mips/include/asm/sn/addrs.h @@ -27,16 +27,11 @@ #ifndef __ASSEMBLY__ -#define PS_UINT_CAST (unsigned long) #define UINT64_CAST (unsigned long) -#define HUBREG_CAST (volatile hubreg_t *) - #else /* __ASSEMBLY__ */ -#define PS_UINT_CAST #define UINT64_CAST -#define HUBREG_CAST #endif /* __ASSEMBLY__ */ @@ -256,42 +251,22 @@ * Otherwise, the recommended approach is to use *_HUB_L() and *_HUB_S(). * They're always safe. */ -#define LOCAL_HUB_ADDR(_x) (HUBREG_CAST (IALIAS_BASE + (_x))) -#define REMOTE_HUB_ADDR(_n, _x) (HUBREG_CAST (NODE_SWIN_BASE(_n, 1) + \ - 0x800000 + (_x))) -#ifdef CONFIG_SGI_IP27 -#define REMOTE_HUB_PI_ADDR(_n, _sn, _x) (HUBREG_CAST (NODE_SWIN_BASE(_n, 1) + \ - 0x800000 + (_x))) -#endif /* CONFIG_SGI_IP27 */ +#define LOCAL_HUB_ADDR(_x) (IALIAS_BASE + (_x)) +#define REMOTE_HUB_ADDR(_n, _x) ((NODE_SWIN_BASE(_n, 1) + 0x800000 + (_x))) #ifndef __ASSEMBLY__ -#define HUB_L(_a) *(_a) -#define HUB_S(_a, _d) *(_a) = (_d) +#define HUB_L(_a) __raw_readq((u64 *)(_a)) +#define HUB_S(_a, _d) __raw_writeq((_d), (u64 *)(_a)) #define LOCAL_HUB_L(_r) HUB_L(LOCAL_HUB_ADDR(_r)) #define LOCAL_HUB_S(_r, _d) HUB_S(LOCAL_HUB_ADDR(_r), (_d)) #define REMOTE_HUB_L(_n, _r) HUB_L(REMOTE_HUB_ADDR((_n), (_r))) #define REMOTE_HUB_S(_n, _r, _d) HUB_S(REMOTE_HUB_ADDR((_n), (_r)), (_d)) -#define REMOTE_HUB_PI_L(_n, _sn, _r) HUB_L(REMOTE_HUB_PI_ADDR((_n), (_sn), (_r))) -#define REMOTE_HUB_PI_S(_n, _sn, _r, _d) HUB_S(REMOTE_HUB_PI_ADDR((_n), (_sn), (_r)), (_d)) #endif /* !__ASSEMBLY__ */ /* - * The following macros are used to get to a hub/bridge register, given - * the base of the register space. - */ -#define HUB_REG_PTR(_base, _off) \ - (HUBREG_CAST((__psunsigned_t)(_base) + (__psunsigned_t)(_off))) - -#define HUB_REG_PTR_L(_base, _off) \ - HUB_L(HUB_REG_PTR((_base), (_off))) - -#define HUB_REG_PTR_S(_base, _off, _data) \ - HUB_S(HUB_REG_PTR((_base), (_off)), (_data)) - -/* * Software structure locations -- permanently fixed * See diagram in kldir.h */ @@ -387,44 +362,14 @@ #define SYMMON_STK_END(nasid) (SYMMON_STK_ADDR(nasid, 0) + KLD_SYMMON_STK(nasid)->size) -/* loading symmon 4k below UNIX. the arcs loader needs the topaddr for a - * relocatable program - */ -#define UNIX_DEBUG_LOADADDR 0x300000 -#define SYMMON_LOADADDR(nasid) \ - TO_NODE(nasid, PHYS_TO_K0(UNIX_DEBUG_LOADADDR - 0x1000)) - -#define FREEMEM_OFFSET(nasid) KLD_FREEMEM(nasid)->offset -#define FREEMEM_ADDR(nasid) SYMMON_STK_END(nasid) -/* - * XXX - * Fix this. FREEMEM_ADDR should be aware of if symmon is loaded. - * Also, it should take into account what prom thinks to be a safe - * address - PHYS_TO_K0(NODE_OFFSET(nasid) + FREEMEM_OFFSET(nasid)) - */ -#define FREEMEM_SIZE(nasid) KLD_FREEMEM(nasid)->size - -#define PI_ERROR_OFFSET(nasid) KLD_PI_ERROR(nasid)->offset -#define PI_ERROR_ADDR(nasid) \ - TO_NODE_UNCAC((nasid), PI_ERROR_OFFSET(nasid)) -#define PI_ERROR_SIZE(nasid) KLD_PI_ERROR(nasid)->size - #define NODE_OFFSET_TO_K0(_nasid, _off) \ PHYS_TO_K0((NODE_OFFSET(_nasid) + (_off)) | CAC_BASE) #define NODE_OFFSET_TO_K1(_nasid, _off) \ TO_UNCAC((NODE_OFFSET(_nasid) + (_off)) | UNCAC_BASE) -#define K0_TO_NODE_OFFSET(_k0addr) \ - ((__psunsigned_t)(_k0addr) & NODE_ADDRSPACE_MASK) #define KERN_VARS_ADDR(nasid) KLD_KERN_VARS(nasid)->pointer #define KERN_VARS_SIZE(nasid) KLD_KERN_VARS(nasid)->size -#define KERN_XP_ADDR(nasid) KLD_KERN_XP(nasid)->pointer -#define KERN_XP_SIZE(nasid) KLD_KERN_XP(nasid)->size - -#define GPDA_ADDR(nasid) TO_NODE_CAC(nasid, GPDA_OFFSET) - #endif /* !__ASSEMBLY__ */ diff --git a/arch/mips/include/asm/sn/arch.h b/arch/mips/include/asm/sn/arch.h index 471e6870d876..3f1fb1454749 100644 --- a/arch/mips/include/asm/sn/arch.h +++ b/arch/mips/include/asm/sn/arch.h @@ -17,8 +17,6 @@ #include #endif -typedef u64 hubreg_t; - #define cputonasid(cpu) (sn_cpu_info[(cpu)].p_nasid) #define cputoslice(cpu) (sn_cpu_info[(cpu)].p_slice) #define makespnum(_nasid, _slice) \ diff --git a/arch/mips/sgi-ip27/ip27-hubio.c b/arch/mips/sgi-ip27/ip27-hubio.c index 2abe016a0ffc..9b4fd7773423 100644 --- a/arch/mips/sgi-ip27/ip27-hubio.c +++ b/arch/mips/sgi-ip27/ip27-hubio.c @@ -135,7 +135,7 @@ static void hub_setup_prb(nasid_t nasid, int prbnum, int credits) **/ static void hub_set_piomode(nasid_t nasid) { - hubreg_t ii_iowa; + u64 ii_iowa; hubii_wcr_t ii_wcr; unsigned i; diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index e501c43c02db..83399e578b61 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -177,7 +177,7 @@ extern void ip27_reboot_setup(void); void __init plat_mem_setup(void) { - hubreg_t p, e, n_mode; + u64 p, e, n_mode; nasid_t nid; ip27_reboot_setup(); diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 0dde6164a06f..f37155ef7ed9 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -85,7 +85,7 @@ static int ms1bit(unsigned long x) static void ip27_do_irq_mask0(void) { int irq, swlevel; - hubreg_t pend0, mask0; + u64 pend0, mask0; cpuid_t cpu = smp_processor_id(); int pi_int_mask0 = (cputoslice(cpu) == 0) ? PI_INT_MASK0_A : PI_INT_MASK0_B; @@ -132,7 +132,7 @@ static void ip27_do_irq_mask0(void) static void ip27_do_irq_mask1(void) { int irq, swlevel; - hubreg_t pend1, mask1; + u64 pend1, mask1; cpuid_t cpu = smp_processor_id(); int pi_int_mask1 = (cputoslice(cpu) == 0) ? PI_INT_MASK1_A : PI_INT_MASK1_B; struct slice_data *si = cpu_data[cpu].data; diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index 813d13f92957..87ef4181934e 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -44,7 +44,7 @@ static int is_fine_dirmode(void) return ((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE; } -static hubreg_t get_region(cnodeid_t cnode) +static u64 get_region(cnodeid_t cnode) { if (fine_mode) return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT; @@ -52,9 +52,9 @@ static hubreg_t get_region(cnodeid_t cnode) return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT; } -static hubreg_t region_mask; +static u64 region_mask; -static void gen_region_mask(hubreg_t *region_mask) +static void gen_region_mask(u64 *region_mask) { cnodeid_t cnode; diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c index 8ac2bfa35fb6..8cb3a5d6d7d1 100644 --- a/arch/mips/sgi-ip27/ip27-nmi.c +++ b/arch/mips/sgi-ip27/ip27-nmi.c @@ -130,7 +130,7 @@ void nmi_cpu_eframe_save(nasid_t nasid, int slice) void nmi_dump_hub_irq(nasid_t nasid, int slice) { - hubreg_t mask0, mask1, pend0, pend1; + u64 mask0, mask1, pend0, pend1; if (slice == 0) { /* Slice A */ mask0 = REMOTE_HUB_L(nasid, PI_INT_MASK0_A); From patchwork Thu Jan 24 17:47:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Bogendoerfer X-Patchwork-Id: 10779699 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3B0571515 for ; Thu, 24 Jan 2019 17:48:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2B8203220D for ; Thu, 24 Jan 2019 17:48:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1FCDE326B3; Thu, 24 Jan 2019 17:48:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.4 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,SORTED_RECIPS autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 863F3326AD for ; Thu, 24 Jan 2019 17:48:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729057AbfAXRrs (ORCPT ); Thu, 24 Jan 2019 12:47:48 -0500 Received: from mx2.suse.de ([195.135.220.15]:51358 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728565AbfAXRrr (ORCPT ); Thu, 24 Jan 2019 12:47:47 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 36A64B0DD; Thu, 24 Jan 2019 17:47:45 +0000 (UTC) From: Thomas Bogendoerfer To: Bjorn Helgaas , James Hogan , linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org, linux-pci@vger.kernel.org, Lorenzo Pieralisi , Paul Burton , Ralf Baechle Subject: [PATCH 2/7] MIPS: SGI-IP27: clean up bridge access and header files Date: Thu, 24 Jan 2019 18:47:23 +0100 Message-Id: <20190124174728.28812-3-tbogendoerfer@suse.de> X-Mailer: git-send-email 2.13.7 In-Reply-To: <20190124174728.28812-1-tbogendoerfer@suse.de> References: <20190124174728.28812-1-tbogendoerfer@suse.de> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Introduced bridge_read/bridge_write/bridge_set/bridge_clr for accessing bridge register and get rid of volatile declarations. Also removed all typedefs from arch/mips/include/asm/pci/bridge.h and cleaned up language in arch/mips/pci/ops-bridge.c Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/pci/bridge.h | 217 +++++++++++++++++------------------ arch/mips/include/asm/sn/sn0/addrs.h | 5 - arch/mips/pci/ops-bridge.c | 68 ++++------- arch/mips/pci/pci-ip27.c | 31 +++-- arch/mips/sgi-ip27/ip27-irq-pci.c | 24 ++-- 5 files changed, 153 insertions(+), 192 deletions(-) diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index 3206245d1ed6..6155618ce45b 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h @@ -44,19 +44,37 @@ */ #ifndef __ASSEMBLY__ +/* Address translation entry for mapped pci32 accesses */ +union bridge_ate { + u64 ent; + struct ate_s { + u64 rmf:16; + u64 addr:36; + u64 targ:4; + u64 reserved:3; + u64 barrier:1; + u64 prefetch:1; + u64 precise:1; + u64 coherent:1; + u64 valid:1; + } field; +}; -/* - * All accesses to bridge hardware registers must be done - * using 32-bit loads and stores. - */ -typedef u32 bridgereg_t; +#define ATE_V 0x01 +#define ATE_CO 0x02 +#define ATE_PREC 0x04 +#define ATE_PREF 0x08 +#define ATE_BAR 0x10 -typedef u64 bridge_ate_t; +#define ATE_PFNSHIFT 12 +#define ATE_TIDSHIFT 8 +#define ATE_RMFSHIFT 48 -/* pointers to bridge ATEs - * are always "pointer to volatile" - */ -typedef volatile bridge_ate_t *bridge_ate_p; +#define mkate(xaddr, xid, attr) (((xaddr) & 0x0000fffffffff000ULL) | \ + ((xid)<sysdata)) +#define bridge_read(bc, reg) __raw_readl(&bc->base->reg) +#define bridge_write(bc, reg, val) __raw_writel(val, &bc->base->reg) +#define bridge_set(bc, reg, val) \ + __raw_writel(__raw_readl(&bc->base->reg) | (val), &bc->base->reg) +#define bridge_clr(bc, reg, val) \ + __raw_writel(__raw_readl(&bc->base->reg) & ~(val), &bc->base->reg) + extern void register_bridge_irq(unsigned int irq); extern int request_bridge_irq(struct bridge_controller *bc); diff --git a/arch/mips/include/asm/sn/sn0/addrs.h b/arch/mips/include/asm/sn/sn0/addrs.h index 6b53070f400f..f13df84edfdd 100644 --- a/arch/mips/include/asm/sn/sn0/addrs.h +++ b/arch/mips/include/asm/sn/sn0/addrs.h @@ -134,11 +134,6 @@ #define CALIAS_BASE CAC_BASE - - -#define BRIDGE_REG_PTR(_base, _off) ((volatile bridgereg_t *) \ - ((__psunsigned_t)(_base) + (__psunsigned_t)(_off))) - #define SN0_WIDGET_BASE(_nasid, _wid) (NODE_SWIN_BASE((_nasid), (_wid))) /* Turn on sable logging for the processors whose bits are set. */ diff --git a/arch/mips/pci/ops-bridge.c b/arch/mips/pci/ops-bridge.c index a1d2c4ae0d1b..df95b0da08f2 100644 --- a/arch/mips/pci/ops-bridge.c +++ b/arch/mips/pci/ops-bridge.c @@ -44,7 +44,7 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * value) { struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); - bridge_t *bridge = bc->base; + struct bridge_regs *bridge = bc->base; int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); volatile void *addr; @@ -56,11 +56,11 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_DEVICE_NOT_FOUND; /* - * IOC3 is fucking fucked beyond belief ... Don't even give the + * IOC3 is broken beyond belief ... Don't even give the * generic PCI code a chance to look at it for real ... */ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto oh_my_gawd; + goto is_ioc3; addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; @@ -73,21 +73,16 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -oh_my_gawd: +is_ioc3: /* - * IOC3 is fucking fucked beyond belief ... Don't even give the - * generic PCI code a chance to look at the wrong register. + * IOC3 special handling */ if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { *value = emulate_ioc3_cfg(where, size); return PCIBIOS_SUCCESSFUL; } - /* - * IOC3 is fucking fucked beyond belief ... Don't try to access - * anything but 32-bit words ... - */ addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; if (get_dbe(cf, (u32 *) addr)) @@ -104,7 +99,7 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * value) { struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); - bridge_t *bridge = bc->base; + struct bridge_regs *bridge = bc->base; int busno = bus->number; int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); @@ -112,19 +107,19 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, u32 cf, shift, mask; int res; - bridge->b_pci_cfg = (busno << 16) | (slot << 11); + bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; if (get_dbe(cf, (u32 *) addr)) return PCIBIOS_DEVICE_NOT_FOUND; /* - * IOC3 is fucking fucked beyond belief ... Don't even give the + * IOC3 is broken beyond belief ... Don't even give the * generic PCI code a chance to look at it for real ... */ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto oh_my_gawd; + goto is_ioc3; - bridge->b_pci_cfg = (busno << 16) | (slot << 11); + bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; if (size == 1) @@ -136,22 +131,17 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; -oh_my_gawd: +is_ioc3: /* - * IOC3 is fucking fucked beyond belief ... Don't even give the - * generic PCI code a chance to look at the wrong register. + * IOC3 special handling */ if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { *value = emulate_ioc3_cfg(where, size); return PCIBIOS_SUCCESSFUL; } - /* - * IOC3 is fucking fucked beyond belief ... Don't try to access - * anything but 32-bit words ... - */ - bridge->b_pci_cfg = (busno << 16) | (slot << 11); + bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; if (get_dbe(cf, (u32 *) addr)) @@ -177,7 +167,7 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); - bridge_t *bridge = bc->base; + struct bridge_regs *bridge = bc->base; int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); volatile void *addr; @@ -189,11 +179,11 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_DEVICE_NOT_FOUND; /* - * IOC3 is fucking fucked beyond belief ... Don't even give the + * IOC3 is broken beyond belief ... Don't even give the * generic PCI code a chance to look at it for real ... */ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto oh_my_gawd; + goto is_ioc3; addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; @@ -210,19 +200,14 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_SUCCESSFUL; -oh_my_gawd: +is_ioc3: /* - * IOC3 is fucking fucked beyond belief ... Don't even give the - * generic PCI code a chance to touch the wrong register. + * IOC3 special handling */ if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) return PCIBIOS_SUCCESSFUL; - /* - * IOC3 is fucking fucked beyond belief ... Don't try to access - * anything but 32-bit words ... - */ addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; if (get_dbe(cf, (u32 *) addr)) @@ -243,7 +228,7 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); - bridge_t *bridge = bc->base; + struct bridge_regs *bridge = bc->base; int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); int busno = bus->number; @@ -251,17 +236,17 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, u32 cf, shift, mask, smask; int res; - bridge->b_pci_cfg = (busno << 16) | (slot << 11); + bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; if (get_dbe(cf, (u32 *) addr)) return PCIBIOS_DEVICE_NOT_FOUND; /* - * IOC3 is fucking fucked beyond belief ... Don't even give the + * IOC3 is broken beyond belief ... Don't even give the * generic PCI code a chance to look at it for real ... */ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto oh_my_gawd; + goto is_ioc3; addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; @@ -278,19 +263,14 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_SUCCESSFUL; -oh_my_gawd: +is_ioc3: /* - * IOC3 is fucking fucked beyond belief ... Don't even give the - * generic PCI code a chance to touch the wrong register. + * IOC3 special handling */ if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) return PCIBIOS_SUCCESSFUL; - /* - * IOC3 is fucking fucked beyond belief ... Don't try to access - * anything but 32-bit words ... - */ addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; if (get_dbe(cf, (u32 *) addr)) diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index c94a66070a60..7cf50290a6d9 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -47,7 +47,6 @@ int bridge_probe(nasid_t nasid, int widget_id, int masterwid) unsigned long offset = NODE_OFFSET(nasid); struct bridge_controller *bc; static int num_bridges = 0; - bridge_t *bridge; int slot; pci_set_flags(PCI_PROBE_ONLY); @@ -87,45 +86,43 @@ int bridge_probe(nasid_t nasid, int widget_id, int masterwid) /* * point to this bridge */ - bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); + bc->base = (struct bridge_regs *)RAW_NODE_SWIN_BASE(nasid, widget_id); /* * Clear all pending interrupts. */ - bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR; + bridge_write(bc, b_int_rst_stat, BRIDGE_IRR_ALL_CLR); /* * Until otherwise set up, assume all interrupts are from slot 0 */ - bridge->b_int_device = 0x0; + bridge_write(bc, b_int_device, 0x0); /* * swap pio's to pci mem and io space (big windows) */ - bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | - BRIDGE_CTRL_MEM_SWAP; + bridge_set(bc, b_wid_control, BRIDGE_CTRL_IO_SWAP | + BRIDGE_CTRL_MEM_SWAP); #ifdef CONFIG_PAGE_SIZE_4KB - bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE; + bridge_clr(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); #else /* 16kB or larger */ - bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE; + bridge_set(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); #endif /* * Hmm... IRIX sets additional bits in the address which * are documented as reserved in the bridge docs. */ - bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); - bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ - bridge->b_dir_map = (masterwid << 20); /* DMA */ - bridge->b_int_enable = 0; + bridge_write(bc, b_wid_int_upper, 0x8000 | (masterwid << 16)); + bridge_write(bc, b_wid_int_lower, 0x01800090); /* PI_INT_PEND_MOD off*/ + bridge_write(bc, b_dir_map, (masterwid << 20)); /* DMA */ + bridge_write(bc, b_int_enable, 0); for (slot = 0; slot < 8; slot ++) { - bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; + bridge_set(bc, b_device[slot].reg, BRIDGE_DEV_SWAP_DIR); bc->pci_int[slot] = -1; } - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - - bc->base = bridge; + bridge_read(bc, b_wid_tflush); /* wait until Bridge PIO complete */ register_pci_controller(&bc->pc); @@ -206,7 +203,7 @@ phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dma_addr) static inline void pci_disable_swapping(struct pci_dev *dev) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); - bridge_t *bridge = bc->base; + struct bridge_regs *bridge = bc->base; int slot = PCI_SLOT(dev->devfn); /* Turn off byte swapping */ diff --git a/arch/mips/sgi-ip27/ip27-irq-pci.c b/arch/mips/sgi-ip27/ip27-irq-pci.c index cd449e90b917..a00a23b32a2a 100644 --- a/arch/mips/sgi-ip27/ip27-irq-pci.c +++ b/arch/mips/sgi-ip27/ip27-irq-pci.c @@ -136,14 +136,12 @@ static int intr_disconnect_level(int cpu, int bit) static unsigned int startup_bridge_irq(struct irq_data *d) { struct bridge_controller *bc; - bridgereg_t device; - bridge_t *bridge; int pin, swlevel; cpuid_t cpu; + u64 device; pin = SLOT_FROM_PCI_IRQ(d->irq); bc = IRQ_TO_BRIDGE(d->irq); - bridge = bc->base; pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", d->irq, pin); /* @@ -151,9 +149,10 @@ static unsigned int startup_bridge_irq(struct irq_data *d) * of INT_PEND0 are taken */ swlevel = find_level(&cpu, d->irq); - bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); - bridge->b_int_enable |= (1 << pin); - bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */ + bridge_write(bc, b_int_addr[pin].addr, + (0x20000 | swlevel | (bc->nasid << 8))); + bridge_set(bc, b_int_enable, (1 << pin)); + bridge_set(bc, b_int_enable, 0x7ffffe00); /* more stuff in int_enable */ /* * Enable sending of an interrupt clear packt to the hub on a high to @@ -162,18 +161,18 @@ static unsigned int startup_bridge_irq(struct irq_data *d) * IRIX sets additional bits in the address which are documented as * reserved in the bridge docs. */ - bridge->b_int_mode |= (1UL << pin); + bridge_set(bc, b_int_mode, (1UL << pin)); /* * We assume the bridge to have a 1:1 mapping between devices * (slots) and intr pins. */ - device = bridge->b_int_device; + device = bridge_read(bc, b_int_device); device &= ~(7 << (pin*3)); device |= (pin << (pin*3)); - bridge->b_int_device = device; + bridge_write(bc, b_int_device, device); - bridge->b_wid_tflush; + bridge_read(bc, b_wid_tflush); intr_connect_level(cpu, swlevel); @@ -184,7 +183,6 @@ static unsigned int startup_bridge_irq(struct irq_data *d) static void shutdown_bridge_irq(struct irq_data *d) { struct bridge_controller *bc = IRQ_TO_BRIDGE(d->irq); - bridge_t *bridge = bc->base; int pin, swlevel; cpuid_t cpu; @@ -198,8 +196,8 @@ static void shutdown_bridge_irq(struct irq_data *d) swlevel = find_level(&cpu, d->irq); intr_disconnect_level(cpu, swlevel); - bridge->b_int_enable &= ~(1 << pin); - bridge->b_wid_tflush; + bridge_clr(bc, b_int_enable, (1 << pin)); + bridge_read(bc, b_wid_tflush); } static inline void enable_bridge_irq(struct irq_data *d) From patchwork Thu Jan 24 17:47:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Bogendoerfer X-Patchwork-Id: 10779701 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1764391E for ; Thu, 24 Jan 2019 17:48:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0AC833220D for ; Thu, 24 Jan 2019 17:48:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F37DA3264E; Thu, 24 Jan 2019 17:48:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.4 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,SORTED_RECIPS autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 65818326AA for ; Thu, 24 Jan 2019 17:48:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729082AbfAXRrs (ORCPT ); Thu, 24 Jan 2019 12:47:48 -0500 Received: from mx2.suse.de ([195.135.220.15]:51310 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728196AbfAXRrs (ORCPT ); Thu, 24 Jan 2019 12:47:48 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 315DCB0D7; Thu, 24 Jan 2019 17:47:45 +0000 (UTC) From: Thomas Bogendoerfer To: Bjorn Helgaas , James Hogan , linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org, linux-pci@vger.kernel.org, Lorenzo Pieralisi , Paul Burton , Ralf Baechle Subject: [PATCH 3/7] MIPS: SGI-IP27: use pr_info/pr_emerg and pr_cont to fix output Date: Thu, 24 Jan 2019 18:47:24 +0100 Message-Id: <20190124174728.28812-4-tbogendoerfer@suse.de> X-Mailer: git-send-email 2.13.7 In-Reply-To: <20190124174728.28812-1-tbogendoerfer@suse.de> References: <20190124174728.28812-1-tbogendoerfer@suse.de> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Topology and NMI output needs pr_cont() to look the way it was in the old days of printk. Signed-off-by: Thomas Bogendoerfer --- arch/mips/sgi-ip27/ip27-memory.c | 28 +++++++++--------- arch/mips/sgi-ip27/ip27-nmi.c | 62 ++++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index 87ef4181934e..fb077a947575 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -154,11 +154,11 @@ static int __init compute_node_distance(nasid_t nasid_a, nasid_t nasid_b) } if (router_a == NULL) { - printk("node_distance: router_a NULL\n"); + pr_info("node_distance: router_a NULL\n"); return -1; } if (router_b == NULL) { - printk("node_distance: router_b NULL\n"); + pr_info("node_distance: router_b NULL\n"); return -1; } @@ -203,17 +203,17 @@ static void __init dump_topology(void) klrou_t *router; cnodeid_t row, col; - printk("************** Topology ********************\n"); + pr_info("************** Topology ********************\n"); - printk(" "); + pr_info(" "); for_each_online_node(col) - printk("%02d ", col); - printk("\n"); + pr_cont("%02d ", col); + pr_cont("\n"); for_each_online_node(row) { - printk("%02d ", row); + pr_info("%02d ", row); for_each_online_node(col) - printk("%2d ", node_distance(row, col)); - printk("\n"); + pr_cont("%2d ", node_distance(row, col)); + pr_cont("\n"); } for_each_online_node(cnode) { @@ -230,7 +230,7 @@ static void __init dump_topology(void) do { if (brd->brd_flags & DUPLICATE_BOARD) continue; - printk("Router %d:", router_num); + pr_cont("Router %d:", router_num); router_num++; router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); @@ -244,11 +244,11 @@ static void __init dump_topology(void) router->rou_port[port].port_offset); if (dest_brd->brd_type == KLTYPE_IP27) - printk(" %d", dest_brd->brd_nasid); + pr_cont(" %d", dest_brd->brd_nasid); if (dest_brd->brd_type == KLTYPE_ROUTER) - printk(" r"); + pr_cont(" r"); } - printk("\n"); + pr_cont("\n"); } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); } @@ -373,7 +373,7 @@ static void __init szmem(void) if ((nodebytes >> PAGE_SHIFT) * (sizeof(struct page)) > (slot0sz << PAGE_SHIFT)) { - printk("Ignoring slot %d onwards on node %d\n", + pr_info("Ignoring slot %d onwards on node %d\n", slot, node); slot = MAX_MEM_SLOTS; continue; diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c index 8cb3a5d6d7d1..3aae388561d9 100644 --- a/arch/mips/sgi-ip27/ip27-nmi.c +++ b/arch/mips/sgi-ip27/ip27-nmi.c @@ -62,70 +62,70 @@ void nmi_cpu_eframe_save(nasid_t nasid, int slice) (TO_UNCAC(TO_NODE(nasid, IP27_NMI_KREGS_OFFSET)) + slice * IP27_NMI_KREGS_CPU_SIZE); - printk("NMI nasid %d: slice %d\n", nasid, slice); + pr_emerg("NMI nasid %d: slice %d\n", nasid, slice); /* * Saved main processor registers */ for (i = 0; i < 32; ) { if ((i % 4) == 0) - printk("$%2d :", i); - printk(" %016lx", nr->gpr[i]); + pr_emerg("$%2d :", i); + pr_cont(" %016lx", nr->gpr[i]); i++; if ((i % 4) == 0) - printk("\n"); + pr_cont("\n"); } - printk("Hi : (value lost)\n"); - printk("Lo : (value lost)\n"); + pr_emerg("Hi : (value lost)\n"); + pr_emerg("Lo : (value lost)\n"); /* * Saved cp0 registers */ - printk("epc : %016lx %pS\n", nr->epc, (void *) nr->epc); - printk("%s\n", print_tainted()); - printk("ErrEPC: %016lx %pS\n", nr->error_epc, (void *) nr->error_epc); - printk("ra : %016lx %pS\n", nr->gpr[31], (void *) nr->gpr[31]); - printk("Status: %08lx ", nr->sr); + pr_emerg("epc : %016lx %pS\n", nr->epc, (void *)nr->epc); + pr_emerg("%s\n", print_tainted()); + pr_emerg("ErrEPC: %016lx %pS\n", nr->error_epc, (void *)nr->error_epc); + pr_emerg("ra : %016lx %pS\n", nr->gpr[31], (void *)nr->gpr[31]); + pr_emerg("Status: %08lx ", nr->sr); if (nr->sr & ST0_KX) - printk("KX "); + pr_cont("KX "); if (nr->sr & ST0_SX) - printk("SX "); + pr_cont("SX "); if (nr->sr & ST0_UX) - printk("UX "); + pr_cont("UX "); switch (nr->sr & ST0_KSU) { case KSU_USER: - printk("USER "); + pr_cont("USER "); break; case KSU_SUPERVISOR: - printk("SUPERVISOR "); + pr_cont("SUPERVISOR "); break; case KSU_KERNEL: - printk("KERNEL "); + pr_cont("KERNEL "); break; default: - printk("BAD_MODE "); + pr_cont("BAD_MODE "); break; } if (nr->sr & ST0_ERL) - printk("ERL "); + pr_cont("ERL "); if (nr->sr & ST0_EXL) - printk("EXL "); + pr_cont("EXL "); if (nr->sr & ST0_IE) - printk("IE "); - printk("\n"); + pr_cont("IE "); + pr_cont("\n"); - printk("Cause : %08lx\n", nr->cause); - printk("PrId : %08x\n", read_c0_prid()); - printk("BadVA : %016lx\n", nr->badva); - printk("CErr : %016lx\n", nr->cache_err); - printk("NMI_SR: %016lx\n", nr->nmi_sr); + pr_emerg("Cause : %08lx\n", nr->cause); + pr_emerg("PrId : %08x\n", read_c0_prid()); + pr_emerg("BadVA : %016lx\n", nr->badva); + pr_emerg("CErr : %016lx\n", nr->cache_err); + pr_emerg("NMI_SR: %016lx\n", nr->nmi_sr); - printk("\n"); + pr_emerg("\n"); } void nmi_dump_hub_irq(nasid_t nasid, int slice) @@ -143,9 +143,9 @@ void nmi_dump_hub_irq(nasid_t nasid, int slice) pend0 = REMOTE_HUB_L(nasid, PI_INT_PEND0); pend1 = REMOTE_HUB_L(nasid, PI_INT_PEND1); - printk("PI_INT_MASK0: %16Lx PI_INT_MASK1: %16Lx\n", mask0, mask1); - printk("PI_INT_PEND0: %16Lx PI_INT_PEND1: %16Lx\n", pend0, pend1); - printk("\n\n"); + pr_emerg("PI_INT_MASK0: %16llx PI_INT_MASK1: %16llx\n", mask0, mask1); + pr_emerg("PI_INT_PEND0: %16llx PI_INT_PEND1: %16llx\n", pend0, pend1); + pr_emerg("\n\n"); } /* From patchwork Thu Jan 24 17:47:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Bogendoerfer X-Patchwork-Id: 10779705 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 807D891E for ; Thu, 24 Jan 2019 17:48:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 71CA83220D for ; Thu, 24 Jan 2019 17:48:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 661AB3269E; Thu, 24 Jan 2019 17:48:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.4 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,SORTED_RECIPS autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1746C3220D for ; Thu, 24 Jan 2019 17:48:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729228AbfAXRs1 (ORCPT ); Thu, 24 Jan 2019 12:48:27 -0500 Received: from mx2.suse.de ([195.135.220.15]:51304 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728130AbfAXRrq (ORCPT ); Thu, 24 Jan 2019 12:47:46 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 34B63B0DA; Thu, 24 Jan 2019 17:47:45 +0000 (UTC) From: Thomas Bogendoerfer To: Bjorn Helgaas , James Hogan , linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org, linux-pci@vger.kernel.org, Lorenzo Pieralisi , Paul Burton , Ralf Baechle Subject: [PATCH 4/7] MIPS: SGI-IP27: do xtalk scanning later Date: Thu, 24 Jan 2019 18:47:25 +0100 Message-Id: <20190124174728.28812-5-tbogendoerfer@suse.de> X-Mailer: git-send-email 2.13.7 In-Reply-To: <20190124174728.28812-1-tbogendoerfer@suse.de> References: <20190124174728.28812-1-tbogendoerfer@suse.de> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Move xtalk scanning to a later boot stage to be able using things like kmalloc and friends. Signed-off-by: Thomas Bogendoerfer --- arch/mips/sgi-ip27/ip27-init.c | 3 --- arch/mips/sgi-ip27/ip27-xtalk.c | 13 ++++++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 83399e578b61..aba985cf07c0 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -52,8 +52,6 @@ EXPORT_SYMBOL_GPL(sn_cpu_info); extern void pcibr_setup(cnodeid_t); -extern void xtalk_probe_node(cnodeid_t nid); - static void per_hub_init(cnodeid_t cnode) { struct hub_data *hub = hub_data(cnode); @@ -71,7 +69,6 @@ static void per_hub_init(cnodeid_t cnode) REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); hub_rtc_init(cnode); - xtalk_probe_node(cnode); #ifdef CONFIG_REPLICATE_EXHANDLERS /* diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index 4fe5678ba74d..ce06aaa115ae 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -99,7 +99,7 @@ static int xbow_probe(nasid_t nasid) return 0; } -void xtalk_probe_node(cnodeid_t nid) +static void xtalk_probe_node(cnodeid_t nid) { volatile u64 hubreg; nasid_t nasid; @@ -133,3 +133,14 @@ void xtalk_probe_node(cnodeid_t nid) break; } } + +static int __init xtalk_init(void) +{ + cnodeid_t cnode; + + for_each_online_node(cnode) + xtalk_probe_node(cnode); + + return 0; +} +arch_initcall(xtalk_init); From patchwork Thu Jan 24 17:47:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Bogendoerfer X-Patchwork-Id: 10779683 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1D3441515 for ; Thu, 24 Jan 2019 17:48:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0D1E23220D for ; Thu, 24 Jan 2019 17:48:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F400A326B4; Thu, 24 Jan 2019 17:48:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.4 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,SORTED_RECIPS autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3D1503220D for ; Thu, 24 Jan 2019 17:48:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729145AbfAXRrz (ORCPT ); Thu, 24 Jan 2019 12:47:55 -0500 Received: from mx2.suse.de ([195.135.220.15]:51376 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727991AbfAXRrt (ORCPT ); Thu, 24 Jan 2019 12:47:49 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 764C2B0DE; Thu, 24 Jan 2019 17:47:45 +0000 (UTC) From: Thomas Bogendoerfer To: Bjorn Helgaas , James Hogan , linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org, linux-pci@vger.kernel.org, Lorenzo Pieralisi , Paul Burton , Ralf Baechle Subject: [PATCH 5/7] MIPS: SGI-IP27: rework HUB interrupts Date: Thu, 24 Jan 2019 18:47:26 +0100 Message-Id: <20190124174728.28812-6-tbogendoerfer@suse.de> X-Mailer: git-send-email 2.13.7 In-Reply-To: <20190124174728.28812-1-tbogendoerfer@suse.de> References: <20190124174728.28812-1-tbogendoerfer@suse.de> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This commit rearranges the HUB interrupt code by using MIPS_IRQ_CPU interrupt handling code and modern Linux IRQ framework features to get rid of global and per cpu arrays. It also adds support for irq affinity setting. Signed-off-by: Thomas Bogendoerfer --- arch/mips/Kconfig | 1 + arch/mips/include/asm/mach-ip27/irq.h | 12 +- arch/mips/include/asm/mach-ip27/mmzone.h | 2 - arch/mips/include/asm/pci/bridge.h | 4 +- arch/mips/pci/pci-ip27.c | 18 +- arch/mips/sgi-ip27/Makefile | 3 +- arch/mips/sgi-ip27/ip27-init.c | 26 +-- arch/mips/sgi-ip27/ip27-irq-pci.c | 264 ------------------------- arch/mips/sgi-ip27/ip27-irq.c | 326 ++++++++++++++++++++++--------- arch/mips/sgi-ip27/ip27-irqno.c | 48 ----- arch/mips/sgi-ip27/ip27-timer.c | 42 +--- 11 files changed, 250 insertions(+), 496 deletions(-) delete mode 100644 arch/mips/sgi-ip27/ip27-irq-pci.c delete mode 100644 arch/mips/sgi-ip27/ip27-irqno.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0d14f51d0002..7d7f5d79af41 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -676,6 +676,7 @@ config SGI_IP27 select DEFAULT_SGI_PARTITION select SYS_HAS_EARLY_PRINTK select HAVE_PCI + select IRQ_MIPS_CPU select NR_CPUS_DEFAULT_64 select SYS_HAS_CPU_R10000 select SYS_SUPPORTS_64BIT_KERNEL diff --git a/arch/mips/include/asm/mach-ip27/irq.h b/arch/mips/include/asm/mach-ip27/irq.h index b0b7261ff3ad..fd91c58aaf7d 100644 --- a/arch/mips/include/asm/mach-ip27/irq.h +++ b/arch/mips/include/asm/mach-ip27/irq.h @@ -10,13 +10,15 @@ #ifndef __ASM_MACH_IP27_IRQ_H #define __ASM_MACH_IP27_IRQ_H -/* - * A hardwired interrupt number is completely stupid for this system - a - * large configuration might have thousands if not tenthousands of - * interrupts. - */ #define NR_IRQS 256 #include_next +#define IP27_HUB_PEND0_IRQ (MIPS_CPU_IRQ_BASE + 2) +#define IP27_HUB_PEND1_IRQ (MIPS_CPU_IRQ_BASE + 3) +#define IP27_RT_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 4) + +#define IP27_HUB_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) +#define IP27_HUB_IRQ_COUNT 128 + #endif /* __ASM_MACH_IP27_IRQ_H */ diff --git a/arch/mips/include/asm/mach-ip27/mmzone.h b/arch/mips/include/asm/mach-ip27/mmzone.h index 2ed3094dee07..8114253f5976 100644 --- a/arch/mips/include/asm/mach-ip27/mmzone.h +++ b/arch/mips/include/asm/mach-ip27/mmzone.h @@ -12,7 +12,6 @@ struct slice_data { unsigned long irq_enable_mask[2]; - int level_to_irq[LEVELS_PER_SLICE]; }; struct hub_data { @@ -20,7 +19,6 @@ struct hub_data { DECLARE_BITMAP(h_bigwin_used, HUB_NUM_BIG_WINDOW); cpumask_t h_cpus; unsigned long slice_map; - unsigned long irq_alloc_mask[2]; struct slice_data slice[2]; }; diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index 6155618ce45b..1fc60b1ae349 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h @@ -823,7 +823,6 @@ struct bridge_controller { struct bridge_regs *base; nasid_t nasid; unsigned int widget_id; - unsigned int irq_cpu; u64 baddr; unsigned int pci_int[8]; }; @@ -838,8 +837,7 @@ struct bridge_controller { #define bridge_clr(bc, reg, val) \ __raw_writel(__raw_readl(&bc->base->reg) & ~(val), &bc->base->reg) -extern void register_bridge_irq(unsigned int irq); -extern int request_bridge_irq(struct bridge_controller *bc); +extern int request_bridge_irq(struct bridge_controller *bc, int pin); extern struct pci_ops bridge_pci_ops; diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 7cf50290a6d9..3c177b4d0609 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -24,22 +24,11 @@ #define MAX_PCI_BUSSES 40 /* - * Max #PCI devices (like scsi controllers) we handle on a bus. - */ -#define MAX_DEVICES_PER_PCIBUS 8 - -/* * XXX: No kmalloc available when we do our crosstalk scan, * we should try to move it later in the boot process. */ static struct bridge_controller bridges[MAX_PCI_BUSSES]; -/* - * Translate from irq to software PCI bus number and PCI slot. - */ -struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; -int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; - extern struct pci_ops bridge_pci_ops; int bridge_probe(nasid_t nasid, int widget_id, int masterwid) @@ -77,7 +66,6 @@ int bridge_probe(nasid_t nasid, int widget_id, int masterwid) bc->io.end = ~0UL; bc->io.flags = IORESOURCE_IO; - bc->irq_cpu = smp_processor_id(); bc->widget_id = widget_id; bc->nasid = nasid; @@ -165,16 +153,12 @@ int pcibios_plat_dev_init(struct pci_dev *dev) irq = bc->pci_int[slot]; if (irq == -1) { - irq = request_bridge_irq(bc); + irq = request_bridge_irq(bc, slot); if (irq < 0) return irq; bc->pci_int[slot] = irq; } - - irq_to_bridge[irq] = bc; - irq_to_slot[irq] = slot; - dev->irq = irq; return 0; diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile index 73502fda13ee..27c14ede191e 100644 --- a/arch/mips/sgi-ip27/Makefile +++ b/arch/mips/sgi-ip27/Makefile @@ -3,10 +3,9 @@ # Makefile for the IP27 specific kernel interface routines under Linux. # -obj-y := ip27-berr.o ip27-irq.o ip27-irqno.o ip27-init.o ip27-klconfig.o \ +obj-y := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o \ ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o ip27-timer.o \ ip27-hubio.o ip27-xtalk.o obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o -obj-$(CONFIG_PCI) += ip27-irq-pci.o obj-$(CONFIG_SMP) += ip27-smp.o diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index aba985cf07c0..395c4aff9493 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -56,7 +56,6 @@ static void per_hub_init(cnodeid_t cnode) { struct hub_data *hub = hub_data(cnode); nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); - int i; cpumask_set_cpu(smp_processor_id(), &hub->h_cpus); @@ -87,24 +86,6 @@ static void per_hub_init(cnodeid_t cnode) __flush_cache_all(); } #endif - - /* - * Some interrupts are reserved by hardware or by software convention. - * Mark these as reserved right away so they won't be used accidentally - * later. - */ - for (i = 0; i <= BASE_PCI_IRQ; i++) { - __set_bit(i, hub->irq_alloc_mask); - LOCAL_HUB_CLR_INTR(INT_PEND0_BASELVL + i); - } - - __set_bit(IP_PEND0_6_63, hub->irq_alloc_mask); - LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63); - - for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) { - __set_bit(i, hub->irq_alloc_mask); - LOCAL_HUB_CLR_INTR(INT_PEND1_BASELVL + i); - } } void per_cpu_init(void) @@ -114,7 +95,6 @@ void per_cpu_init(void) cnodeid_t cnode = get_compact_nodeid(); struct hub_data *hub = hub_data(cnode); struct slice_data *si = hub->slice + slice; - int i; if (test_and_set_bit(slice, &hub->slice_map)) return; @@ -123,9 +103,6 @@ void per_cpu_init(void) per_hub_init(cnode); - for (i = 0; i < LEVELS_PER_SLICE; i++) - si->level_to_irq[i] = -1; - /* * We use this so we can find the local hub's data as fast as only * possible. @@ -138,7 +115,8 @@ void per_cpu_init(void) /* Install our NMI handler if symmon hasn't installed one. */ install_cpu_nmi_handler(cputoslice(cpu)); - set_c0_status(SRB_DEV0 | SRB_DEV1); + enable_percpu_irq(IP27_HUB_PEND0_IRQ, IRQ_TYPE_NONE); + enable_percpu_irq(IP27_HUB_PEND1_IRQ, IRQ_TYPE_NONE); } /* diff --git a/arch/mips/sgi-ip27/ip27-irq-pci.c b/arch/mips/sgi-ip27/ip27-irq-pci.c deleted file mode 100644 index a00a23b32a2a..000000000000 --- a/arch/mips/sgi-ip27/ip27-irq-pci.c +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ip27-irq.c: Highlevel interrupt handling for IP27 architecture. - * - * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - * Copyright (C) 1999 - 2001 Kanoj Sarcar - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the appropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ - -extern struct bridge_controller *irq_to_bridge[]; -extern int irq_to_slot[]; - -/* - * use these macros to get the encoded nasid and widget id - * from the irq value - */ -#define IRQ_TO_BRIDGE(i) irq_to_bridge[(i)] -#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] - -static inline int alloc_level(int cpu, int irq) -{ - struct hub_data *hub = hub_data(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - int level; - - level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); - if (level >= LEVELS_PER_SLICE) - panic("Cpu %d flooded with devices", cpu); - - __set_bit(level, hub->irq_alloc_mask); - si->level_to_irq[level] = irq; - - return level; -} - -static inline int find_level(cpuid_t *cpunum, int irq) -{ - int cpu, i; - - for_each_online_cpu(cpu) { - struct slice_data *si = cpu_data[cpu].data; - - for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++) - if (si->level_to_irq[i] == irq) { - *cpunum = cpu; - - return i; - } - } - - panic("Could not identify cpu/level for irq %d", irq); -} - -static int intr_connect_level(int cpu, int bit) -{ - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - - set_bit(bit, si->irq_enable_mask); - - if (!cputoslice(cpu)) { - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); - } else { - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); - } - - return 0; -} - -static int intr_disconnect_level(int cpu, int bit) -{ - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - - clear_bit(bit, si->irq_enable_mask); - - if (!cputoslice(cpu)) { - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); - } else { - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); - } - - return 0; -} - -/* Startup one of the (PCI ...) IRQs routes over a bridge. */ -static unsigned int startup_bridge_irq(struct irq_data *d) -{ - struct bridge_controller *bc; - int pin, swlevel; - cpuid_t cpu; - u64 device; - - pin = SLOT_FROM_PCI_IRQ(d->irq); - bc = IRQ_TO_BRIDGE(d->irq); - - pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", d->irq, pin); - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = find_level(&cpu, d->irq); - bridge_write(bc, b_int_addr[pin].addr, - (0x20000 | swlevel | (bc->nasid << 8))); - bridge_set(bc, b_int_enable, (1 << pin)); - bridge_set(bc, b_int_enable, 0x7ffffe00); /* more stuff in int_enable */ - - /* - * Enable sending of an interrupt clear packt to the hub on a high to - * low transition of the interrupt pin. - * - * IRIX sets additional bits in the address which are documented as - * reserved in the bridge docs. - */ - bridge_set(bc, b_int_mode, (1UL << pin)); - - /* - * We assume the bridge to have a 1:1 mapping between devices - * (slots) and intr pins. - */ - device = bridge_read(bc, b_int_device); - device &= ~(7 << (pin*3)); - device |= (pin << (pin*3)); - bridge_write(bc, b_int_device, device); - - bridge_read(bc, b_wid_tflush); - - intr_connect_level(cpu, swlevel); - - return 0; /* Never anything pending. */ -} - -/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ -static void shutdown_bridge_irq(struct irq_data *d) -{ - struct bridge_controller *bc = IRQ_TO_BRIDGE(d->irq); - int pin, swlevel; - cpuid_t cpu; - - pr_debug("bridge_shutdown: irq 0x%x\n", d->irq); - pin = SLOT_FROM_PCI_IRQ(d->irq); - - /* - * map irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = find_level(&cpu, d->irq); - intr_disconnect_level(cpu, swlevel); - - bridge_clr(bc, b_int_enable, (1 << pin)); - bridge_read(bc, b_wid_tflush); -} - -static inline void enable_bridge_irq(struct irq_data *d) -{ - cpuid_t cpu; - int swlevel; - - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ - intr_connect_level(cpu, swlevel); -} - -static inline void disable_bridge_irq(struct irq_data *d) -{ - cpuid_t cpu; - int swlevel; - - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ - intr_disconnect_level(cpu, swlevel); -} - -static struct irq_chip bridge_irq_type = { - .name = "bridge", - .irq_startup = startup_bridge_irq, - .irq_shutdown = shutdown_bridge_irq, - .irq_mask = disable_bridge_irq, - .irq_unmask = enable_bridge_irq, -}; - -void register_bridge_irq(unsigned int irq) -{ - irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq); -} - -int request_bridge_irq(struct bridge_controller *bc) -{ - int irq = allocate_irqno(); - int swlevel, cpu; - nasid_t nasid; - - if (irq < 0) - return irq; - - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - cpu = bc->irq_cpu; - swlevel = alloc_level(cpu, irq); - if (unlikely(swlevel < 0)) { - free_irqno(irq); - - return -EAGAIN; - } - - /* Make sure it's not already pending when we connect it. */ - nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - REMOTE_HUB_CLR_INTR(nasid, swlevel); - - intr_connect_level(cpu, swlevel); - - register_bridge_irq(irq); - - return irq; -} diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index f37155ef7ed9..a9db2f28b609 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -7,67 +7,232 @@ * Copyright (C) 1999 - 2001 Kanoj Sarcar */ -#undef DEBUG - -#include -#include -#include -#include -#include -#include #include +#include #include -#include -#include -#include #include -#include -#include #include -#include #include -#include - -#include +#include +#include #include #include #include #include #include -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the appropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ +struct hub_irq_data { + struct bridge_controller *bc; + u64 irq_mask_addr[2]; + cpuid_t cpu; + int bit; + int pin; +}; -extern asmlinkage void ip27_irq(void); +static DECLARE_BITMAP(hub_irq_map, IP27_HUB_IRQ_COUNT); -/* - * Find first bit set - */ -static int ms1bit(unsigned long x) +static inline int alloc_level(void) +{ + int level; + +again: + level = find_first_zero_bit(hub_irq_map, LEVELS_PER_SLICE); + if (level >= LEVELS_PER_SLICE) + return -ENOSPC; + + if (test_and_set_bit(level, hub_irq_map)) + goto again; + + return level; +} + +static void enable_hub_irq(struct irq_data *d) +{ + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); + struct slice_data *si = cpu_data[hd->cpu].data; + + set_bit(hd->bit, si->irq_enable_mask); + HUB_S(hd->irq_mask_addr[0], si->irq_enable_mask[0]); + HUB_S(hd->irq_mask_addr[1], si->irq_enable_mask[1]); +} + +static void disable_hub_irq(struct irq_data *d) +{ + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); + struct slice_data *si = cpu_data[hd->cpu].data; + + clear_bit(hd->bit, si->irq_enable_mask); + HUB_S(hd->irq_mask_addr[0], si->irq_enable_mask[0]); + HUB_S(hd->irq_mask_addr[1], si->irq_enable_mask[1]); +} + +static unsigned int startup_bridge_irq(struct irq_data *d) { - int b = 0, s; + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); + struct bridge_controller *bc; + nasid_t nasid; + u32 device; + int pin; + + if (!hd) + return -EINVAL; + + pin = hd->pin; + bc = hd->bc; + + nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(hd->cpu)); + bridge_write(bc, b_int_addr[pin].addr, + (0x20000 | hd->bit | (nasid << 8))); + bridge_set(bc, b_int_enable, (1 << pin)); + bridge_set(bc, b_int_enable, 0x7ffffe00); /* more stuff in int_enable */ + + /* + * Enable sending of an interrupt clear packt to the hub on a high to + * low transition of the interrupt pin. + * + * IRIX sets additional bits in the address which are documented as + * reserved in the bridge docs. + */ + bridge_set(bc, b_int_mode, (1UL << pin)); + + /* + * We assume the bridge to have a 1:1 mapping between devices + * (slots) and intr pins. + */ + device = bridge_read(bc, b_int_device); + device &= ~(7 << (pin*3)); + device |= (pin << (pin*3)); + bridge_write(bc, b_int_device, device); - s = 16; if (x >> 16 == 0) s = 0; b += s; x >>= s; - s = 8; if (x >> 8 == 0) s = 0; b += s; x >>= s; - s = 4; if (x >> 4 == 0) s = 0; b += s; x >>= s; - s = 2; if (x >> 2 == 0) s = 0; b += s; x >>= s; - s = 1; if (x >> 1 == 0) s = 0; b += s; + bridge_read(bc, b_wid_tflush); - return b; + enable_hub_irq(d); + + return 0; /* Never anything pending. */ +} + +static void shutdown_bridge_irq(struct irq_data *d) +{ + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); + struct bridge_controller *bc; + int pin = hd->pin; + + if (!hd) + return; + + disable_hub_irq(d); + + bc = hd->bc; + bridge_clr(bc, b_int_enable, (1 << pin)); + bridge_read(bc, b_wid_tflush); +} + +static void setup_hub_mask(struct hub_irq_data *hd, const struct cpumask *mask) +{ + nasid_t nasid; + int cpu; + + cpu = cpumask_first_and(mask, cpu_online_mask); + nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); + hd->cpu = cpu; + if (!cputoslice(cpu)) { + hd->irq_mask_addr[0] = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A); + hd->irq_mask_addr[1] = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A); + } else { + hd->irq_mask_addr[0] = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_B); + hd->irq_mask_addr[1] = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_B); + } + + /* Make sure it's not already pending when we connect it. */ + REMOTE_HUB_CLR_INTR(nasid, hd->bit); +} + +static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask, + bool force) +{ + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); + + if (!hd) + return -EINVAL; + + if (irqd_is_started(d)) + disable_hub_irq(d); + + setup_hub_mask(hd, mask); + + if (irqd_is_started(d)) + startup_bridge_irq(d); + + irq_data_update_effective_affinity(d, cpumask_of(hd->cpu)); + + return 0; +} + +static struct irq_chip hub_irq_type = { + .name = "HUB", + .irq_startup = startup_bridge_irq, + .irq_shutdown = shutdown_bridge_irq, + .irq_mask = disable_hub_irq, + .irq_unmask = enable_hub_irq, + .irq_set_affinity = set_affinity_hub_irq, +}; + +int request_bridge_irq(struct bridge_controller *bc, int pin) +{ + struct hub_irq_data *hd; + struct hub_data *hub; + struct irq_desc *desc; + int swlevel; + int irq; + + hd = kzalloc(sizeof(*hd), GFP_KERNEL); + if (!hd) + return -ENOMEM; + + swlevel = alloc_level(); + if (unlikely(swlevel < 0)) { + kfree(hd); + return -EAGAIN; + } + irq = swlevel + IP27_HUB_IRQ_BASE; + + hd->bc = bc; + hd->bit = swlevel; + hd->pin = pin; + irq_set_chip_data(irq, hd); + + /* use CPU connected to nearest hub */ + hub = hub_data(NASID_TO_COMPACT_NODEID(bc->nasid)); + setup_hub_mask(hd, &hub->h_cpus); + + desc = irq_to_desc(irq); + desc->irq_common_data.node = bc->nasid; + cpumask_copy(desc->irq_common_data.affinity, &hub->h_cpus); + + return irq; +} + +void ip27_hub_irq_init(void) +{ + int i; + + for (i = IP27_HUB_IRQ_BASE; + i < (IP27_HUB_IRQ_BASE + IP27_HUB_IRQ_COUNT); i++) + irq_set_chip_and_handler(i, &hub_irq_type, handle_level_irq); + + /* + * Some interrupts are reserved by hardware or by software convention. + * Mark these as reserved right away so they won't be used accidentally + * later. + */ + for (i = 0; i <= BASE_PCI_IRQ; i++) + set_bit(i, hub_irq_map); + + set_bit(IP_PEND0_6_63, hub_irq_map); + + for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) + set_bit(i, hub_irq_map); } /* @@ -82,9 +247,9 @@ static int ms1bit(unsigned long x) * Kanoj 05.13.00 */ -static void ip27_do_irq_mask0(void) +static void ip27_do_irq_mask0(struct irq_desc *desc) { - int irq, swlevel; + int swlevel; u64 pend0, mask0; cpuid_t cpu = smp_processor_id(); int pi_int_mask0 = @@ -98,7 +263,7 @@ static void ip27_do_irq_mask0(void) if (!pend0) return; - swlevel = ms1bit(pend0); + swlevel = __ffs(pend0); #ifdef CONFIG_SMP if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) { LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); @@ -119,23 +284,18 @@ static void ip27_do_irq_mask0(void) } else #endif { - /* "map" swlevel to irq */ - struct slice_data *si = cpu_data[cpu].data; - - irq = si->level_to_irq[swlevel]; - do_IRQ(irq); + do_IRQ(swlevel + IP27_HUB_IRQ_BASE); } LOCAL_HUB_L(PI_INT_PEND0); } -static void ip27_do_irq_mask1(void) +static void ip27_do_irq_mask1(struct irq_desc *desc) { - int irq, swlevel; + int swlevel; u64 pend1, mask1; cpuid_t cpu = smp_processor_id(); int pi_int_mask1 = (cputoslice(cpu) == 0) ? PI_INT_MASK1_A : PI_INT_MASK1_B; - struct slice_data *si = cpu_data[cpu].data; /* copied from Irix intpend0() */ pend1 = LOCAL_HUB_L(PI_INT_PEND1); @@ -145,62 +305,25 @@ static void ip27_do_irq_mask1(void) if (!pend1) return; - swlevel = ms1bit(pend1); - /* "map" swlevel to irq */ - irq = si->level_to_irq[swlevel]; - LOCAL_HUB_CLR_INTR(swlevel); - do_IRQ(irq); + swlevel = __ffs(pend1); + do_IRQ(swlevel + IP27_HUB_IRQ_BASE + 64); LOCAL_HUB_L(PI_INT_PEND1); } -static void ip27_prof_timer(void) -{ - panic("CPU %d got a profiling interrupt", smp_processor_id()); -} - -static void ip27_hub_error(void) -{ - panic("CPU %d got a hub error interrupt", smp_processor_id()); -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned long pending = read_c0_cause() & read_c0_status(); - extern unsigned int rt_timer_irq; - - if (pending & CAUSEF_IP4) - do_IRQ(rt_timer_irq); - else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */ - ip27_do_irq_mask0(); - else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */ - ip27_do_irq_mask1(); - else if (pending & CAUSEF_IP5) - ip27_prof_timer(); - else if (pending & CAUSEF_IP6) - ip27_hub_error(); -} - -void __init arch_init_irq(void) -{ -} - void install_ipi(void) { int slice = LOCAL_HUB_L(PI_CPU_NUM); int cpu = smp_processor_id(); struct slice_data *si = cpu_data[cpu].data; - struct hub_data *hub = hub_data(cpu_to_node(cpu)); int resched, call; resched = CPU_RESCHED_A_IRQ + slice; - __set_bit(resched, hub->irq_alloc_mask); - __set_bit(resched, si->irq_enable_mask); + set_bit(resched, si->irq_enable_mask); LOCAL_HUB_CLR_INTR(resched); call = CPU_CALL_A_IRQ + slice; - __set_bit(call, hub->irq_alloc_mask); - __set_bit(call, si->irq_enable_mask); + set_bit(call, si->irq_enable_mask); LOCAL_HUB_CLR_INTR(call); if (slice == 0) { @@ -211,3 +334,14 @@ void install_ipi(void) LOCAL_HUB_S(PI_INT_MASK1_B, si->irq_enable_mask[1]); } } + +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(); + ip27_hub_irq_init(); + + irq_set_percpu_devid(IP27_HUB_PEND0_IRQ); + irq_set_chained_handler(IP27_HUB_PEND0_IRQ, ip27_do_irq_mask0); + irq_set_percpu_devid(IP27_HUB_PEND1_IRQ); + irq_set_chained_handler(IP27_HUB_PEND1_IRQ, ip27_do_irq_mask1); +} diff --git a/arch/mips/sgi-ip27/ip27-irqno.c b/arch/mips/sgi-ip27/ip27-irqno.c deleted file mode 100644 index 957ab58e1c00..000000000000 --- a/arch/mips/sgi-ip27/ip27-irqno.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include - -#include - -static DECLARE_BITMAP(irq_map, NR_IRQS); - -int allocate_irqno(void) -{ - int irq; - -again: - irq = find_first_zero_bit(irq_map, NR_IRQS); - - if (irq >= NR_IRQS) - return -ENOSPC; - - if (test_and_set_bit(irq, irq_map)) - goto again; - - return irq; -} - -/* - * Allocate the 16 legacy interrupts for i8259 devices. This happens early - * in the kernel initialization so treating allocation failure as BUG() is - * ok. - */ -void __init alloc_legacy_irqno(void) -{ - int i; - - for (i = 0; i <= 16; i++) - BUG_ON(test_and_set_bit(i, irq_map)); -} - -void free_irqno(unsigned int irq) -{ - smp_mb__before_atomic(); - clear_bit(irq, irq_map); - smp_mb__after_atomic(); -} diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 9d55247533a5..9b4b9ac621a3 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -38,20 +38,6 @@ #include #include -static void enable_rt_irq(struct irq_data *d) -{ -} - -static void disable_rt_irq(struct irq_data *d) -{ -} - -static struct irq_chip rt_irq_type = { - .name = "SN HUB RT timer", - .irq_mask = disable_rt_irq, - .irq_unmask = enable_rt_irq, -}; - static int rt_next_event(unsigned long delta, struct clock_event_device *evt) { unsigned int cpu = smp_processor_id(); @@ -65,8 +51,6 @@ static int rt_next_event(unsigned long delta, struct clock_event_device *evt) return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; } -unsigned int rt_timer_irq; - static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent); static DEFINE_PER_CPU(char [11], hub_rt_name); @@ -87,6 +71,7 @@ static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) struct irqaction hub_rt_irqaction = { .handler = hub_rt_counter_handler, + .percpu_dev_id = &hub_rt_clockevent, .flags = IRQF_PERCPU | IRQF_TIMER, .name = "hub-rt", }; @@ -107,7 +92,6 @@ void hub_rt_clock_event_init(void) unsigned int cpu = smp_processor_id(); struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); unsigned char *name = per_cpu(hub_rt_name, cpu); - int irq = rt_timer_irq; sprintf(name, "hub-rt %d", cpu); cd->name = name; @@ -118,29 +102,19 @@ void hub_rt_clock_event_init(void) cd->min_delta_ns = clockevent_delta2ns(0x300, cd); cd->min_delta_ticks = 0x300; cd->rating = 200; - cd->irq = irq; + cd->irq = IP27_RT_TIMER_IRQ; cd->cpumask = cpumask_of(cpu); cd->set_next_event = rt_next_event; clockevents_register_device(cd); + + enable_percpu_irq(IP27_RT_TIMER_IRQ, IRQ_TYPE_NONE); } static void __init hub_rt_clock_event_global_init(void) { - int irq; - - do { - smp_wmb(); - irq = rt_timer_irq; - if (irq) - break; - - irq = allocate_irqno(); - if (irq < 0) - panic("Allocation of irq number for timer failed"); - } while (xchg(&rt_timer_irq, irq)); - - irq_set_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); - setup_irq(irq, &hub_rt_irqaction); + irq_set_handler(IP27_RT_TIMER_IRQ, handle_percpu_devid_irq); + irq_set_percpu_devid(IP27_RT_TIMER_IRQ); + setup_percpu_irq(IP27_RT_TIMER_IRQ, &hub_rt_irqaction); } static u64 hub_rt_read(struct clocksource *cs) @@ -194,8 +168,6 @@ void cpu_time_init(void) panic("No information about myself?"); printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); - - set_c0_status(SRB_TIMOCLK); } void hub_rtc_init(cnodeid_t cnode) From patchwork Thu Jan 24 17:47:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Bogendoerfer X-Patchwork-Id: 10779695 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 55BBC1823 for ; Thu, 24 Jan 2019 17:48:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 49916326B3 for ; Thu, 24 Jan 2019 17:48:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3DDA2326B6; Thu, 24 Jan 2019 17:48:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.4 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,SORTED_RECIPS autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A1DDD3264E for ; Thu, 24 Jan 2019 17:48:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729215AbfAXRsQ (ORCPT ); Thu, 24 Jan 2019 12:48:16 -0500 Received: from mx2.suse.de ([195.135.220.15]:51378 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729006AbfAXRrs (ORCPT ); Thu, 24 Jan 2019 12:47:48 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 7720FB0E0; Thu, 24 Jan 2019 17:47:45 +0000 (UTC) From: Thomas Bogendoerfer To: Bjorn Helgaas , James Hogan , linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org, linux-pci@vger.kernel.org, Lorenzo Pieralisi , Paul Burton , Ralf Baechle Subject: [PATCH 6/7] MIPS: SGI-IP27: use generic PCI driver Date: Thu, 24 Jan 2019 18:47:27 +0100 Message-Id: <20190124174728.28812-7-tbogendoerfer@suse.de> X-Mailer: git-send-email 2.13.7 In-Reply-To: <20190124174728.28812-1-tbogendoerfer@suse.de> References: <20190124174728.28812-1-tbogendoerfer@suse.de> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Converted bridge code to a platform driver using the PCI generic driver framework and use adding platform devices during xtalk scan. This allows easier sharing bridge drvier for other SGI platforms like IP30 (Octane) and IP35 (Origin 3k, Fuel, Tezro). Signed-off-by: Thomas Bogendoerfer --- arch/mips/Kconfig | 2 + arch/mips/include/asm/pci/bridge.h | 6 +- arch/mips/include/asm/xtalk/xtalk.h | 9 - arch/mips/pci/Makefile | 1 - arch/mips/pci/pci-ip27.c | 214 --------------- arch/mips/sgi-ip27/ip27-init.c | 2 + arch/mips/sgi-ip27/ip27-xtalk.c | 31 ++- drivers/pci/controller/Kconfig | 3 + drivers/pci/controller/Makefile | 1 + .../pci/controller/pci-xtalk-bridge.c | 288 +++++++++++++++++---- include/linux/platform_data/xtalk-bridge.h | 17 ++ 11 files changed, 286 insertions(+), 288 deletions(-) delete mode 100644 arch/mips/pci/pci-ip27.c rename arch/mips/pci/ops-bridge.c => drivers/pci/controller/pci-xtalk-bridge.c (51%) create mode 100644 include/linux/platform_data/xtalk-bridge.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 7d7f5d79af41..f2f258abee59 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -678,6 +678,8 @@ config SGI_IP27 select HAVE_PCI select IRQ_MIPS_CPU select NR_CPUS_DEFAULT_64 + select PCI_DRIVERS_GENERIC + select PCI_XTALK_BRIDGE select SYS_HAS_CPU_R10000 select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index 1fc60b1ae349..af2da166815e 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h @@ -816,15 +816,13 @@ struct bridge_err_cmdword { #define PCI64_ATTR_RMF_SHFT 48 struct bridge_controller { - struct pci_controller pc; struct resource mem; struct resource io; struct resource busn; struct bridge_regs *base; - nasid_t nasid; - unsigned int widget_id; u64 baddr; unsigned int pci_int[8]; + nasid_t nasid; }; #define BRIDGE_CONTROLLER(bus) \ @@ -839,6 +837,4 @@ struct bridge_controller { extern int request_bridge_irq(struct bridge_controller *bc, int pin); -extern struct pci_ops bridge_pci_ops; - #endif /* _ASM_PCI_BRIDGE_H */ diff --git a/arch/mips/include/asm/xtalk/xtalk.h b/arch/mips/include/asm/xtalk/xtalk.h index 26d2ed1fa917..680e7efebbaf 100644 --- a/arch/mips/include/asm/xtalk/xtalk.h +++ b/arch/mips/include/asm/xtalk/xtalk.h @@ -47,15 +47,6 @@ typedef struct xtalk_piomap_s *xtalk_piomap_t; #define XIO_PORT(x) ((xwidgetnum_t)(((x)&XIO_PORT_BITS) >> XIO_PORT_SHIFT)) #define XIO_PACK(p, o) ((((uint64_t)(p))< -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Max #PCI busses we can handle; ie, max #PCI bridges. - */ -#define MAX_PCI_BUSSES 40 - -/* - * XXX: No kmalloc available when we do our crosstalk scan, - * we should try to move it later in the boot process. - */ -static struct bridge_controller bridges[MAX_PCI_BUSSES]; - -extern struct pci_ops bridge_pci_ops; - -int bridge_probe(nasid_t nasid, int widget_id, int masterwid) -{ - unsigned long offset = NODE_OFFSET(nasid); - struct bridge_controller *bc; - static int num_bridges = 0; - int slot; - - pci_set_flags(PCI_PROBE_ONLY); - - printk("a bridge\n"); - - /* XXX: kludge alert.. */ - if (!num_bridges) - ioport_resource.end = ~0UL; - - bc = &bridges[num_bridges]; - - bc->pc.pci_ops = &bridge_pci_ops; - bc->pc.mem_resource = &bc->mem; - bc->pc.io_resource = &bc->io; - - bc->pc.index = num_bridges; - - bc->mem.name = "Bridge PCI MEM"; - bc->pc.mem_offset = offset; - bc->mem.start = 0; - bc->mem.end = ~0UL; - bc->mem.flags = IORESOURCE_MEM; - - bc->io.name = "Bridge IO MEM"; - bc->pc.io_offset = offset; - bc->io.start = 0UL; - bc->io.end = ~0UL; - bc->io.flags = IORESOURCE_IO; - - bc->widget_id = widget_id; - bc->nasid = nasid; - - bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR; - - /* - * point to this bridge - */ - bc->base = (struct bridge_regs *)RAW_NODE_SWIN_BASE(nasid, widget_id); - - /* - * Clear all pending interrupts. - */ - bridge_write(bc, b_int_rst_stat, BRIDGE_IRR_ALL_CLR); - - /* - * Until otherwise set up, assume all interrupts are from slot 0 - */ - bridge_write(bc, b_int_device, 0x0); - - /* - * swap pio's to pci mem and io space (big windows) - */ - bridge_set(bc, b_wid_control, BRIDGE_CTRL_IO_SWAP | - BRIDGE_CTRL_MEM_SWAP); -#ifdef CONFIG_PAGE_SIZE_4KB - bridge_clr(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); -#else /* 16kB or larger */ - bridge_set(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); -#endif - - /* - * Hmm... IRIX sets additional bits in the address which - * are documented as reserved in the bridge docs. - */ - bridge_write(bc, b_wid_int_upper, 0x8000 | (masterwid << 16)); - bridge_write(bc, b_wid_int_lower, 0x01800090); /* PI_INT_PEND_MOD off*/ - bridge_write(bc, b_dir_map, (masterwid << 20)); /* DMA */ - bridge_write(bc, b_int_enable, 0); - - for (slot = 0; slot < 8; slot ++) { - bridge_set(bc, b_device[slot].reg, BRIDGE_DEV_SWAP_DIR); - bc->pci_int[slot] = -1; - } - bridge_read(bc, b_wid_tflush); /* wait until Bridge PIO complete */ - - register_pci_controller(&bc->pc); - - num_bridges++; - - return 0; -} - -/* - * All observed requests have pin == 1. We could have a global here, that - * gets incremented and returned every time - unfortunately, pci_map_irq - * may be called on the same device over and over, and need to return the - * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. - * - * A given PCI device, in general, should be able to intr any of the cpus - * on any one of the hubs connected to its xbow. - */ -int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - return 0; -} - -static inline struct pci_dev *bridge_root_dev(struct pci_dev *dev) -{ - while (dev->bus->parent) { - /* Move up the chain of bridges. */ - dev = dev->bus->self; - } - - return dev; -} - -/* Do platform specific device initialization at pci_enable_device() time */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); - struct pci_dev *rdev = bridge_root_dev(dev); - int slot = PCI_SLOT(rdev->devfn); - int irq; - - irq = bc->pci_int[slot]; - if (irq == -1) { - irq = request_bridge_irq(bc, slot); - if (irq < 0) - return irq; - - bc->pci_int[slot] = irq; - } - dev->irq = irq; - - return 0; -} - -dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct bridge_controller *bc = BRIDGE_CONTROLLER(pdev->bus); - - return bc->baddr + paddr; -} - -phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dma_addr) -{ - return dma_addr & ~(0xffUL << 56); -} - -/* - * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses - * to find the slot number in sense of the bridge device register. - * XXX This also means multiple devices might rely on conflicting bridge - * settings. - */ - -static inline void pci_disable_swapping(struct pci_dev *dev) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); - struct bridge_regs *bridge = bc->base; - int slot = PCI_SLOT(dev->devfn); - - /* Turn off byte swapping */ - bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR; - bridge->b_widget.w_tflush; /* Flush */ -} - -static void pci_fixup_ioc3(struct pci_dev *d) -{ - pci_disable_swapping(d); -} - -#ifdef CONFIG_NUMA -int pcibus_to_node(struct pci_bus *bus) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); - - return bc->nasid; -} -EXPORT_SYMBOL(pcibus_to_node); -#endif /* CONFIG_NUMA */ - -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, - pci_fixup_ioc3); diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 395c4aff9493..752c7ada3abd 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -192,5 +192,7 @@ void __init plat_mem_setup(void) ioc3_eth_init(); per_cpu_init(); + ioport_resource.end = 0; + ioport_resource.end = ~0UL; set_io_port_base(IO_BASE); } diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index ce06aaa115ae..8579b651d862 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -9,6 +9,8 @@ #include #include +#include +#include #include #include #include @@ -20,7 +22,19 @@ #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbow in Xbridge */ #define BASE_XBOW_PORT 8 /* Lowest external port */ -extern int bridge_probe(nasid_t nasid, int widget, int masterwid); +static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) +{ + struct platform_device *pdev; + struct xtalk_bridge_platform_data bridge_data; + + pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO); + bridge_data.nasid = nasid; + bridge_data.widget = widget; + bridge_data.masterwid = masterwid; + platform_device_add_data(pdev, &bridge_data, sizeof(bridge_data)); + platform_device_add(pdev); + pr_info("xtalk:n%d/%x bridge widget\n", nasid, widget); +} static int probe_one_port(nasid_t nasid, int widget, int masterwid) { @@ -31,13 +45,10 @@ static int probe_one_port(nasid_t nasid, int widget, int masterwid) (RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); - printk(KERN_INFO "Cpu %d, Nasid 0x%x, widget 0x%x (partnum 0x%x) is ", - smp_processor_id(), nasid, widget, partnum); - switch (partnum) { case BRIDGE_WIDGET_PART_NUM: case XBRIDGE_WIDGET_PART_NUM: - bridge_probe(nasid, widget, masterwid); + bridge_platform_create(nasid, widget, masterwid); break; default: break; @@ -52,8 +63,6 @@ static int xbow_probe(nasid_t nasid) klxbow_t *xbow_p; unsigned masterwid, i; - printk("is xbow\n"); - /* * found xbow, so may have multiple bridges * need to probe xbow @@ -117,19 +126,17 @@ static void xtalk_probe_node(cnodeid_t nid) (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); - printk(KERN_INFO "Cpu %d, Nasid 0x%x: partnum 0x%x is ", - smp_processor_id(), nasid, partnum); - switch (partnum) { case BRIDGE_WIDGET_PART_NUM: - bridge_probe(nasid, 0x8, 0xa); + bridge_platform_create(nasid, 0x8, 0xa); break; case XBOW_WIDGET_PART_NUM: case XXBOW_WIDGET_PART_NUM: + pr_info("xtalk:n%d/0 xbow widget\n", nasid); xbow_probe(nasid); break; default: - printk(" unknown widget??\n"); + pr_info("xtalk:n%d/0 unknown widget (0x%x)\n", nasid, partnum); break; } } diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig index 6671946dbf66..c3815353f2f8 100644 --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig @@ -265,6 +265,9 @@ config PCIE_TANGO_SMP8759 This can lead to data corruption if drivers perform concurrent config and MMIO accesses. +config PCI_XTALK_BRIDGE + bool + config VMD depends on PCI_MSI && X86_64 && SRCU tristate "Intel Volume Management Device Driver" diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile index d56a507495c5..bcbd740f878c 100644 --- a/drivers/pci/controller/Makefile +++ b/drivers/pci/controller/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o +obj-$(CONFIG_PCI_XTALK_BRIDGE) += pci-xtalk-bridge.o obj-$(CONFIG_VMD) += vmd.o # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW obj-y += dwc/ diff --git a/arch/mips/pci/ops-bridge.c b/drivers/pci/controller/pci-xtalk-bridge.c similarity index 51% rename from arch/mips/pci/ops-bridge.c rename to drivers/pci/controller/pci-xtalk-bridge.c index df95b0da08f2..b90fbec8f891 100644 --- a/arch/mips/pci/ops-bridge.c +++ b/drivers/pci/controller/pci-xtalk-bridge.c @@ -3,13 +3,21 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1999, 2000, 04, 06 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2003 Christoph Hellwig (hch@lst.de) + * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ +#include +#include #include -#include -#include +#include +#include +#include +#include + #include +#include +#include #include #include @@ -29,6 +37,20 @@ static u32 emulate_ioc3_cfg(int where, int size) return 0; } +static void bridge_disable_swapping(struct pci_dev *dev) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); + int slot = PCI_SLOT(dev->devfn); + + /* Turn off byte swapping */ + bridge_clr(bc, b_device[slot].reg, BRIDGE_DEV_SWAP_DIR); + bridge_read(bc, b_widget.w_tflush); /* Flush */ +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, + bridge_disable_swapping); + + /* * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is * not really documented, so right now I can't write code which uses it. @@ -39,20 +61,19 @@ static u32 emulate_ioc3_cfg(int where, int size) * which is used in SGI systems. The IOC3 can only handle 32-bit PCI * accesses and does only decode parts of it's address space. */ - static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * value) + int where, int size, u32 *value) { struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); struct bridge_regs *bridge = bc->base; int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); - volatile void *addr; + void *addr; u32 cf, shift, mask; int res; addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; - if (get_dbe(cf, (u32 *) addr)) + if (get_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; /* @@ -65,11 +86,11 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; if (size == 1) - res = get_dbe(*value, (u8 *) addr); + res = get_dbe(*value, (u8 *)addr); else if (size == 2) - res = get_dbe(*value, (u16 *) addr); + res = get_dbe(*value, (u16 *)addr); else - res = get_dbe(*value, (u32 *) addr); + res = get_dbe(*value, (u32 *)addr); return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; @@ -84,8 +105,7 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, } addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; - - if (get_dbe(cf, (u32 *) addr)) + if (get_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; shift = ((where & 3) << 3); @@ -96,20 +116,20 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, } static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * value) + int where, int size, u32 *value) { struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); struct bridge_regs *bridge = bc->base; int busno = bus->number; int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); - volatile void *addr; + void *addr; u32 cf, shift, mask; int res; bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; - if (get_dbe(cf, (u32 *) addr)) + if (get_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; /* @@ -119,15 +139,14 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) goto is_ioc3; - bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; if (size == 1) - res = get_dbe(*value, (u8 *) addr); + res = get_dbe(*value, (u8 *)addr); else if (size == 2) - res = get_dbe(*value, (u16 *) addr); + res = get_dbe(*value, (u16 *)addr); else - res = get_dbe(*value, (u32 *) addr); + res = get_dbe(*value, (u32 *)addr); return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; @@ -141,10 +160,8 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_SUCCESSFUL; } - bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; - - if (get_dbe(cf, (u32 *) addr)) + if (get_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; shift = ((where & 3) << 3); @@ -155,7 +172,7 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, } static int pci_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * value) + int where, int size, u32 *value) { if (!pci_is_root_bus(bus)) return pci_conf1_read_config(bus, devfn, where, size, value); @@ -170,12 +187,12 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, struct bridge_regs *bridge = bc->base; int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); - volatile void *addr; + void *addr; u32 cf, shift, mask, smask; int res; addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; - if (get_dbe(cf, (u32 *) addr)) + if (get_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; /* @@ -187,13 +204,12 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; - if (size == 1) { - res = put_dbe(value, (u8 *) addr); - } else if (size == 2) { - res = put_dbe(value, (u16 *) addr); - } else { - res = put_dbe(value, (u32 *) addr); - } + if (size == 1) + res = put_dbe(value, (u8 *)addr); + else if (size == 2) + res = put_dbe(value, (u16 *)addr); + else + res = put_dbe(value, (u32 *)addr); if (res) return PCIBIOS_DEVICE_NOT_FOUND; @@ -210,7 +226,7 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; - if (get_dbe(cf, (u32 *) addr)) + if (get_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; shift = ((where & 3) << 3); @@ -218,7 +234,7 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, smask = mask << shift; cf = (cf & ~smask) | ((value & mask) << shift); - if (put_dbe(cf, (u32 *) addr)) + if (put_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_SUCCESSFUL; @@ -232,13 +248,13 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, int slot = PCI_SLOT(devfn); int fn = PCI_FUNC(devfn); int busno = bus->number; - volatile void *addr; + void *addr; u32 cf, shift, mask, smask; int res; bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11)); addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; - if (get_dbe(cf, (u32 *) addr)) + if (get_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; /* @@ -250,13 +266,12 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; - if (size == 1) { - res = put_dbe(value, (u8 *) addr); - } else if (size == 2) { - res = put_dbe(value, (u16 *) addr); - } else { - res = put_dbe(value, (u32 *) addr); - } + if (size == 1) + res = put_dbe(value, (u8 *)addr); + else if (size == 2) + res = put_dbe(value, (u16 *)addr); + else + res = put_dbe(value, (u32 *)addr); if (res) return PCIBIOS_DEVICE_NOT_FOUND; @@ -272,8 +287,7 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_SUCCESSFUL; addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; - - if (get_dbe(cf, (u32 *) addr)) + if (get_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; shift = ((where & 3) << 3); @@ -281,7 +295,7 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, smask = mask << shift; cf = (cf & ~smask) | ((value & mask) << shift); - if (put_dbe(cf, (u32 *) addr)) + if (put_dbe(cf, (u32 *)addr)) return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_SUCCESSFUL; @@ -296,7 +310,187 @@ static int pci_write_config(struct pci_bus *bus, unsigned int devfn, return pci_conf0_write_config(bus, devfn, where, size, value); } -struct pci_ops bridge_pci_ops = { +static struct pci_ops bridge_pci_ops = { .read = pci_read_config, .write = pci_write_config, }; + +#ifdef CONFIG_NUMA +int pcibus_to_node(struct pci_bus *bus) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + + return bc->nasid; +} +EXPORT_SYMBOL(pcibus_to_node); +#endif /* CONFIG_NUMA */ + +/* + * All observed requests have pin == 1. We could have a global here, that + * gets incremented and returned every time - unfortunately, pci_map_irq + * may be called on the same device over and over, and need to return the + * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. + * + * A given PCI device, in general, should be able to intr any of the cpus + * on any one of the hubs connected to its xbow. + */ +static int bridge_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); + int irq; + + irq = bc->pci_int[slot]; + if (irq == -1) { + irq = request_bridge_irq(bc, slot); + if (irq < 0) + return irq; + + bc->pci_int[slot] = irq; + } + return irq; +} + +dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct bridge_controller *bc = BRIDGE_CONTROLLER(pdev->bus); + + return bc->baddr + paddr; +} + +phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dma_addr) +{ + return dma_addr & ~(0xffUL << 56); +} + +static int bridge_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct bridge_controller *bc; + struct pci_host_bridge *host; + unsigned long offset; + int slot; + int err; + struct xtalk_bridge_platform_data *bd = dev_get_platdata(&pdev->dev); + + offset = NODE_OFFSET(bd->nasid); + + pci_set_flags(PCI_PROBE_ONLY); + + host = devm_pci_alloc_host_bridge(dev, sizeof(*bc)); + if (!host) + return -ENOMEM; + + bc = pci_host_bridge_priv(host); + + bc->mem.name = "Bridge PCI MEM"; + bc->mem.start = offset + (bd->widget << SWIN_SIZE_BITS); + bc->mem.end = bc->mem.start + SWIN_SIZE; + bc->mem.flags = IORESOURCE_MEM; + + bc->io.name = "Bridge PCI IO"; + bc->io.start = offset + (bd->widget << SWIN_SIZE_BITS); + bc->io.end = bc->io.start + SWIN_SIZE; + bc->io.flags = IORESOURCE_IO; + + bc->busn.name = "Bridge PCI busn"; + bc->busn.start = 0; + bc->busn.end = 0xff; + bc->busn.flags = IORESOURCE_BUS; + + pci_add_resource_offset(&host->windows, &bc->mem, offset); + pci_add_resource_offset(&host->windows, &bc->io, offset); + pci_add_resource(&host->windows, &bc->busn); + + err = devm_request_pci_bus_resources(dev, &host->windows); + if (err < 0) { + pci_free_resource_list(&host->windows); + return err; + } + + bc->nasid = bd->nasid; + + bc->baddr = (u64)bd->masterwid << 60 | PCI64_ATTR_BAR; + + /* + * point to this bridge + */ + bc->base = (struct bridge_regs *)RAW_NODE_SWIN_BASE(bd->nasid, + bd->widget); + + /* + * Clear all pending interrupts. + */ + bridge_write(bc, b_int_rst_stat, BRIDGE_IRR_ALL_CLR); + + /* + * Until otherwise set up, assume all interrupts are from slot 0 + */ + bridge_write(bc, b_int_device, 0x0); + + /* + * disable swapping for big windows + */ + bridge_clr(bc, b_wid_control, + BRIDGE_CTRL_IO_SWAP | BRIDGE_CTRL_MEM_SWAP); +#ifdef CONFIG_PAGE_SIZE_4KB + bridge_clr(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); +#else /* 16kB or larger */ + bridge_set(bc, b_wid_control, BRIDGE_CTRL_PAGE_SIZE); +#endif + + /* + * Hmm... IRIX sets additional bits in the address which + * are documented as reserved in the bridge docs. + */ + bridge_write(bc, b_wid_int_upper, 0x8000 | (bd->masterwid << 16)); + bridge_write(bc, b_wid_int_lower, 0x01800090); /* PI_INT_PEND_MOD off*/ + bridge_write(bc, b_dir_map, (bd->masterwid << 20)); /* DMA */ + bridge_write(bc, b_int_enable, 0); + + for (slot = 0; slot < 8; slot++) { + bridge_set(bc, b_device[slot].reg, BRIDGE_DEV_SWAP_DIR); + bc->pci_int[slot] = -1; + } + bridge_read(bc, b_wid_tflush); /* wait until Bridge PIO complete */ + + host->dev.parent = dev; + host->sysdata = bc; + host->busnr = 0; + host->ops = &bridge_pci_ops; + host->map_irq = bridge_map_irq; + host->swizzle_irq = pci_common_swizzle; + + err = pci_scan_root_bus_bridge(host); + if (err < 0) + return err; + + pci_bus_claim_resources(host->bus); + pci_bus_add_devices(host->bus); + + platform_set_drvdata(pdev, host->bus); + + return 0; +} + +static int bridge_remove(struct platform_device *pdev) +{ + struct pci_bus *bus = platform_get_drvdata(pdev); + + pci_lock_rescan_remove(); + pci_stop_root_bus(bus); + pci_remove_root_bus(bus); + pci_unlock_rescan_remove(); + + return 0; +} + +static struct platform_driver bridge_driver = { + .probe = bridge_probe, + .remove = bridge_remove, + .driver = { + .name = "xtalk-bridge", + } +}; + +builtin_platform_driver(bridge_driver); diff --git a/include/linux/platform_data/xtalk-bridge.h b/include/linux/platform_data/xtalk-bridge.h new file mode 100644 index 000000000000..818d4b457429 --- /dev/null +++ b/include/linux/platform_data/xtalk-bridge.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * SGI PCI Xtalk Bridge + */ + +#ifndef PLATFORM_DATA_XTALK_BRIDGE_H +#define PLATFORM_DATA_XTALK_BRIDGE_H + +#include + +struct xtalk_bridge_platform_data { + nasid_t nasid; + int widget; + int masterwid; +}; + +#endif /* PLATFORM_DATA_XTALK_BRIDGE_H */ From patchwork Thu Jan 24 17:47:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Bogendoerfer X-Patchwork-Id: 10779687 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0C6611515 for ; Thu, 24 Jan 2019 17:48:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F3A82326AA for ; Thu, 24 Jan 2019 17:48:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E6829326B6; Thu, 24 Jan 2019 17:48:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.4 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,SORTED_RECIPS autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C4694326AA for ; Thu, 24 Jan 2019 17:48:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728650AbfAXRrz (ORCPT ); Thu, 24 Jan 2019 12:47:55 -0500 Received: from mx2.suse.de ([195.135.220.15]:51374 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729005AbfAXRrt (ORCPT ); Thu, 24 Jan 2019 12:47:49 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 7C20EB0E2; Thu, 24 Jan 2019 17:47:45 +0000 (UTC) From: Thomas Bogendoerfer To: Bjorn Helgaas , James Hogan , linux-kernel@vger.kernel.org, linux-mips@vger.kernel.org, linux-pci@vger.kernel.org, Lorenzo Pieralisi , Paul Burton , Ralf Baechle Subject: [PATCH 7/7] MIPS: SGI-IP27: abstract chipset irq from bridge Date: Thu, 24 Jan 2019 18:47:28 +0100 Message-Id: <20190124174728.28812-8-tbogendoerfer@suse.de> X-Mailer: git-send-email 2.13.7 In-Reply-To: <20190124174728.28812-1-tbogendoerfer@suse.de> References: <20190124174728.28812-1-tbogendoerfer@suse.de> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Bridge ASIC is widely used in different SGI systems, but the connected chipset is either HUB, HEART or BEDROCK. This commit abstracts chipset irq setup and moves the bridge related irq setup to bridge code. Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/pci/bridge.h | 2 - arch/mips/include/asm/sn/intr.h | 7 ++++ arch/mips/sgi-ip27/ip27-irq.c | 67 ++++++++----------------------- drivers/pci/controller/pci-xtalk-bridge.c | 64 ++++++++++++++++++++++++++++- 4 files changed, 87 insertions(+), 53 deletions(-) diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index af2da166815e..9b13bda5c3f6 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h @@ -835,6 +835,4 @@ struct bridge_controller { #define bridge_clr(bc, reg, val) \ __raw_writel(__raw_readl(&bc->base->reg) & ~(val), &bc->base->reg) -extern int request_bridge_irq(struct bridge_controller *bc, int pin); - #endif /* _ASM_PCI_BRIDGE_H */ diff --git a/arch/mips/include/asm/sn/intr.h b/arch/mips/include/asm/sn/intr.h index fc1348193957..9c9f2e883a71 100644 --- a/arch/mips/include/asm/sn/intr.h +++ b/arch/mips/include/asm/sn/intr.h @@ -126,4 +126,11 @@ do { \ #define NI_ERROR_INTR 62 #define MSC_PANIC_INTR 63 +struct irq_source_ops { + void (*start_irq_source)(cpuid_t cpu, int bit, void *d); + void (*stop_irq_source)(cpuid_t cpu, int bit, void *d); +}; + +extern int request_chipset_irq(struct irq_source_ops *o, void *d, nasid_t n); + #endif /* __ASM_SN_INTR_H */ diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index a9db2f28b609..cac5f6956048 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -12,10 +12,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -23,11 +23,11 @@ #include struct hub_irq_data { - struct bridge_controller *bc; + struct irq_source_ops *isrc_ops; + void *isrc_data; u64 irq_mask_addr[2]; cpuid_t cpu; int bit; - int pin; }; static DECLARE_BITMAP(hub_irq_map, IP27_HUB_IRQ_COUNT); @@ -67,65 +67,32 @@ static void disable_hub_irq(struct irq_data *d) HUB_S(hd->irq_mask_addr[1], si->irq_enable_mask[1]); } -static unsigned int startup_bridge_irq(struct irq_data *d) +static unsigned int startup_hub_irq(struct irq_data *d) { struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); - struct bridge_controller *bc; - nasid_t nasid; - u32 device; - int pin; if (!hd) return -EINVAL; - pin = hd->pin; - bc = hd->bc; - - nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(hd->cpu)); - bridge_write(bc, b_int_addr[pin].addr, - (0x20000 | hd->bit | (nasid << 8))); - bridge_set(bc, b_int_enable, (1 << pin)); - bridge_set(bc, b_int_enable, 0x7ffffe00); /* more stuff in int_enable */ - - /* - * Enable sending of an interrupt clear packt to the hub on a high to - * low transition of the interrupt pin. - * - * IRIX sets additional bits in the address which are documented as - * reserved in the bridge docs. - */ - bridge_set(bc, b_int_mode, (1UL << pin)); - - /* - * We assume the bridge to have a 1:1 mapping between devices - * (slots) and intr pins. - */ - device = bridge_read(bc, b_int_device); - device &= ~(7 << (pin*3)); - device |= (pin << (pin*3)); - bridge_write(bc, b_int_device, device); - - bridge_read(bc, b_wid_tflush); + if (hd->isrc_ops && hd->isrc_ops->start_irq_source) + hd->isrc_ops->start_irq_source(hd->cpu, hd->bit, hd->isrc_data); enable_hub_irq(d); return 0; /* Never anything pending. */ } -static void shutdown_bridge_irq(struct irq_data *d) +static void shutdown_hub_irq(struct irq_data *d) { struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); - struct bridge_controller *bc; - int pin = hd->pin; if (!hd) return; disable_hub_irq(d); - bc = hd->bc; - bridge_clr(bc, b_int_enable, (1 << pin)); - bridge_read(bc, b_wid_tflush); + if (hd->isrc_ops && hd->isrc_ops->stop_irq_source) + hd->isrc_ops->stop_irq_source(hd->cpu, hd->bit, hd->isrc_data); } static void setup_hub_mask(struct hub_irq_data *hd, const struct cpumask *mask) @@ -162,7 +129,7 @@ static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask, setup_hub_mask(hd, mask); if (irqd_is_started(d)) - startup_bridge_irq(d); + startup_hub_irq(d); irq_data_update_effective_affinity(d, cpumask_of(hd->cpu)); @@ -171,14 +138,14 @@ static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask, static struct irq_chip hub_irq_type = { .name = "HUB", - .irq_startup = startup_bridge_irq, - .irq_shutdown = shutdown_bridge_irq, + .irq_startup = startup_hub_irq, + .irq_shutdown = shutdown_hub_irq, .irq_mask = disable_hub_irq, .irq_unmask = enable_hub_irq, .irq_set_affinity = set_affinity_hub_irq, }; -int request_bridge_irq(struct bridge_controller *bc, int pin) +int request_chipset_irq(struct irq_source_ops *ops, void *d, nasid_t nasid) { struct hub_irq_data *hd; struct hub_data *hub; @@ -197,17 +164,17 @@ int request_bridge_irq(struct bridge_controller *bc, int pin) } irq = swlevel + IP27_HUB_IRQ_BASE; - hd->bc = bc; + hd->isrc_ops = ops; + hd->isrc_data = d; hd->bit = swlevel; - hd->pin = pin; irq_set_chip_data(irq, hd); /* use CPU connected to nearest hub */ - hub = hub_data(NASID_TO_COMPACT_NODEID(bc->nasid)); + hub = hub_data(NASID_TO_COMPACT_NODEID(nasid)); setup_hub_mask(hd, &hub->h_cpus); desc = irq_to_desc(irq); - desc->irq_common_data.node = bc->nasid; + desc->irq_common_data.node = nasid; cpumask_copy(desc->irq_common_data.affinity, &hub->h_cpus); return irq; diff --git a/drivers/pci/controller/pci-xtalk-bridge.c b/drivers/pci/controller/pci-xtalk-bridge.c index b90fbec8f891..1dfa78b4f514 100644 --- a/drivers/pci/controller/pci-xtalk-bridge.c +++ b/drivers/pci/controller/pci-xtalk-bridge.c @@ -325,6 +325,60 @@ int pcibus_to_node(struct pci_bus *bus) EXPORT_SYMBOL(pcibus_to_node); #endif /* CONFIG_NUMA */ +struct bridge_irq_src_data { + struct bridge_controller *bc; + int pin; +}; + +static void bridge_start_irq_source(cpuid_t cpu, int bit, void *d) +{ + struct bridge_irq_src_data *data = d; + struct bridge_controller *bc = data->bc; + nasid_t nasid; + u32 device; + int pin = data->pin; + + nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); + bridge_write(bc, b_int_addr[pin].addr, + (0x20000 | bit | (nasid << 8))); + bridge_set(bc, b_int_enable, (1 << pin)); + bridge_set(bc, b_int_enable, 0x7ffffe00); /* more stuff in int_enable */ + + /* + * Enable sending of an interrupt clear packt to the hub on a high to + * low transition of the interrupt pin. + * + * IRIX sets additional bits in the address which are documented as + * reserved in the bridge docs. + */ + bridge_set(bc, b_int_mode, (1UL << pin)); + + /* + * We assume the bridge to have a 1:1 mapping between devices + * (slots) and intr pins. + */ + device = bridge_read(bc, b_int_device); + device &= ~(7 << (pin*3)); + device |= (pin << (pin*3)); + bridge_write(bc, b_int_device, device); + + bridge_read(bc, b_wid_tflush); +} + +static void bridge_stop_irq_source(cpuid_t cpi, int bit, void *d) +{ + struct bridge_irq_src_data *data = d; + + bridge_clr(data->bc, b_int_enable, (1 << data->pin)); + bridge_read(data->bc, b_wid_tflush); +} + +static struct irq_source_ops bridge_irq_src_ops = { + .start_irq_source = bridge_start_irq_source, + .stop_irq_source = bridge_stop_irq_source +}; + + /* * All observed requests have pin == 1. We could have a global here, that * gets incremented and returned every time - unfortunately, pci_map_irq @@ -337,11 +391,19 @@ EXPORT_SYMBOL(pcibus_to_node); static int bridge_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); + struct bridge_irq_src_data *data; int irq; irq = bc->pci_int[slot]; if (irq == -1) { - irq = request_bridge_irq(bc, slot); + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->bc = bc; + data->pin = slot; + + irq = request_chipset_irq(&bridge_irq_src_ops, data, bc->nasid); if (irq < 0) return irq;