diff options
Diffstat (limited to 'arch/powerpc/sysdev')
24 files changed, 223 insertions, 144 deletions
| diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig index 9ebcc1337560..5aa92ff3622d 100644 --- a/arch/powerpc/sysdev/Kconfig +++ b/arch/powerpc/sysdev/Kconfig @@ -12,17 +12,11 @@ config PPC4xx_HSTA_MSI  	depends on PCI_MSI  	depends on PCI && 4xx -config PPC4xx_MSI -	bool -	depends on PCI_MSI -	depends on PCI && 4xx -  config PPC_MSI_BITMAP  	bool  	depends on PCI_MSI  	default y if MPIC  	default y if FSL_PCI -	default y if PPC4xx_MSI  	default y if PPC_POWERNV  source "arch/powerpc/sysdev/xics/Kconfig" diff --git a/arch/powerpc/sysdev/cpm2.c b/arch/powerpc/sysdev/cpm2.c index 68538b8329f7..3f130312b6e9 100644 --- a/arch/powerpc/sysdev/cpm2.c +++ b/arch/powerpc/sysdev/cpm2.c @@ -135,7 +135,7 @@ void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src)  }  EXPORT_SYMBOL(__cpm2_setbrg); -int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode) +int __init cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)  {  	int ret = 0;  	int shift; @@ -265,7 +265,7 @@ int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)  	return ret;  } -int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock) +int __init cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)  {  	int ret = 0;  	int shift; @@ -326,7 +326,7 @@ struct cpm2_ioports {  	u32 res[3];  }; -void cpm2_set_pin(int port, int pin, int flags) +void __init cpm2_set_pin(int port, int pin, int flags)  {  	struct cpm2_ioports __iomem *iop =  		(struct cpm2_ioports __iomem *)&cpm2_immr->im_ioport; diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 1d33b7a5ea83..be6b99b1b352 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -226,7 +226,7 @@ static void dart_free(struct iommu_table *tbl, long index, long npages)  	dart_cache_sync(orig_dp, orig_npages);  } -static void allocate_dart(void) +static void __init allocate_dart(void)  {  	unsigned long tmp; diff --git a/arch/powerpc/sysdev/fsl_mpic_err.c b/arch/powerpc/sysdev/fsl_mpic_err.c index 9a98bb212922..df06bb6b838f 100644 --- a/arch/powerpc/sysdev/fsl_mpic_err.c +++ b/arch/powerpc/sysdev/fsl_mpic_err.c @@ -58,7 +58,7 @@ static struct irq_chip fsl_mpic_err_chip = {  	.irq_unmask	= fsl_mpic_unmask_err,  }; -int mpic_setup_error_int(struct mpic *mpic, int intvec) +int __init mpic_setup_error_int(struct mpic *mpic, int intvec)  {  	int i; @@ -121,7 +121,7 @@ static irqreturn_t fsl_error_int_handler(int irq, void *data)  	return IRQ_HANDLED;  } -void mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum) +void __init mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum)  {  	unsigned int virq;  	int ret; diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index e6b06c3f8197..b3475ae9f236 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -125,17 +125,13 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)  	struct fsl_msi *msi_data;  	irq_hw_number_t hwirq; -	for_each_pci_msi_entry(entry, pdev) { -		if (!entry->irq) -			continue; +	msi_for_each_desc(entry, &pdev->dev, MSI_DESC_ASSOCIATED) {  		hwirq = virq_to_hw(entry->irq);  		msi_data = irq_get_chip_data(entry->irq);  		irq_set_msi_desc(entry->irq, NULL);  		irq_dispose_mapping(entry->irq);  		msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);  	} - -	return;  }  static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, @@ -215,7 +211,7 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  		}  	} -	for_each_pci_msi_entry(entry, pdev) { +	msi_for_each_desc(entry, &pdev->dev, MSI_DESC_NOTASSOCIATED) {  		/*  		 * Loop over all the MSI devices until we find one that has an  		 * available interrupt. diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index b8f76f3fd994..674f047b7820 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -1106,7 +1106,7 @@ static const struct of_device_id pci_ids[] = {  struct device_node *fsl_pci_primary; -void fsl_pci_assign_primary(void) +void __init fsl_pci_assign_primary(void)  {  	struct device_node *np; diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h index 1d7a41205695..cdbde2e0c96e 100644 --- a/arch/powerpc/sysdev/fsl_pci.h +++ b/arch/powerpc/sysdev/fsl_pci.h @@ -120,7 +120,7 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose);  extern struct device_node *fsl_pci_primary;  #ifdef CONFIG_PCI -void fsl_pci_assign_primary(void); +void __init fsl_pci_assign_primary(void);  #else  static inline void fsl_pci_assign_primary(void) {}  #endif diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index dc1a151c63d7..3b1ae98e3ce9 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c @@ -208,7 +208,7 @@ static const struct irq_domain_ops i8259_host_ops = {  	.xlate = i8259_host_xlate,  }; -struct irq_domain *i8259_get_host(void) +struct irq_domain *__init i8259_get_host(void)  {  	return i8259_host;  } diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 7638a50a7c38..3f10c9fc3b68 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -767,7 +767,7 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)  	return ipic;  } -void ipic_set_default_priority(void) +void __init ipic_set_default_priority(void)  {  	ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT);  	ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 995fb2ada507..d5cb48b61bbd 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1323,8 +1323,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,  	psrc = of_get_property(mpic->node, "protected-sources", &psize);  	if (psrc) {  		/* Allocate a bitmap with one bit per interrupt */ -		unsigned int mapsize = BITS_TO_LONGS(intvec_top + 1); -		mpic->protected = kcalloc(mapsize, sizeof(long), GFP_KERNEL); +		mpic->protected = bitmap_zalloc(intvec_top + 1, GFP_KERNEL);  		BUG_ON(mpic->protected == NULL);  		for (i = 0; i < psize/sizeof(u32); i++) {  			if (psrc[i] > intvec_top) @@ -1840,7 +1839,7 @@ unsigned int mpic_get_mcirq(void)  }  #ifdef CONFIG_SMP -void mpic_request_ipis(void) +void __init mpic_request_ipis(void)  {  	struct mpic *mpic = mpic_primary;  	int i; diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h index 73a31a429d46..bb460ff57a06 100644 --- a/arch/powerpc/sysdev/mpic.h +++ b/arch/powerpc/sysdev/mpic.h @@ -8,8 +8,8 @@  #ifdef CONFIG_PCI_MSI  extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq); -extern int mpic_msi_init_allocator(struct mpic *mpic); -extern int mpic_u3msi_init(struct mpic *mpic); +int __init mpic_msi_init_allocator(struct mpic *mpic); +int __init mpic_u3msi_init(struct mpic *mpic);  #else  static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,  					  irq_hw_number_t hwirq) @@ -24,7 +24,7 @@ static inline int mpic_u3msi_init(struct mpic *mpic)  #endif  #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PPC_PASEMI) -int mpic_pasemi_msi_init(struct mpic *mpic); +int __init mpic_pasemi_msi_init(struct mpic *mpic);  #else  static inline int mpic_pasemi_msi_init(struct mpic *mpic) { return -1; }  #endif @@ -37,8 +37,8 @@ extern void mpic_reset_core(int cpu);  #ifdef CONFIG_FSL_SOC  extern int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw); -extern void mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum); -extern int mpic_setup_error_int(struct mpic *mpic, int intvec); +void __init mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum); +int __init mpic_setup_error_int(struct mpic *mpic, int intvec);  #else  static inline int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw)  { diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index 4695c04320ae..f412d6ad0b66 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c @@ -24,7 +24,7 @@ void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)  }  #ifdef CONFIG_MPIC_U3_HT_IRQS -static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) +static int __init mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)  {  	irq_hw_number_t hwirq;  	const struct irq_domain_ops *ops = mpic->irqhost->ops; @@ -68,13 +68,13 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)  	return 0;  }  #else -static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) +static int __init mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)  {  	return -1;  }  #endif -int mpic_msi_init_allocator(struct mpic *mpic) +int __init mpic_msi_init_allocator(struct mpic *mpic)  {  	int rc; diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c index a42a20280035..444e9ce42d0a 100644 --- a/arch/powerpc/sysdev/mpic_timer.c +++ b/arch/powerpc/sysdev/mpic_timer.c @@ -384,7 +384,7 @@ struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev,  }  EXPORT_SYMBOL(mpic_request_timer); -static int timer_group_get_freq(struct device_node *np, +static int __init timer_group_get_freq(struct device_node *np,  			struct timer_group_priv *priv)  {  	u32 div; @@ -411,7 +411,7 @@ static int timer_group_get_freq(struct device_node *np,  	return 0;  } -static int timer_group_get_irq(struct device_node *np, +static int __init timer_group_get_irq(struct device_node *np,  		struct timer_group_priv *priv)  {  	const u32 all_timer[] = { 0, TIMERS_PER_GROUP }; @@ -459,7 +459,7 @@ static int timer_group_get_irq(struct device_node *np,  	return 0;  } -static void timer_group_init(struct device_node *np) +static void __init timer_group_init(struct device_node *np)  {  	struct timer_group_priv *priv;  	unsigned int i = 0; diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index 3861023d378a..3f4841dfefb5 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c @@ -104,17 +104,12 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)  	struct msi_desc *entry;  	irq_hw_number_t hwirq; -	for_each_pci_msi_entry(entry, pdev) { -		if (!entry->irq) -			continue; - +	msi_for_each_desc(entry, &pdev->dev, MSI_DESC_ASSOCIATED) {  		hwirq = virq_to_hw(entry->irq);  		irq_set_msi_desc(entry->irq, NULL);  		irq_dispose_mapping(entry->irq);  		msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);  	} - -	return;  }  static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) @@ -136,7 +131,7 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  		return -ENXIO;  	} -	for_each_pci_msi_entry(entry, pdev) { +	msi_for_each_desc(entry, &pdev->dev, MSI_DESC_NOTASSOCIATED) {  		hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);  		if (hwirq < 0) {  			pr_debug("u3msi: failed allocating hwirq\n"); @@ -174,7 +169,7 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  	return 0;  } -int mpic_u3msi_init(struct mpic *mpic) +int __init mpic_u3msi_init(struct mpic *mpic)  {  	int rc;  	struct pci_controller *phb; diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c index 4c4a6efd5e5f..9e13fb35ed5c 100644 --- a/arch/powerpc/sysdev/tsi108_dev.c +++ b/arch/powerpc/sysdev/tsi108_dev.c @@ -51,13 +51,12 @@ phys_addr_t get_csrbase(void)  	}  	return tsi108_csr_base;  } +EXPORT_SYMBOL(get_csrbase);  u32 get_vir_csrbase(void)  {  	return (u32) (ioremap(get_csrbase(), 0x10000));  } - -EXPORT_SYMBOL(get_csrbase);  EXPORT_SYMBOL(get_vir_csrbase);  static int __init tsi108_eth_of_init(void) diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index 042bb38fa5c2..1070220f15d5 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c @@ -257,7 +257,7 @@ static void tsi108_pci_int_unmask(u_int irq)  	mb();  } -static void init_pci_source(void) +static void __init init_pci_source(void)  {  	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL,  			0x0000ff00); diff --git a/arch/powerpc/sysdev/udbg_memcons.c b/arch/powerpc/sysdev/udbg_memcons.c index d38bbeed219b..5020044400dc 100644 --- a/arch/powerpc/sysdev/udbg_memcons.c +++ b/arch/powerpc/sysdev/udbg_memcons.c @@ -92,7 +92,7 @@ int memcons_getc(void)  	return c;  } -void udbg_init_memcons(void) +void __init udbg_init_memcons(void)  {  	udbg_putc = memcons_putc;  	udbg_getc = memcons_getc; diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c index 6765d9e264a3..cf8db19a4f7d 100644 --- a/arch/powerpc/sysdev/xics/icp-hv.c +++ b/arch/powerpc/sysdev/xics/icp-hv.c @@ -162,7 +162,7 @@ static const struct icp_ops icp_hv_ops = {  #endif  }; -int icp_hv_init(void) +int __init icp_hv_init(void)  {  	struct device_node *np; diff --git a/arch/powerpc/sysdev/xics/icp-opal.c b/arch/powerpc/sysdev/xics/icp-opal.c index 675d708863d5..bda4c32582d9 100644 --- a/arch/powerpc/sysdev/xics/icp-opal.c +++ b/arch/powerpc/sysdev/xics/icp-opal.c @@ -184,7 +184,7 @@ static const struct icp_ops icp_opal_ops = {  #endif  }; -int icp_opal_init(void) +int __init icp_opal_init(void)  {  	struct device_node *np; diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index 244a727c6ba4..f3fb2a12124c 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c @@ -121,7 +121,7 @@ void xics_mask_unknown_vec(unsigned int vec)  #ifdef CONFIG_SMP -static void xics_request_ipi(void) +static void __init xics_request_ipi(void)  {  	unsigned int ipi; diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c index 7b69299c2912..1ca5564bda9d 100644 --- a/arch/powerpc/sysdev/xive/common.c +++ b/arch/powerpc/sysdev/xive/common.c @@ -85,6 +85,16 @@ static DEFINE_PER_CPU(struct xive_cpu *, xive_cpu);  #define XIVE_INVALID_TARGET	(-1)  /* + * Global toggle to switch on/off StoreEOI + */ +static bool xive_store_eoi = true; + +static bool xive_is_store_eoi(struct xive_irq_data *xd) +{ +	return xd->flags & XIVE_IRQ_FLAG_STORE_EOI && xive_store_eoi; +} + +/*   * Read the next entry in a queue, return its content if it's valid   * or 0 if there is no new entry.   * @@ -208,7 +218,7 @@ static notrace u8 xive_esb_read(struct xive_irq_data *xd, u32 offset)  {  	u64 val; -	if (offset == XIVE_ESB_SET_PQ_10 && xd->flags & XIVE_IRQ_FLAG_STORE_EOI) +	if (offset == XIVE_ESB_SET_PQ_10 && xive_is_store_eoi(xd))  		offset |= XIVE_ESB_LD_ST_MO;  	if ((xd->flags & XIVE_IRQ_FLAG_H_INT_ESB) && xive_ops->esb_rw) @@ -227,6 +237,21 @@ static void xive_esb_write(struct xive_irq_data *xd, u32 offset, u64 data)  		out_be64(xd->eoi_mmio + offset, data);  } +#if defined(CONFIG_XMON) || defined(CONFIG_DEBUG_FS) +static void xive_irq_data_dump(struct xive_irq_data *xd, char *buffer, size_t size) +{ +	u64 val = xive_esb_read(xd, XIVE_ESB_GET); + +	snprintf(buffer, size, "flags=%c%c%c PQ=%c%c 0x%016llx 0x%016llx", +		 xive_is_store_eoi(xd) ? 'S' : ' ', +		 xd->flags & XIVE_IRQ_FLAG_LSI ? 'L' : ' ', +		 xd->flags & XIVE_IRQ_FLAG_H_INT_ESB ? 'H' : ' ', +		 val & XIVE_ESB_VAL_P ? 'P' : '-', +		 val & XIVE_ESB_VAL_Q ? 'Q' : '-', +		 xd->trig_page, xd->eoi_page); +} +#endif +  #ifdef CONFIG_XMON  static notrace void xive_dump_eq(const char *name, struct xive_q *q)  { @@ -252,11 +277,10 @@ notrace void xmon_xive_do_dump(int cpu)  #ifdef CONFIG_SMP  		{ -			u64 val = xive_esb_read(&xc->ipi_data, XIVE_ESB_GET); +			char buffer[128]; -			xmon_printf("IPI=0x%08x PQ=%c%c ", xc->hw_ipi, -				    val & XIVE_ESB_VAL_P ? 'P' : '-', -				    val & XIVE_ESB_VAL_Q ? 'Q' : '-'); +			xive_irq_data_dump(&xc->ipi_data, buffer, sizeof(buffer)); +			xmon_printf("IPI=0x%08x %s", xc->hw_ipi, buffer);  		}  #endif  		xive_dump_eq("EQ", &xc->queue[xive_irq_priority]); @@ -291,15 +315,11 @@ int xmon_xive_get_irq_config(u32 hw_irq, struct irq_data *d)  		d = xive_get_irq_data(hw_irq);  	if (d) { -		struct xive_irq_data *xd = irq_data_get_irq_handler_data(d); -		u64 val = xive_esb_read(xd, XIVE_ESB_GET); - -		xmon_printf("flags=%c%c%c PQ=%c%c", -			    xd->flags & XIVE_IRQ_FLAG_STORE_EOI ? 'S' : ' ', -			    xd->flags & XIVE_IRQ_FLAG_LSI ? 'L' : ' ', -			    xd->flags & XIVE_IRQ_FLAG_H_INT_ESB ? 'H' : ' ', -			    val & XIVE_ESB_VAL_P ? 'P' : '-', -			    val & XIVE_ESB_VAL_Q ? 'Q' : '-'); +		char buffer[128]; + +		xive_irq_data_dump(irq_data_get_irq_handler_data(d), +				   buffer, sizeof(buffer)); +		xmon_printf("%s", buffer);  	}  	xmon_printf("\n"); @@ -385,7 +405,7 @@ static void xive_do_source_eoi(struct xive_irq_data *xd)  	xd->stale_p = false;  	/* If the XIVE supports the new "store EOI facility, use it */ -	if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI) { +	if (xive_is_store_eoi(xd)) {  		xive_esb_write(xd, XIVE_ESB_STORE_EOI, 0);  		return;  	} @@ -451,6 +471,8 @@ static void xive_do_source_set_mask(struct xive_irq_data *xd,  {  	u64 val; +	pr_debug("%s: HW 0x%x %smask\n", __func__, xd->hw_irq, mask ? "" : "un"); +  	/*  	 * If the interrupt had P set, it may be in a queue.  	 * @@ -612,8 +634,8 @@ static unsigned int xive_irq_startup(struct irq_data *d)  	xd->saved_p = false;  	xd->stale_p = false; -	pr_devel("xive_irq_startup: irq %d [0x%x] data @%p\n", -		 d->irq, hw_irq, d); + +	pr_debug("%s: irq %d [0x%x] data @%p\n", __func__, d->irq, hw_irq, d);  	/* Pick a target */  	target = xive_pick_irq_target(d, irq_data_get_affinity_mask(d)); @@ -654,8 +676,7 @@ static void xive_irq_shutdown(struct irq_data *d)  	struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);  	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); -	pr_devel("xive_irq_shutdown: irq %d [0x%x] data @%p\n", -		 d->irq, hw_irq, d); +	pr_debug("%s: irq %d [0x%x] data @%p\n", __func__, d->irq, hw_irq, d);  	if (WARN_ON(xd->target == XIVE_INVALID_TARGET))  		return; @@ -679,7 +700,7 @@ static void xive_irq_unmask(struct irq_data *d)  {  	struct xive_irq_data *xd = irq_data_get_irq_handler_data(d); -	pr_devel("xive_irq_unmask: irq %d data @%p\n", d->irq, xd); +	pr_debug("%s: irq %d data @%p\n", __func__, d->irq, xd);  	xive_do_source_set_mask(xd, false);  } @@ -688,7 +709,7 @@ static void xive_irq_mask(struct irq_data *d)  {  	struct xive_irq_data *xd = irq_data_get_irq_handler_data(d); -	pr_devel("xive_irq_mask: irq %d data @%p\n", d->irq, xd); +	pr_debug("%s: irq %d data @%p\n", __func__, d->irq, xd);  	xive_do_source_set_mask(xd, true);  } @@ -702,7 +723,7 @@ static int xive_irq_set_affinity(struct irq_data *d,  	u32 target, old_target;  	int rc = 0; -	pr_debug("%s: irq %d/%x\n", __func__, d->irq, hw_irq); +	pr_debug("%s: irq %d/0x%x\n", __func__, d->irq, hw_irq);  	/* Is this valid ? */  	if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids) @@ -975,7 +996,7 @@ EXPORT_SYMBOL_GPL(is_xive_irq);  void xive_cleanup_irq_data(struct xive_irq_data *xd)  { -	pr_debug("%s for HW %x\n", __func__, xd->hw_irq); +	pr_debug("%s for HW 0x%x\n", __func__, xd->hw_irq);  	if (xd->eoi_mmio) {  		iounmap(xd->eoi_mmio); @@ -1211,8 +1232,8 @@ static int xive_setup_cpu_ipi(unsigned int cpu)  		pr_err("Failed to map IPI CPU %d\n", cpu);  		return -EIO;  	} -	pr_devel("CPU %d HW IPI %x, virq %d, trig_mmio=%p\n", cpu, -	    xc->hw_ipi, xive_ipi_irq, xc->ipi_data.trig_mmio); +	pr_debug("CPU %d HW IPI 0x%x, virq %d, trig_mmio=%p\n", cpu, +		 xc->hw_ipi, xive_ipi_irq, xc->ipi_data.trig_mmio);  	/* Unmask it */  	xive_do_source_set_mask(&xc->ipi_data, false); @@ -1390,7 +1411,7 @@ static int xive_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,  	if (rc)  		return rc; -	pr_debug("%s %d/%lx #%d\n", __func__, virq, hwirq, nr_irqs); +	pr_debug("%s %d/0x%lx #%d\n", __func__, virq, hwirq, nr_irqs);  	for (i = 0; i < nr_irqs; i++) {  		/* TODO: call xive_irq_domain_map() */ @@ -1504,7 +1525,7 @@ static void xive_setup_cpu(void)  #ifdef CONFIG_SMP  void xive_smp_setup_cpu(void)  { -	pr_devel("SMP setup CPU %d\n", smp_processor_id()); +	pr_debug("SMP setup CPU %d\n", smp_processor_id());  	/* This will have already been done on the boot CPU */  	if (smp_processor_id() != boot_cpuid) @@ -1650,10 +1671,10 @@ bool __init xive_core_init(struct device_node *np, const struct xive_ops *ops,  	ppc_md.get_irq = xive_get_irq;  	__xive_enabled = true; -	pr_devel("Initializing host..\n"); +	pr_debug("Initializing host..\n");  	xive_init_host(np); -	pr_devel("Initializing boot CPU..\n"); +	pr_debug("Initializing boot CPU..\n");  	/* Allocate per-CPU data and queues */  	xive_prepare_cpu(smp_processor_id()); @@ -1691,36 +1712,36 @@ static int __init xive_off(char *arg)  }  __setup("xive=off", xive_off); -static void xive_debug_show_cpu(struct seq_file *m, int cpu) +static int __init xive_store_eoi_cmdline(char *arg) +{ +	if (!arg) +		return -EINVAL; + +	if (strncmp(arg, "off", 3) == 0) { +		pr_info("StoreEOI disabled on kernel command line\n"); +		xive_store_eoi = false; +	} +	return 0; +} +__setup("xive.store-eoi=", xive_store_eoi_cmdline); + +#ifdef CONFIG_DEBUG_FS +static void xive_debug_show_ipi(struct seq_file *m, int cpu)  {  	struct xive_cpu *xc = per_cpu(xive_cpu, cpu); -	seq_printf(m, "CPU %d:", cpu); +	seq_printf(m, "CPU %d: ", cpu);  	if (xc) {  		seq_printf(m, "pp=%02x CPPR=%02x ", xc->pending_prio, xc->cppr);  #ifdef CONFIG_SMP  		{ -			u64 val = xive_esb_read(&xc->ipi_data, XIVE_ESB_GET); +			char buffer[128]; -			seq_printf(m, "IPI=0x%08x PQ=%c%c ", xc->hw_ipi, -				   val & XIVE_ESB_VAL_P ? 'P' : '-', -				   val & XIVE_ESB_VAL_Q ? 'Q' : '-'); +			xive_irq_data_dump(&xc->ipi_data, buffer, sizeof(buffer)); +			seq_printf(m, "IPI=0x%08x %s", xc->hw_ipi, buffer);  		}  #endif -		{ -			struct xive_q *q = &xc->queue[xive_irq_priority]; -			u32 i0, i1, idx; - -			if (q->qpage) { -				idx = q->idx; -				i0 = be32_to_cpup(q->qpage + idx); -				idx = (idx + 1) & q->msk; -				i1 = be32_to_cpup(q->qpage + idx); -				seq_printf(m, "EQ idx=%d T=%d %08x %08x ...", -					   q->idx, q->toggle, i0, i1); -			} -		}  	}  	seq_puts(m, "\n");  } @@ -1732,8 +1753,7 @@ static void xive_debug_show_irq(struct seq_file *m, struct irq_data *d)  	u32 target;  	u8 prio;  	u32 lirq; -	struct xive_irq_data *xd; -	u64 val; +	char buffer[128];  	rc = xive_ops->get_irq_config(hw_irq, &target, &prio, &lirq);  	if (rc) { @@ -1744,43 +1764,101 @@ static void xive_debug_show_irq(struct seq_file *m, struct irq_data *d)  	seq_printf(m, "IRQ 0x%08x : target=0x%x prio=%02x lirq=0x%x ",  		   hw_irq, target, prio, lirq); -	xd = irq_data_get_irq_handler_data(d); -	val = xive_esb_read(xd, XIVE_ESB_GET); -	seq_printf(m, "flags=%c%c%c PQ=%c%c", -		   xd->flags & XIVE_IRQ_FLAG_STORE_EOI ? 'S' : ' ', -		   xd->flags & XIVE_IRQ_FLAG_LSI ? 'L' : ' ', -		   xd->flags & XIVE_IRQ_FLAG_H_INT_ESB ? 'H' : ' ', -		   val & XIVE_ESB_VAL_P ? 'P' : '-', -		   val & XIVE_ESB_VAL_Q ? 'Q' : '-'); +	xive_irq_data_dump(irq_data_get_irq_handler_data(d), buffer, sizeof(buffer)); +	seq_puts(m, buffer);  	seq_puts(m, "\n");  } -static int xive_core_debug_show(struct seq_file *m, void *private) +static int xive_irq_debug_show(struct seq_file *m, void *private)  {  	unsigned int i;  	struct irq_desc *desc; + +	for_each_irq_desc(i, desc) { +		struct irq_data *d = irq_domain_get_irq_data(xive_irq_domain, i); + +		if (d) +			xive_debug_show_irq(m, d); +	} +	return 0; +} +DEFINE_SHOW_ATTRIBUTE(xive_irq_debug); + +static int xive_ipi_debug_show(struct seq_file *m, void *private) +{  	int cpu;  	if (xive_ops->debug_show)  		xive_ops->debug_show(m, private);  	for_each_possible_cpu(cpu) -		xive_debug_show_cpu(m, cpu); +		xive_debug_show_ipi(m, cpu); +	return 0; +} +DEFINE_SHOW_ATTRIBUTE(xive_ipi_debug); -	for_each_irq_desc(i, desc) { -		struct irq_data *d = irq_domain_get_irq_data(xive_irq_domain, i); +static void xive_eq_debug_show_one(struct seq_file *m, struct xive_q *q, u8 prio) +{ +	int i; -		if (d) -			xive_debug_show_irq(m, d); +	seq_printf(m, "EQ%d idx=%d T=%d\n", prio, q->idx, q->toggle); +	if (q->qpage) { +		for (i = 0; i < q->msk + 1; i++) { +			if (!(i % 8)) +				seq_printf(m, "%05d ", i); +			seq_printf(m, "%08x%s", be32_to_cpup(q->qpage + i), +				   (i + 1) % 8 ? " " : "\n"); +		}  	} +	seq_puts(m, "\n"); +} + +static int xive_eq_debug_show(struct seq_file *m, void *private) +{ +	int cpu = (long)m->private; +	struct xive_cpu *xc = per_cpu(xive_cpu, cpu); + +	if (xc) +		xive_eq_debug_show_one(m, &xc->queue[xive_irq_priority], +				       xive_irq_priority);  	return 0;  } -DEFINE_SHOW_ATTRIBUTE(xive_core_debug); +DEFINE_SHOW_ATTRIBUTE(xive_eq_debug); + +static void xive_core_debugfs_create(void) +{ +	struct dentry *xive_dir; +	struct dentry *xive_eq_dir; +	long cpu; +	char name[16]; + +	xive_dir = debugfs_create_dir("xive", arch_debugfs_dir); +	if (IS_ERR(xive_dir)) +		return; + +	debugfs_create_file("ipis", 0400, xive_dir, +			    NULL, &xive_ipi_debug_fops); +	debugfs_create_file("interrupts", 0400, xive_dir, +			    NULL, &xive_irq_debug_fops); +	xive_eq_dir = debugfs_create_dir("eqs", xive_dir); +	for_each_possible_cpu(cpu) { +		snprintf(name, sizeof(name), "cpu%ld", cpu); +		debugfs_create_file(name, 0400, xive_eq_dir, (void *)cpu, +				    &xive_eq_debug_fops); +	} +	debugfs_create_bool("store-eoi", 0600, xive_dir, &xive_store_eoi); + +	if (xive_ops->debug_create) +		xive_ops->debug_create(xive_dir); +} +#else +static inline void xive_core_debugfs_create(void) { } +#endif /* CONFIG_DEBUG_FS */  int xive_core_debug_init(void)  { -	if (xive_enabled()) -		debugfs_create_file("xive", 0400, arch_debugfs_dir, -				    NULL, &xive_core_debug_fops); +	if (xive_enabled() && IS_ENABLED(CONFIG_DEBUG_FS)) +		xive_core_debugfs_create(); +  	return 0;  } diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index 1aec282cd650..f940428ad13f 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c @@ -41,7 +41,7 @@ static u32 xive_queue_shift;  static u32 xive_pool_vps = XIVE_INVALID_VP;  static struct kmem_cache *xive_provision_cache;  static bool xive_has_single_esc; -static bool xive_has_save_restore; +bool xive_has_save_restore;  int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data)  { @@ -63,6 +63,8 @@ int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data)  	opal_flags = be64_to_cpu(flags);  	if (opal_flags & OPAL_XIVE_IRQ_STORE_EOI)  		data->flags |= XIVE_IRQ_FLAG_STORE_EOI; +	if (opal_flags & OPAL_XIVE_IRQ_STORE_EOI2) +		data->flags |= XIVE_IRQ_FLAG_STORE_EOI;  	if (opal_flags & OPAL_XIVE_IRQ_LSI)  		data->flags |= XIVE_IRQ_FLAG_LSI;  	data->eoi_page = be64_to_cpu(eoi_page); @@ -459,6 +461,14 @@ void xive_native_sync_queue(u32 hw_irq)  }  EXPORT_SYMBOL_GPL(xive_native_sync_queue); +#ifdef CONFIG_DEBUG_FS +static int xive_native_debug_create(struct dentry *xive_dir) +{ +	debugfs_create_bool("save-restore", 0600, xive_dir, &xive_has_save_restore); +	return 0; +} +#endif +  static const struct xive_ops xive_native_ops = {  	.populate_irq_data	= xive_native_populate_irq_data,  	.configure_irq		= xive_native_configure_irq, @@ -476,10 +486,13 @@ static const struct xive_ops xive_native_ops = {  	.get_ipi		= xive_native_get_ipi,  	.put_ipi		= xive_native_put_ipi,  #endif /* CONFIG_SMP */ +#ifdef CONFIG_DEBUG_FS +	.debug_create		= xive_native_debug_create, +#endif /* CONFIG_DEBUG_FS */  	.name			= "native",  }; -static bool xive_parse_provisioning(struct device_node *np) +static bool __init xive_parse_provisioning(struct device_node *np)  {  	int rc; @@ -519,7 +532,7 @@ static bool xive_parse_provisioning(struct device_node *np)  	return true;  } -static void xive_native_setup_pools(void) +static void __init xive_native_setup_pools(void)  {  	/* Allocate a pool big enough */  	pr_debug("XIVE: Allocating VP block for pool size %u\n", nr_cpu_ids); diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c index f143b6f111ac..928f95004501 100644 --- a/arch/powerpc/sysdev/xive/spapr.c +++ b/arch/powerpc/sysdev/xive/spapr.c @@ -44,7 +44,7 @@ struct xive_irq_bitmap {  static LIST_HEAD(xive_irq_bitmaps); -static int xive_irq_bitmap_add(int base, int count) +static int __init xive_irq_bitmap_add(int base, int count)  {  	struct xive_irq_bitmap *xibm; @@ -173,7 +173,7 @@ static long plpar_int_get_source_info(unsigned long flags,  	} while (plpar_busy_delay(rc));  	if (rc) { -		pr_err("H_INT_GET_SOURCE_INFO lisn=%ld failed %ld\n", lisn, rc); +		pr_err("H_INT_GET_SOURCE_INFO lisn=0x%lx failed %ld\n", lisn, rc);  		return rc;  	} @@ -182,8 +182,8 @@ static long plpar_int_get_source_info(unsigned long flags,  	*trig_page = retbuf[2];  	*esb_shift = retbuf[3]; -	pr_devel("H_INT_GET_SOURCE_INFO flags=%lx eoi=%lx trig=%lx shift=%lx\n", -		retbuf[0], retbuf[1], retbuf[2], retbuf[3]); +	pr_debug("H_INT_GET_SOURCE_INFO lisn=0x%lx flags=0x%lx eoi=0x%lx trig=0x%lx shift=0x%lx\n", +		 lisn, retbuf[0], retbuf[1], retbuf[2], retbuf[3]);  	return 0;  } @@ -200,8 +200,8 @@ static long plpar_int_set_source_config(unsigned long flags,  	long rc; -	pr_devel("H_INT_SET_SOURCE_CONFIG flags=%lx lisn=%lx target=%lx prio=%lx sw_irq=%lx\n", -		flags, lisn, target, prio, sw_irq); +	pr_debug("H_INT_SET_SOURCE_CONFIG flags=0x%lx lisn=0x%lx target=%ld prio=%ld sw_irq=%ld\n", +		 flags, lisn, target, prio, sw_irq);  	do { @@ -210,7 +210,7 @@ static long plpar_int_set_source_config(unsigned long flags,  	} while (plpar_busy_delay(rc));  	if (rc) { -		pr_err("H_INT_SET_SOURCE_CONFIG lisn=%ld target=%lx prio=%lx failed %ld\n", +		pr_err("H_INT_SET_SOURCE_CONFIG lisn=0x%lx target=%ld prio=%ld failed %ld\n",  		       lisn, target, prio, rc);  		return rc;  	} @@ -227,7 +227,7 @@ static long plpar_int_get_source_config(unsigned long flags,  	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];  	long rc; -	pr_devel("H_INT_GET_SOURCE_CONFIG flags=%lx lisn=%lx\n", flags, lisn); +	pr_debug("H_INT_GET_SOURCE_CONFIG flags=0x%lx lisn=0x%lx\n", flags, lisn);  	do {  		rc = plpar_hcall(H_INT_GET_SOURCE_CONFIG, retbuf, flags, lisn, @@ -235,7 +235,7 @@ static long plpar_int_get_source_config(unsigned long flags,  	} while (plpar_busy_delay(rc));  	if (rc) { -		pr_err("H_INT_GET_SOURCE_CONFIG lisn=%ld failed %ld\n", +		pr_err("H_INT_GET_SOURCE_CONFIG lisn=0x%lx failed %ld\n",  		       lisn, rc);  		return rc;  	} @@ -244,8 +244,8 @@ static long plpar_int_get_source_config(unsigned long flags,  	*prio   = retbuf[1];  	*sw_irq = retbuf[2]; -	pr_devel("H_INT_GET_SOURCE_CONFIG target=%lx prio=%lx sw_irq=%lx\n", -		retbuf[0], retbuf[1], retbuf[2]); +	pr_debug("H_INT_GET_SOURCE_CONFIG target=%ld prio=%ld sw_irq=%ld\n", +		 retbuf[0], retbuf[1], retbuf[2]);  	return 0;  } @@ -273,8 +273,8 @@ static long plpar_int_get_queue_info(unsigned long flags,  	*esn_page = retbuf[0];  	*esn_size = retbuf[1]; -	pr_devel("H_INT_GET_QUEUE_INFO page=%lx size=%lx\n", -		retbuf[0], retbuf[1]); +	pr_debug("H_INT_GET_QUEUE_INFO cpu=%ld prio=%ld page=0x%lx size=0x%lx\n", +		 target, priority, retbuf[0], retbuf[1]);  	return 0;  } @@ -289,8 +289,8 @@ static long plpar_int_set_queue_config(unsigned long flags,  {  	long rc; -	pr_devel("H_INT_SET_QUEUE_CONFIG flags=%lx target=%lx priority=%lx qpage=%lx qsize=%lx\n", -		flags,  target, priority, qpage, qsize); +	pr_debug("H_INT_SET_QUEUE_CONFIG flags=0x%lx target=%ld priority=0x%lx qpage=0x%lx qsize=0x%lx\n", +		 flags,  target, priority, qpage, qsize);  	do {  		rc = plpar_hcall_norets(H_INT_SET_QUEUE_CONFIG, flags, target, @@ -298,7 +298,7 @@ static long plpar_int_set_queue_config(unsigned long flags,  	} while (plpar_busy_delay(rc));  	if (rc) { -		pr_err("H_INT_SET_QUEUE_CONFIG cpu=%ld prio=%ld qpage=%lx returned %ld\n", +		pr_err("H_INT_SET_QUEUE_CONFIG cpu=%ld prio=%ld qpage=0x%lx returned %ld\n",  		       target, priority, qpage, rc);  		return  rc;  	} @@ -315,7 +315,7 @@ static long plpar_int_sync(unsigned long flags, unsigned long lisn)  	} while (plpar_busy_delay(rc));  	if (rc) { -		pr_err("H_INT_SYNC lisn=%ld returned %ld\n", lisn, rc); +		pr_err("H_INT_SYNC lisn=0x%lx returned %ld\n", lisn, rc);  		return  rc;  	} @@ -333,8 +333,8 @@ static long plpar_int_esb(unsigned long flags,  	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];  	long rc; -	pr_devel("H_INT_ESB flags=%lx lisn=%lx offset=%lx in=%lx\n", -		flags,  lisn, offset, in_data); +	pr_debug("H_INT_ESB flags=0x%lx lisn=0x%lx offset=0x%lx in=0x%lx\n", +		 flags,  lisn, offset, in_data);  	do {  		rc = plpar_hcall(H_INT_ESB, retbuf, flags, lisn, offset, @@ -342,7 +342,7 @@ static long plpar_int_esb(unsigned long flags,  	} while (plpar_busy_delay(rc));  	if (rc) { -		pr_err("H_INT_ESB lisn=%ld offset=%ld returned %ld\n", +		pr_err("H_INT_ESB lisn=0x%lx offset=0x%lx returned %ld\n",  		       lisn, offset, rc);  		return  rc;  	} @@ -653,6 +653,9 @@ static int xive_spapr_debug_show(struct seq_file *m, void *private)  	struct xive_irq_bitmap *xibm;  	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; +  	list_for_each_entry(xibm, &xive_irq_bitmaps, list) {  		memset(buf, 0, PAGE_SIZE);  		bitmap_print_to_pagebuf(true, buf, xibm->bitmap, xibm->count); @@ -687,7 +690,7 @@ static const struct xive_ops xive_spapr_ops = {  /*   * get max priority from "/ibm,plat-res-int-priorities"   */ -static bool xive_get_max_prio(u8 *max_prio) +static bool __init xive_get_max_prio(u8 *max_prio)  {  	struct device_node *rootdn;  	const __be32 *reg; @@ -741,7 +744,7 @@ static bool xive_get_max_prio(u8 *max_prio)  	return true;  } -static const u8 *get_vec5_feature(unsigned int index) +static const u8 *__init get_vec5_feature(unsigned int index)  {  	unsigned long root, chosen;  	int size; diff --git a/arch/powerpc/sysdev/xive/xive-internal.h b/arch/powerpc/sysdev/xive/xive-internal.h index 504e7edce358..fe6d95d54af9 100644 --- a/arch/powerpc/sysdev/xive/xive-internal.h +++ b/arch/powerpc/sysdev/xive/xive-internal.h @@ -58,6 +58,7 @@ struct xive_ops {  	void	(*put_ipi)(unsigned int cpu, struct xive_cpu *xc);  #endif  	int	(*debug_show)(struct seq_file *m, void *private); +	int	(*debug_create)(struct dentry *xive_dir);  	const char *name;  }; @@ -72,5 +73,6 @@ static inline u32 xive_alloc_order(u32 queue_shift)  }  extern bool xive_cmdline_disabled; +extern bool xive_has_save_restore;  #endif /*  __XIVE_INTERNAL_H */ |