armada-370-xp irqchip updates round 5
Subsystems (2)
v2 cover armada-370-xp irqchip updates round 5
Hi Thomas, Andrew, Ilpo et al.,
This is v2 of the last round of updates for armada-370-xp irqchip before I send the one patch adding support for SoC Error interrupts.
I have addressed the issues pointed out by Thomas in v1, which you can see at
https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=871321
This series can be applied on tip/irq/core.
Marek
Marek Behún (12):
irqchip/armada-370-xp: Drop IPI_DOORBELL_START and rename
IPI_DOORBELL_END
irqchip/armada-370-xp: Drop msi_doorbell_end() irqchip/armada-370-xp: Add the __init attribute to mpic_msi_init() irqchip/armada-370-xp: Put __init attribute after return type in
mpic_ipi_init()
irqchip/armada-370-xp: Put static variables into driver private
structure
irqchip/armada-370-xp: Put MSI doorbell limits into the mpic structure irqchip/armada-370-xp: Pass around the driver private structure irqchip/armada-370-xp: Dynamically allocate the driver private
structure
irqchip/armada-370-xp: Correct reenabling last per-CPU interrupt irqchip/armada-370-xp: Iterate only valid bits of the per-CPU
interrupt cause register
irqchip/armada-370-xp: Allow mapping only per-CPU interrupts irqchip/armada-370-xp: Use the mpic_is_ipi_available() helper in one
more case
drivers/irqchip/irq-armada-370-xp.c | 407 ++++++++++++++++------------ 1 file changed, 229 insertions(+), 178 deletions(-)
Signature · 1 line
2.44.2
PATCH v2 1/12 irqchip/armada-370-xp: Drop IPI_DOORBELL_START and rename IPI_DOORBELL_END
Drop IPI_DOORBELL_START since it is not used and rename IPI_DOORBELL_END to IPI_DOORBELL_NR.
--- drivers/irqchip/irq-armada-370-xp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +6 -7
@@ -136,8 +136,7 @@#define MPIC_MAX_PER_CPU_IRQS 28/* IPI and MSI interrupt definitions for IPI platforms */ -#define IPI_DOORBELL_START 0 -#define IPI_DOORBELL_END 8 +#define IPI_DOORBELL_NR 8#define IPI_DOORBELL_MASK GENMASK(7, 0)#define PCI_MSI_DOORBELL_START 16#define PCI_MSI_DOORBELL_NR 16
@@ -452,7 +451,7 @@ static const struct irq_domain_ops mpic_ipi_domain_ops = {static void mpic_ipi_resume (void ) { -for (irq_hw_number_t i =0 ; i <IPI_DOORBELL_END ; i++) { +for (irq_hw_number_t i =0 ; i <IPI_DOORBELL_NR ; i++) {unsigned int virq =irq_find_mapping (mpic_ipi_domain, i);struct irq_data *d;
@@ -468,17 +467,17 @@ static __init int mpic_ipi_init(struct device_node *node) {int base_ipi; - mpic_ipi_domain =irq_domain_create_linear (of_node_to_fwnode (node),IPI_DOORBELL_END , + mpic_ipi_domain =irq_domain_create_linear (of_node_to_fwnode (node),IPI_DOORBELL_NR , &mpic_ipi_domain_ops,NULL );if (WARN_ON (!mpic_ipi_domain))return -ENOMEM ;irq_domain_update_bus_token (mpic_ipi_domain,DOMAIN_BUS_IPI ); - base_ipi =irq_domain_alloc_irqs (mpic_ipi_domain,IPI_DOORBELL_END ,NUMA_NO_NODE ,NULL ); + base_ipi =irq_domain_alloc_irqs (mpic_ipi_domain,IPI_DOORBELL_NR ,NUMA_NO_NODE ,NULL );if (WARN_ON (!base_ipi))return -ENOMEM ; -set_smp_ipi_range (base_ipi,IPI_DOORBELL_END ); +set_smp_ipi_range (base_ipi,IPI_DOORBELL_NR );return 0 ; }
@@ -627,7 +626,7 @@ static void mpic_handle_ipi_irq(void) cause =readl_relaxed (per_cpu_int_base +MPIC_IN_DRBEL_CAUSE ); cause &=IPI_DOORBELL_MASK ; -for_each_set_bit (i, &cause,IPI_DOORBELL_END ) +for_each_set_bit (i, &cause,IPI_DOORBELL_NR ) generic_handle_domain_irq(mpic_ipi_domain, i); }#else
Signature · 1 line
2.44.2
PATCH v2 2/12 irqchip/armada-370-xp: Drop msi_doorbell_end()
In reply to Marek BehúnDrop the msi_doorbell_end() function and related constants, it is not used anymore.
--- drivers/irqchip/irq-armada-370-xp.c | 7 ------- 1 file changed, 7 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +0 -7
@@ -140,13 +140,11 @@#define IPI_DOORBELL_MASK GENMASK(7, 0)#define PCI_MSI_DOORBELL_START 16#define PCI_MSI_DOORBELL_NR 16 -#define PCI_MSI_DOORBELL_END 32#define PCI_MSI_DOORBELL_MASK GENMASK(31, 16)/* MSI interrupt definitions for non-IPI platforms */ #define PCI_MSI_FULL_DOORBELL_START 0#define PCI_MSI_FULL_DOORBELL_NR 32 -#define PCI_MSI_FULL_DOORBELL_END 32#define PCI_MSI_FULL_DOORBELL_MASK GENMASK(31, 0)#define PCI_MSI_FULL_DOORBELL_SRC0_MASK GENMASK(15, 0)#define PCI_MSI_FULL_DOORBELL_SRC1_MASK GENMASK(31, 16)
@@ -190,11 +188,6 @@ static inline unsigned int msi_doorbell_size(void)return mpic_is_ipi_available () ?PCI_MSI_DOORBELL_NR :PCI_MSI_FULL_DOORBELL_NR ; } -static inline unsigned int msi_doorbell_end (void ) -{ -return mpic_is_ipi_available () ?PCI_MSI_DOORBELL_END :PCI_MSI_FULL_DOORBELL_END ; -} -static inline bool mpic_is_percpu_irq (irq_hw_number_t hwirq) {return hwirq <=MPIC_MAX_PER_CPU_IRQS ;
Signature · 1 line
2.44.2
PATCH v2 3/12 irqchip/armada-370-xp: Add the __init attribute to mpic_msi_init()
In reply to Marek BehúnAdd the __init attribute to the mpic_msi_init() function. It is only called from the device initializer, and so can be dropped after boot is complete.
--- drivers/irqchip/irq-armada-370-xp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/irqchip/irq-armada-370-xp.c +1 -1
@@ -314,7 +314,7 @@ static void mpic_msi_reenable_percpu(void)writel (1 , per_cpu_int_base +MPIC_INT_CLEAR_MASK ); } -static int mpic_msi_init (struct device_node *node,phys_addr_t main_int_phys_base) +static int __init mpic_msi_init (struct device_node *node,phys_addr_t main_int_phys_base) { msi_doorbell_addr = main_int_phys_base +MPIC_SW_TRIG_INT ;
Signature · 1 line
2.44.2
PATCH v2 4/12 irqchip/armada-370-xp: Put __init attribute after return type in mpic_ipi_init()
In reply to Marek BehúnFor consistency with the rest of the driver, put the __init attribute after the return type of the mpic_ipi_init() function.
--- drivers/irqchip/irq-armada-370-xp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/irqchip/irq-armada-370-xp.c +1 -1
@@ -456,7 +456,7 @@ static void mpic_ipi_resume(void) } } -static __init int mpic_ipi_init (struct device_node *node) +static int __init mpic_ipi_init (struct device_node *node) {int base_ipi;
Signature · 1 line
2.44.2
PATCH v2 5/12 irqchip/armada-370-xp: Put static variables into driver private structure
In reply to Marek BehúnIn preparation for converting the driver to modern style put all the interrupt controller private static variables into driver private structure.
Access to these variables changes as:
main_int_base mpic->base
per_cpu_int_base mpic->per_cpu
mpic_domain mpic->domain
parent_irq mpic->parent_irq
...
--- drivers/irqchip/irq-armada-370-xp.c | 223 +++++++++++++++------------- 1 file changed, 122 insertions(+), 101 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +122 -101
@@ -66,11 +66,11 @@* * The "global interrupt mask/unmask" is modified using the * MPIC_INT_SET_ENABLE and MPIC_INT_CLEAR_ENABLE -* registers, which are relative to "main_int_base". +* registers, which are relative to "mpic->base". * * The "per-CPU mask/unmask" is modified using the MPIC_INT_SET_MASK * and MPIC_INT_CLEAR_MASK registers, which are relative to -* "per_cpu_int_base". This base address points to a special address, +* "mpic->per_cpu". This base address points to a special address, * which automatically accesses the registers of the current CPU. * * The per-CPU mask/unmask can also be adjusted using the global
@@ -112,7 +112,7 @@* at the per-CPU level. */ -/* Registers relative to main_int_base */ +/* Registers relative to mpic->base */ #define MPIC_INT_CONTROL 0x00#define MPIC_INT_CONTROL_NUMINT_MASK GENMASK(12, 2)#define MPIC_SW_TRIG_INT 0x04
@@ -122,7 +122,7 @@#define MPIC_INT_SOURCE_CPU_MASK GENMASK(3, 0)#define MPIC_INT_IRQ_FIQ_MASK (cpuid) ((BIT(0) | BIT(8)) << (cpuid)) -/* Registers relative to per_cpu_int_base */ +/* Registers relative to mpic->per_cpu */ #define MPIC_IN_DRBEL_CAUSE 0x08#define MPIC_IN_DRBEL_MASK 0x0c#define MPIC_PPI_CAUSE 0x10
@@ -149,18 +149,40 @@#define PCI_MSI_FULL_DOORBELL_SRC0_MASK GENMASK(15, 0)#define PCI_MSI_FULL_DOORBELL_SRC1_MASK GENMASK(31, 16) -static void __iomem *per_cpu_int_base; -static void __iomem *main_int_base; -static struct irq_domain *mpic_domain; -static u32 doorbell_mask_reg; -static int parent_irq; +/** +* struct mpic - MPIC private data structure +* @base: MPIC registers base address +* @per_cpu: per-CPU registers base address +* @parent_irq: parent IRQ if MPIC is not top-level interrupt controller +* @domain: MPIC main interrupt domain +* @ipi_domain: IPI domain +* @msi_domain: MSI domain +* @msi_inner_domain: MSI inner domain +* @msi_used: bitmap of used MSI numbers +* @msi_lock: mutex serializing access to @msi_used +* @msi_doorbell_addr: physical address of MSI doorbell register +* @doorbell_mask: doorbell mask of MSIs and IPIs, stored on suspend, restored on resume +*/ +struct mpic { +void __iomem *base; +void __iomem *per_cpu; +int parent_irq; +struct irq_domain *domain; +#ifdef CONFIG_SMP +struct irq_domain *ipi_domain; +#endif #ifdef CONFIG_PCI_MSI -static struct irq_domain *mpic_msi_domain; -static struct irq_domain *mpic_msi_inner_domain; -static DECLARE_BITMAP(msi_used, PCI_MSI_FULL_DOORBELL_NR); -static DEFINE_MUTEX (msi_used_lock); -static phys_addr_t msi_doorbell_addr; +struct irq_domain *msi_domain; +struct irq_domain *msi_inner_domain; + DECLARE_BITMAP(msi_used, PCI_MSI_FULL_DOORBELL_NR); +struct mutex msi_lock; +phys_addr_t msi_doorbell_addr;#endif +u32 doorbell_mask; +}; + +static struct mpic mpic_data; +static struct mpic *const mpic = &mpic_data;static inline bool mpic_is_ipi_available (void ) {
@@ -170,7 +192,7 @@ static inline bool mpic_is_ipi_available(void)* interrupt controller (e.g. GIC) that takes care of inter-processor * interrupts. */ -return parent_irq <=0 ; +return mpic->parent_irq <=0 ; }static inline u32 msi_doorbell_mask (void )
@@ -203,9 +225,9 @@ static void mpic_irq_mask(struct irq_data *d)irq_hw_number_t hwirq =irqd_to_hwirq (d);if (!mpic_is_percpu_irq (hwirq)) -writel (hwirq, main_int_base +MPIC_INT_CLEAR_ENABLE ); +writel (hwirq, mpic->base +MPIC_INT_CLEAR_ENABLE );else -writel (hwirq, per_cpu_int_base +MPIC_INT_SET_MASK ); +writel (hwirq, mpic->per_cpu +MPIC_INT_SET_MASK ); }static void mpic_irq_unmask (struct irq_data *d)
@@ -213,9 +235,9 @@ static void mpic_irq_unmask(struct irq_data *d)irq_hw_number_t hwirq =irqd_to_hwirq (d);if (!mpic_is_percpu_irq (hwirq)) -writel (hwirq, main_int_base +MPIC_INT_SET_ENABLE ); +writel (hwirq, mpic->base +MPIC_INT_SET_ENABLE );else -writel (hwirq, per_cpu_int_base +MPIC_INT_CLEAR_MASK ); +writel (hwirq, mpic->per_cpu +MPIC_INT_CLEAR_MASK ); }#ifdef CONFIG_PCI_MSI
@@ -236,8 +258,8 @@ static void mpic_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) {unsigned int cpu =cpumask_first (irq_data_get_effective_affinity_mask (d)); - msg->address_lo =lower_32_bits (msi_doorbell_addr); - msg->address_hi =upper_32_bits (msi_doorbell_addr); + msg->address_lo =lower_32_bits (mpic->msi_doorbell_addr); + msg->address_hi =upper_32_bits (mpic->msi_doorbell_addr); msg->data =BIT (cpu +8 ) | (d->hwirq +msi_doorbell_start ()); }
@@ -269,10 +291,10 @@ static int mpic_msi_alloc(struct irq_domain *domain, unsigned int virq, unsigned {int hwirq; -mutex_lock (&msi_used_lock); - hwirq =bitmap_find_free_region (msi_used,msi_doorbell_size (), +mutex_lock (&mpic->msi_lock); + hwirq =bitmap_find_free_region (mpic->msi_used,msi_doorbell_size (),order_base_2 (nr_irqs)); -mutex_unlock (&msi_used_lock); +mutex_unlock (&mpic->msi_lock);if (hwirq <0 )return -ENOSPC ;
@@ -291,9 +313,9 @@ static void mpic_msi_free(struct irq_domain *domain, unsigned int virq, unsigned {struct irq_data *d =irq_domain_get_irq_data (domain, virq); -mutex_lock (&msi_used_lock); -bitmap_release_region (msi_used, d->hwirq,order_base_2 (nr_irqs)); -mutex_unlock (&msi_used_lock); +mutex_lock (&mpic->msi_lock); +bitmap_release_region (mpic->msi_used, d->hwirq,order_base_2 (nr_irqs)); +mutex_unlock (&mpic->msi_lock); }static const struct irq_domain_ops mpic_msi_domain_ops = {
@@ -306,27 +328,29 @@ static void mpic_msi_reenable_percpu(void)u32 reg;/* Enable MSI doorbell mask and combined cpu local interrupt */ - reg =readl (per_cpu_int_base +MPIC_IN_DRBEL_MASK ); + reg =readl (mpic->per_cpu +MPIC_IN_DRBEL_MASK ); reg |=msi_doorbell_mask (); -writel (reg, per_cpu_int_base +MPIC_IN_DRBEL_MASK ); +writel (reg, mpic->per_cpu +MPIC_IN_DRBEL_MASK );/* Unmask local doorbell interrupt */ -writel (1 , per_cpu_int_base +MPIC_INT_CLEAR_MASK ); +writel (1 , mpic->per_cpu +MPIC_INT_CLEAR_MASK ); }static int __init mpic_msi_init (struct device_node *node,phys_addr_t main_int_phys_base) { - msi_doorbell_addr = main_int_phys_base +MPIC_SW_TRIG_INT ; + mpic->msi_doorbell_addr = main_int_phys_base +MPIC_SW_TRIG_INT ; + +mutex_init (&mpic->msi_lock); - mpic_msi_inner_domain =irq_domain_add_linear (NULL ,msi_doorbell_size (), - &mpic_msi_domain_ops,NULL ); -if (!mpic_msi_inner_domain) + mpic->msi_inner_domain =irq_domain_add_linear (NULL ,msi_doorbell_size (), + &mpic_msi_domain_ops,NULL ); +if (!mpic->msi_inner_domain)return -ENOMEM ; - mpic_msi_domain =pci_msi_create_irq_domain (of_node_to_fwnode (node), &mpic_msi_domain_info, - mpic_msi_inner_domain); -if (!mpic_msi_domain) { -irq_domain_remove (mpic_msi_inner_domain); + mpic->msi_domain =pci_msi_create_irq_domain (of_node_to_fwnode (node), &mpic_msi_domain_info, + mpic->msi_inner_domain); +if (!mpic->msi_domain) { +irq_domain_remove (mpic->msi_inner_domain);return -ENOMEM ; }
@@ -334,7 +358,7 @@ static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_p/* Unmask low 16 MSI irqs on non-IPI platforms */ if (!mpic_is_ipi_available ()) -writel (0 , per_cpu_int_base +MPIC_INT_CLEAR_MASK ); +writel (0 , mpic->per_cpu +MPIC_INT_CLEAR_MASK );return 0 ; }
@@ -362,29 +386,26 @@ static void mpic_perf_init(void) cpuid =cpu_logical_map (smp_processor_id ());/* Enable Performance Counter Overflow interrupts */ -writel (MPIC_INT_CAUSE_PERF (cpuid), - per_cpu_int_base +MPIC_INT_FABRIC_MASK ); +writel (MPIC_INT_CAUSE_PERF (cpuid), mpic->per_cpu +MPIC_INT_FABRIC_MASK ); }#ifdef CONFIG_SMP -static struct irq_domain *mpic_ipi_domain; -static void mpic_ipi_mask (struct irq_data *d) {u32 reg; - reg =readl (per_cpu_int_base +MPIC_IN_DRBEL_MASK ); + reg =readl (mpic->per_cpu +MPIC_IN_DRBEL_MASK ); reg &= ~BIT (d->hwirq); -writel (reg, per_cpu_int_base +MPIC_IN_DRBEL_MASK ); +writel (reg, mpic->per_cpu +MPIC_IN_DRBEL_MASK ); }static void mpic_ipi_unmask (struct irq_data *d) {u32 reg; - reg =readl (per_cpu_int_base +MPIC_IN_DRBEL_MASK ); + reg =readl (mpic->per_cpu +MPIC_IN_DRBEL_MASK ); reg |=BIT (d->hwirq); -writel (reg, per_cpu_int_base +MPIC_IN_DRBEL_MASK ); +writel (reg, mpic->per_cpu +MPIC_IN_DRBEL_MASK ); }static void mpic_ipi_send_mask (struct irq_data *d,const struct cpumask *mask)
@@ -403,12 +424,12 @@ static void mpic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)dsb ();/* submit softirq */ -writel ((map <<8 ) | d->hwirq, main_int_base +MPIC_SW_TRIG_INT ); +writel ((map <<8 ) | d->hwirq, mpic->base +MPIC_SW_TRIG_INT ); }static void mpic_ipi_ack (struct irq_data *d) { -writel (~BIT (d->hwirq), per_cpu_int_base +MPIC_IN_DRBEL_CAUSE ); +writel (~BIT (d->hwirq), mpic->per_cpu +MPIC_IN_DRBEL_CAUSE ); }static struct irq_chip mpic_ipi_irqchip = {
@@ -445,13 +466,13 @@ static const struct irq_domain_ops mpic_ipi_domain_ops = {static void mpic_ipi_resume (void ) {for (irq_hw_number_t i =0 ; i <IPI_DOORBELL_NR ; i++) { -unsigned int virq =irq_find_mapping (mpic_ipi_domain, i); +unsigned int virq =irq_find_mapping (mpic->ipi_domain, i);struct irq_data *d;if (!virq || !irq_percpu_is_enabled (virq))continue ; - d =irq_domain_get_irq_data (mpic_ipi_domain, virq); + d =irq_domain_get_irq_data (mpic->ipi_domain, virq);mpic_ipi_unmask (d); } }
@@ -460,13 +481,13 @@ static int __init mpic_ipi_init(struct device_node *node) {int base_ipi; - mpic_ipi_domain =irq_domain_create_linear (of_node_to_fwnode (node),IPI_DOORBELL_NR , - &mpic_ipi_domain_ops,NULL ); -if (WARN_ON (!mpic_ipi_domain)) + mpic->ipi_domain =irq_domain_create_linear (of_node_to_fwnode (node),IPI_DOORBELL_NR , + &mpic_ipi_domain_ops,NULL ); +if (WARN_ON (!mpic->ipi_domain))return -ENOMEM ; -irq_domain_update_bus_token (mpic_ipi_domain,DOMAIN_BUS_IPI ); - base_ipi =irq_domain_alloc_irqs (mpic_ipi_domain,IPI_DOORBELL_NR ,NUMA_NO_NODE ,NULL ); +irq_domain_update_bus_token (mpic->ipi_domain,DOMAIN_BUS_IPI ); + base_ipi =irq_domain_alloc_irqs (mpic->ipi_domain,IPI_DOORBELL_NR ,NUMA_NO_NODE ,NULL );if (WARN_ON (!base_ipi))return -ENOMEM ;
@@ -483,7 +504,7 @@ static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,/* Select a single core from the affinity mask which is online */ cpu =cpumask_any_and (mask_val, cpu_online_mask); -atomic_io_modify (main_int_base +MPIC_INT_SOURCE_CTL (hwirq), +atomic_io_modify (mpic->base +MPIC_INT_SOURCE_CTL (hwirq),MPIC_INT_SOURCE_CPU_MASK ,BIT (cpu_logical_map (cpu)));irq_data_update_effective_affinity (d,cpumask_of (cpu));
@@ -493,27 +514,27 @@ static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,static void mpic_smp_cpu_init (void ) { -for (irq_hw_number_t i =0 ; i < mpic_domain->hwirq_max; i++) -writel (i, per_cpu_int_base +MPIC_INT_SET_MASK ); +for (irq_hw_number_t i =0 ; i < mpic->domain->hwirq_max; i++) +writel (i, mpic->per_cpu +MPIC_INT_SET_MASK );if (!mpic_is_ipi_available ())return ;/* Disable all IPIs */ -writel (0 , per_cpu_int_base +MPIC_IN_DRBEL_MASK ); +writel (0 , mpic->per_cpu +MPIC_IN_DRBEL_MASK );/* Clear pending IPIs */ -writel (0 , per_cpu_int_base +MPIC_IN_DRBEL_CAUSE ); +writel (0 , mpic->per_cpu +MPIC_IN_DRBEL_CAUSE );/* Unmask IPI interrupt */ -writel (0 , per_cpu_int_base +MPIC_INT_CLEAR_MASK ); +writel (0 , mpic->per_cpu +MPIC_INT_CLEAR_MASK ); }static void mpic_reenable_percpu (void ) {/* Re-enable per-CPU interrupts that were enabled before suspend */ for (irq_hw_number_t i =0 ; i <MPIC_MAX_PER_CPU_IRQS ; i++) { -unsigned int virq =irq_linear_revmap (mpic_domain, i); +unsigned int virq =irq_linear_revmap (mpic->domain, i);struct irq_data *d;if (!virq || !irq_percpu_is_enabled (virq))
@@ -542,7 +563,7 @@ static int mpic_cascaded_starting_cpu(unsigned int cpu) {mpic_perf_init ();mpic_reenable_percpu (); -enable_percpu_irq (parent_irq,IRQ_TYPE_NONE ); +enable_percpu_irq (mpic->parent_irq,IRQ_TYPE_NONE );return 0 ; }
@@ -571,9 +592,9 @@ static int mpic_irq_map(struct irq_domain *h, unsigned int virq,mpic_irq_mask (irq_get_irq_data (virq));if (!mpic_is_percpu_irq (hwirq)) -writel (hwirq, per_cpu_int_base +MPIC_INT_CLEAR_MASK ); +writel (hwirq, mpic->per_cpu +MPIC_INT_CLEAR_MASK );else -writel (hwirq, main_int_base +MPIC_INT_SET_ENABLE ); +writel (hwirq, mpic->base +MPIC_INT_SET_ENABLE );irq_set_status_flags (virq,IRQ_LEVEL );if (mpic_is_percpu_irq (hwirq)) {
@@ -598,12 +619,12 @@ static void mpic_handle_msi_irq(void)unsigned long cause;unsigned int i; - cause =readl_relaxed (per_cpu_int_base +MPIC_IN_DRBEL_CAUSE ); + cause =readl_relaxed (mpic->per_cpu +MPIC_IN_DRBEL_CAUSE ); cause &=msi_doorbell_mask (); -writel (~cause, per_cpu_int_base +MPIC_IN_DRBEL_CAUSE ); +writel (~cause, mpic->per_cpu +MPIC_IN_DRBEL_CAUSE );for_each_set_bit (i, &cause,BITS_PER_LONG ) -generic_handle_domain_irq (mpic_msi_inner_domain, +generic_handle_domain_irq (mpic->msi_inner_domain, i - msi_doorbell_start()); }#else
@@ -616,11 +637,11 @@ static void mpic_handle_ipi_irq(void)unsigned long cause;irq_hw_number_t i; - cause =readl_relaxed (per_cpu_int_base +MPIC_IN_DRBEL_CAUSE ); + cause =readl_relaxed (mpic->per_cpu +MPIC_IN_DRBEL_CAUSE ); cause &=IPI_DOORBELL_MASK ;for_each_set_bit (i, &cause,IPI_DOORBELL_NR ) - generic_handle_domain_irq(mpic_ipi_domain, i); + generic_handle_domain_irq(mpic->ipi_domain, i); }#else static inline void mpic_handle_ipi_irq (void ) {}
@@ -635,11 +656,11 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc)chained_irq_enter (chip, desc); - cause =readl_relaxed (per_cpu_int_base +MPIC_PPI_CAUSE ); + cause =readl_relaxed (mpic->per_cpu +MPIC_PPI_CAUSE ); cpuid =cpu_logical_map (smp_processor_id ());for_each_set_bit (i, &cause,BITS_PER_LONG ) { - irqsrc =readl_relaxed (main_int_base +MPIC_INT_SOURCE_CTL (i)); + irqsrc =readl_relaxed (mpic->base +MPIC_INT_SOURCE_CTL (i));/* Check if the interrupt is not masked on current CPU. * Test IRQ (0-1) and FIQ (8-9) mask bits.
@@ -652,7 +673,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc)continue ; } -generic_handle_domain_irq (mpic_domain, i); +generic_handle_domain_irq (mpic->domain, i); }chained_irq_exit (chip, desc);
@@ -664,14 +685,14 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs)u32 irqstat; do { - irqstat = readl_relaxed(per_cpu_int_base + MPIC_CPU_INTACK); + irqstat = readl_relaxed(mpic->per_cpu + MPIC_CPU_INTACK); i = FIELD_GET(MPIC_CPU_INTACK_IID_MASK, irqstat); if (i > 1022) break; if (i > 1) - generic_handle_domain_irq(mpic_domain, i); + generic_handle_domain_irq(mpic->domain, i); /* MSI handling */ if (i == 1)
@@ -685,7 +706,7 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs)static int mpic_suspend (void ) { - doorbell_mask_reg =readl (per_cpu_int_base +MPIC_IN_DRBEL_MASK ); + mpic->doorbell_mask =readl (mpic->per_cpu +MPIC_IN_DRBEL_MASK );return 0 ; }
@@ -695,8 +716,8 @@ static void mpic_resume(void)bool src0, src1;/* Re-enable interrupts */ -for (irq_hw_number_t i =0 ; i < mpic_domain->hwirq_max; i++) { -unsigned int virq =irq_linear_revmap (mpic_domain, i); +for (irq_hw_number_t i =0 ; i < mpic->domain->hwirq_max; i++) { +unsigned int virq =irq_linear_revmap (mpic->domain, i);struct irq_data *d;if (!virq)
@@ -706,12 +727,12 @@ static void mpic_resume(void)if (!mpic_is_percpu_irq (i)) {/* Non per-CPU interrupts */ -writel (i, per_cpu_int_base +MPIC_INT_CLEAR_MASK ); +writel (i, mpic->per_cpu +MPIC_INT_CLEAR_MASK );if (!irqd_irq_disabled (d))mpic_irq_unmask (d); }else {/* Per-CPU interrupts */ -writel (i, main_int_base +MPIC_INT_SET_ENABLE ); +writel (i, mpic->base +MPIC_INT_SET_ENABLE );/* * Re-enable on the current CPU, mpic_reenable_percpu()
@@ -723,20 +744,20 @@ static void mpic_resume(void) }/* Reconfigure doorbells for IPIs and MSIs */ -writel (doorbell_mask_reg, per_cpu_int_base +MPIC_IN_DRBEL_MASK ); +writel (mpic->doorbell_mask, mpic->per_cpu +MPIC_IN_DRBEL_MASK );if (mpic_is_ipi_available ()) { - src0 = doorbell_mask_reg &IPI_DOORBELL_MASK ; - src1 = doorbell_mask_reg &PCI_MSI_DOORBELL_MASK ; + src0 = mpic->doorbell_mask &IPI_DOORBELL_MASK ; + src1 = mpic->doorbell_mask &PCI_MSI_DOORBELL_MASK ; }else { - src0 = doorbell_mask_reg &PCI_MSI_FULL_DOORBELL_SRC0_MASK ; - src1 = doorbell_mask_reg &PCI_MSI_FULL_DOORBELL_SRC1_MASK ; + src0 = mpic->doorbell_mask &PCI_MSI_FULL_DOORBELL_SRC0_MASK ; + src1 = mpic->doorbell_mask &PCI_MSI_FULL_DOORBELL_SRC1_MASK ; }if (src0) -writel (0 , per_cpu_int_base +MPIC_INT_CLEAR_MASK ); +writel (0 , mpic->per_cpu +MPIC_INT_CLEAR_MASK );if (src1) -writel (1 , per_cpu_int_base +MPIC_INT_CLEAR_MASK ); +writel (1 , mpic->per_cpu +MPIC_INT_CLEAR_MASK );if (mpic_is_ipi_available ())mpic_ipi_resume ();
@@ -784,32 +805,32 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *parunsigned int nr_irqs;int err; - err =mpic_map_region (node,0 , &main_int_base, &phys_base); + err =mpic_map_region (node,0 , &mpic->base, &phys_base);if (err)return err; - err =mpic_map_region (node,1 , &per_cpu_int_base,NULL ); + err =mpic_map_region (node,1 , &mpic->per_cpu,NULL );if (err)return err; - nr_irqs =FIELD_GET (MPIC_INT_CONTROL_NUMINT_MASK ,readl (main_int_base +MPIC_INT_CONTROL )); + nr_irqs =FIELD_GET (MPIC_INT_CONTROL_NUMINT_MASK ,readl (mpic->base +MPIC_INT_CONTROL ));for (irq_hw_number_t i =0 ; i < nr_irqs; i++) -writel (i, main_int_base +MPIC_INT_CLEAR_ENABLE ); +writel (i, mpic->base +MPIC_INT_CLEAR_ENABLE ); - mpic_domain =irq_domain_add_linear (node, nr_irqs, &mpic_irq_ops,NULL ); -if (!mpic_domain) { + mpic->domain =irq_domain_add_linear (node, nr_irqs, &mpic_irq_ops,NULL ); +if (!mpic->domain) {pr_err ("%pOF: Unable to add IRQ domain\n" , node);return -ENOMEM ; } -irq_domain_update_bus_token (mpic_domain,DOMAIN_BUS_WIRED ); +irq_domain_update_bus_token (mpic->domain,DOMAIN_BUS_WIRED );/* -* Initialize parent_irq before calling any other functions, since it is -* used to distinguish between IPI and non-IPI platforms. +* Initialize mpic->parent_irq before calling any other functions, since +* it is used to distinguish between IPI and non-IPI platforms. */ - parent_irq =irq_of_parse_and_map (node,0 ); + mpic->parent_irq =irq_of_parse_and_map (node,0 );/* Setup for the boot CPU */ mpic_perf_init ();
@@ -821,8 +842,8 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *parreturn err; } -if (parent_irq <=0 ) { -irq_set_default_host (mpic_domain); +if (mpic->parent_irq <=0 ) { +irq_set_default_host (mpic->domain);set_handle_irq (mpic_handle_irq);#ifdef CONFIG_SMP err =mpic_ipi_init (node);
@@ -841,7 +862,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par"irqchip/armada/cascade:starting" , mpic_cascaded_starting_cpu, NULL);#endif -irq_set_chained_handler (parent_irq, mpic_handle_cascade_irq); +irq_set_chained_handler (mpic->parent_irq, mpic_handle_cascade_irq); }register_syscore_ops (&mpic_syscore_ops);
Signature · 1 line
2.44.2
PATCH v2 6/12 irqchip/armada-370-xp: Put MSI doorbell limits into the mpic structure
In reply to Marek BehúnPut the MSI doorbell limits msi_doorbell_start, msi_doorbell_size and msi_doorbell_mask into the driver private structure and get rid of the corresponding functions.
--- drivers/irqchip/irq-armada-370-xp.c | 44 ++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +22 -22
@@ -161,6 +161,10 @@* @msi_used: bitmap of used MSI numbers * @msi_lock: mutex serializing access to @msi_used * @msi_doorbell_addr: physical address of MSI doorbell register +* @msi_doorbell_mask: mask of available doorbell bits for MSIs (either PCI_MSI_DOORBELL_MASK or +* PCI_MSI_FULL_DOORBELL_MASK) +* @msi_doorbell_start: first set bit in @msi_doorbell_mask +* @msi_doorbell_size: number of set bits in @msi_doorbell_mask * @doorbell_mask: doorbell mask of MSIs and IPIs, stored on suspend, restored on resume */ struct mpic {
@@ -177,6 +181,8 @@ struct mpic {DECLARE_BITMAP (msi_used,PCI_MSI_FULL_DOORBELL_NR );struct mutex msi_lock;phys_addr_t msi_doorbell_addr; +u32 msi_doorbell_mask; +unsigned int msi_doorbell_start, msi_doorbell_size;#endif u32 doorbell_mask; };
@@ -195,21 +201,6 @@ static inline bool mpic_is_ipi_available(void)return mpic->parent_irq <=0 ; } -static inline u32 msi_doorbell_mask (void ) -{ -return mpic_is_ipi_available () ?PCI_MSI_DOORBELL_MASK :PCI_MSI_FULL_DOORBELL_MASK ; -} - -static inline unsigned int msi_doorbell_start (void ) -{ -return mpic_is_ipi_available () ?PCI_MSI_DOORBELL_START :PCI_MSI_FULL_DOORBELL_START ; -} - -static inline unsigned int msi_doorbell_size (void ) -{ -return mpic_is_ipi_available () ?PCI_MSI_DOORBELL_NR :PCI_MSI_FULL_DOORBELL_NR ; -} -static inline bool mpic_is_percpu_irq (irq_hw_number_t hwirq) {return hwirq <=MPIC_MAX_PER_CPU_IRQS ;
@@ -260,7 +251,7 @@ static void mpic_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) msg->address_lo =lower_32_bits (mpic->msi_doorbell_addr); msg->address_hi =upper_32_bits (mpic->msi_doorbell_addr); - msg->data =BIT (cpu +8 ) | (d->hwirq +msi_doorbell_start ()); + msg->data =BIT (cpu +8 ) | (d->hwirq + mpic->msi_doorbell_start); }static int mpic_msi_set_affinity (struct irq_data *d,const struct cpumask *mask,bool force)
@@ -292,7 +283,7 @@ static int mpic_msi_alloc(struct irq_domain *domain, unsigned int virq, unsignedint hwirq;mutex_lock (&mpic->msi_lock); - hwirq =bitmap_find_free_region (mpic->msi_used,msi_doorbell_size (), + hwirq =bitmap_find_free_region (mpic->msi_used, mpic->msi_doorbell_size,order_base_2 (nr_irqs));mutex_unlock (&mpic->msi_lock);
@@ -329,7 +320,7 @@ static void mpic_msi_reenable_percpu(void)/* Enable MSI doorbell mask and combined cpu local interrupt */ reg =readl (mpic->per_cpu +MPIC_IN_DRBEL_MASK ); - reg |=msi_doorbell_mask (); + reg |= mpic->msi_doorbell_mask;writel (reg, mpic->per_cpu +MPIC_IN_DRBEL_MASK );/* Unmask local doorbell interrupt */
@@ -342,7 +333,17 @@ static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_pmutex_init (&mpic->msi_lock); - mpic->msi_inner_domain =irq_domain_add_linear (NULL ,msi_doorbell_size (), +if (mpic_is_ipi_available ()) { + mpic->msi_doorbell_start =PCI_MSI_DOORBELL_START ; + mpic->msi_doorbell_size =PCI_MSI_DOORBELL_NR ; + mpic->msi_doorbell_mask =PCI_MSI_DOORBELL_MASK ; + }else { + mpic->msi_doorbell_start =PCI_MSI_FULL_DOORBELL_START ; + mpic->msi_doorbell_size =PCI_MSI_FULL_DOORBELL_NR ; + mpic->msi_doorbell_mask =PCI_MSI_FULL_DOORBELL_MASK ; + } + + mpic->msi_inner_domain =irq_domain_add_linear (NULL , mpic->msi_doorbell_size, &mpic_msi_domain_ops,NULL );if (!mpic->msi_inner_domain)return -ENOMEM ;
@@ -620,12 +621,11 @@ static void mpic_handle_msi_irq(void)unsigned int i; cause =readl_relaxed (mpic->per_cpu +MPIC_IN_DRBEL_CAUSE ); - cause &=msi_doorbell_mask (); + cause &= mpic->msi_doorbell_mask;writel (~cause, mpic->per_cpu +MPIC_IN_DRBEL_CAUSE );for_each_set_bit (i, &cause,BITS_PER_LONG ) -generic_handle_domain_irq (mpic->msi_inner_domain, - i - msi_doorbell_start()); + generic_handle_domain_irq(mpic->msi_inner_domain, i - mpic->msi_doorbell_start); }#else static void mpic_handle_msi_irq (void ) {}
Signature · 1 line
2.44.2
PATCH v2 7/12 irqchip/armada-370-xp: Pass around the driver private structure
In reply to Marek BehúnIn continuation of converting the driver to modern style, drop the global pointer to the driver private structure and instead pass it around the functions and callbacks, wherever possible. (There are 3 cases where it is not possible: mpic_cascaded_starting_cpu() and the syscore operations mpic_suspend() and mpic_resume()).
--- drivers/irqchip/irq-armada-370-xp.c | 115 +++++++++++++++++----------- 1 file changed, 70 insertions(+), 45 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +70 -45
@@ -188,9 +188,8 @@ struct mpic { };static struct mpic mpic_data; -static struct mpic *const mpic = &mpic_data; -static inline bool mpic_is_ipi_available (void ) +static inline bool mpic_is_ipi_available (struct mpic *mpic) {/* * We distinguish IPI availability in the IC by the IC not having a
@@ -213,6 +212,7 @@ static inline bool mpic_is_percpu_irq(irq_hw_number_t hwirq)*/ static void mpic_irq_mask (struct irq_data *d) { +struct mpic *mpic =irq_data_get_irq_chip_data (d);irq_hw_number_t hwirq =irqd_to_hwirq (d);if (!mpic_is_percpu_irq (hwirq))
@@ -223,6 +223,7 @@ static void mpic_irq_mask(struct irq_data *d)static void mpic_irq_unmask (struct irq_data *d) { +struct mpic *mpic =irq_data_get_irq_chip_data (d);irq_hw_number_t hwirq =irqd_to_hwirq (d);if (!mpic_is_percpu_irq (hwirq))
@@ -248,6 +249,7 @@ static struct msi_domain_info mpic_msi_domain_info = {static void mpic_compose_msi_msg (struct irq_data *d,struct msi_msg *msg) {unsigned int cpu =cpumask_first (irq_data_get_effective_affinity_mask (d)); +struct mpic *mpic =irq_data_get_irq_chip_data (d); msg->address_lo =lower_32_bits (mpic->msi_doorbell_addr); msg->address_hi =upper_32_bits (mpic->msi_doorbell_addr);
@@ -280,6 +282,7 @@ static struct irq_chip mpic_msi_bottom_irq_chip = {static int mpic_msi_alloc (struct irq_domain *domain,unsigned int virq,unsigned int nr_irqs,void *args) { +struct mpic *mpic = domain->host_data;int hwirq;mutex_lock (&mpic->msi_lock);
@@ -303,6 +306,7 @@ static int mpic_msi_alloc(struct irq_domain *domain, unsigned int virq, unsignedstatic void mpic_msi_free (struct irq_domain *domain,unsigned int virq,unsigned int nr_irqs) {struct irq_data *d =irq_domain_get_irq_data (domain, virq); +struct mpic *mpic = domain->host_data;mutex_lock (&mpic->msi_lock);bitmap_release_region (mpic->msi_used, d->hwirq,order_base_2 (nr_irqs));
@@ -314,7 +318,7 @@ static const struct irq_domain_ops mpic_msi_domain_ops = { .free = mpic_msi_free, }; -static void mpic_msi_reenable_percpu (void ) +static void mpic_msi_reenable_percpu (struct mpic *mpic) {u32 reg;
@@ -327,13 +331,14 @@ static void mpic_msi_reenable_percpu(void)writel (1 , mpic->per_cpu +MPIC_INT_CLEAR_MASK ); } -static int __init mpic_msi_init (struct device_node *node,phys_addr_t main_int_phys_base) +static int __init mpic_msi_init (struct mpic *mpic,struct device_node *node, +phys_addr_t main_int_phys_base) { mpic->msi_doorbell_addr = main_int_phys_base +MPIC_SW_TRIG_INT ;mutex_init (&mpic->msi_lock); -if (mpic_is_ipi_available ()) { +if (mpic_is_ipi_available (mpic)) { mpic->msi_doorbell_start =PCI_MSI_DOORBELL_START ; mpic->msi_doorbell_size =PCI_MSI_DOORBELL_NR ; mpic->msi_doorbell_mask =PCI_MSI_DOORBELL_MASK ;
@@ -344,7 +349,7 @@ static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_p } mpic->msi_inner_domain =irq_domain_add_linear (NULL , mpic->msi_doorbell_size, - &mpic_msi_domain_ops,NULL ); + &mpic_msi_domain_ops, mpic);if (!mpic->msi_inner_domain)return -ENOMEM ;
@@ -355,25 +360,25 @@ static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_p return -ENOMEM; } -mpic_msi_reenable_percpu (); +mpic_msi_reenable_percpu (mpic);/* Unmask low 16 MSI irqs on non-IPI platforms */ -if (!mpic_is_ipi_available ()) +if (!mpic_is_ipi_available (mpic))writel (0 , mpic->per_cpu +MPIC_INT_CLEAR_MASK );return 0 ; }#else -static __maybe_unused void mpic_msi_reenable_percpu (void ) {} +static __maybe_unused void mpic_msi_reenable_percpu (struct mpic *mpic) {} -static inline int mpic_msi_init (struct device_node *node, +static inline int mpic_msi_init (struct mpic *mpic,struct device_node *node,phys_addr_t main_int_phys_base) {return 0 ; }#endif -static void mpic_perf_init (void ) +static void mpic_perf_init (struct mpic *mpic) {u32 cpuid;
@@ -393,6 +398,7 @@ static void mpic_perf_init(void)#ifdef CONFIG_SMP static void mpic_ipi_mask (struct irq_data *d) { +struct mpic *mpic =irq_data_get_irq_chip_data (d);u32 reg; reg =readl (mpic->per_cpu +MPIC_IN_DRBEL_MASK );
@@ -402,6 +408,7 @@ static void mpic_ipi_mask(struct irq_data *d)static void mpic_ipi_unmask (struct irq_data *d) { +struct mpic *mpic =irq_data_get_irq_chip_data (d);u32 reg; reg =readl (mpic->per_cpu +MPIC_IN_DRBEL_MASK );
@@ -411,6 +418,7 @@ static void mpic_ipi_unmask(struct irq_data *d)static void mpic_ipi_send_mask (struct irq_data *d,const struct cpumask *mask) { +struct mpic *mpic =irq_data_get_irq_chip_data (d);unsigned int cpu;u32 map =0 ;
@@ -430,6 +438,8 @@ static void mpic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)static void mpic_ipi_ack (struct irq_data *d) { +struct mpic *mpic =irq_data_get_irq_chip_data (d); +writel (~BIT (d->hwirq), mpic->per_cpu +MPIC_IN_DRBEL_CAUSE ); }
@@ -464,7 +474,7 @@ static const struct irq_domain_ops mpic_ipi_domain_ops = { .free = mpic_ipi_free, }; -static void mpic_ipi_resume (void ) +static void mpic_ipi_resume (struct mpic *mpic) {for (irq_hw_number_t i =0 ; i <IPI_DOORBELL_NR ; i++) {unsigned int virq =irq_find_mapping (mpic->ipi_domain, i);
@@ -478,12 +488,12 @@ static void mpic_ipi_resume(void) } } -static int __init mpic_ipi_init (struct device_node *node) +static int __init mpic_ipi_init (struct mpic *mpic,struct device_node *node) {int base_ipi; mpic->ipi_domain =irq_domain_create_linear (of_node_to_fwnode (node),IPI_DOORBELL_NR , - &mpic_ipi_domain_ops,NULL ); + &mpic_ipi_domain_ops, mpic);if (WARN_ON (!mpic->ipi_domain))return -ENOMEM ;
@@ -499,6 +509,7 @@ static int __init mpic_ipi_init(struct device_node *node)static int mpic_set_affinity (struct irq_data *d,const struct cpumask *mask_val,bool force) { +struct mpic *mpic =irq_data_get_irq_chip_data (d);irq_hw_number_t hwirq =irqd_to_hwirq (d);unsigned int cpu;
@@ -513,12 +524,12 @@ static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,return IRQ_SET_MASK_OK ; } -static void mpic_smp_cpu_init (void ) +static void mpic_smp_cpu_init (struct mpic *mpic) {for (irq_hw_number_t i =0 ; i < mpic->domain->hwirq_max; i++)writel (i, mpic->per_cpu +MPIC_INT_SET_MASK ); -if (!mpic_is_ipi_available ()) +if (!mpic_is_ipi_available (mpic))return ;/* Disable all IPIs */
@@ -531,7 +542,7 @@ static void mpic_smp_cpu_init(void)writel (0 , mpic->per_cpu +MPIC_INT_CLEAR_MASK ); } -static void mpic_reenable_percpu (void ) +static void mpic_reenable_percpu (struct mpic *mpic) {/* Re-enable per-CPU interrupts that were enabled before suspend */ for (irq_hw_number_t i =0 ; i <MPIC_MAX_PER_CPU_IRQS ; i++) {
@@ -545,32 +556,36 @@ static void mpic_reenable_percpu(void) mpic_irq_unmask(d); } -if (mpic_is_ipi_available ()) -mpic_ipi_resume (); +if (mpic_is_ipi_available (mpic)) +mpic_ipi_resume (mpic); -mpic_msi_reenable_percpu (); +mpic_msi_reenable_percpu (mpic); }static int mpic_starting_cpu (unsigned int cpu) { -mpic_perf_init (); -mpic_smp_cpu_init (); -mpic_reenable_percpu (); +struct mpic *mpic =irq_get_default_host ()->host_data; + +mpic_perf_init (mpic); +mpic_smp_cpu_init (mpic); +mpic_reenable_percpu (mpic);return 0 ; }static int mpic_cascaded_starting_cpu (unsigned int cpu) { -mpic_perf_init (); -mpic_reenable_percpu (); +struct mpic *mpic = &mpic_data; + +mpic_perf_init (mpic); +mpic_reenable_percpu (mpic);enable_percpu_irq (mpic->parent_irq,IRQ_TYPE_NONE );return 0 ; }#else -static void mpic_smp_cpu_init (void ) {} -static void mpic_ipi_resume (void ) {} +static void mpic_smp_cpu_init (struct mpic *mpic) {} +static void mpic_ipi_resume (struct mpic *mpic) {}#endif static struct irq_chip mpic_irq_chip = {
@@ -584,13 +599,16 @@ static struct irq_chip mpic_irq_chip = { .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND, }; -static int mpic_irq_map (struct irq_domain *h,unsigned int virq, -irq_hw_number_t hwirq) +static int mpic_irq_map (struct irq_domain *domain,unsigned int virq,irq_hw_number_t hwirq) { +struct mpic *mpic = domain->host_data; +/* IRQs 0 and 1 cannot be mapped, they are handled internally */ if (hwirq <=1 )return -EINVAL ; +irq_set_chip_data (virq, mpic); +mpic_irq_mask (irq_get_irq_data (virq));if (!mpic_is_percpu_irq (hwirq))writel (hwirq, mpic->per_cpu +MPIC_INT_CLEAR_MASK );
@@ -615,7 +633,7 @@ static const struct irq_domain_ops mpic_irq_ops = { };#ifdef CONFIG_PCI_MSI -static void mpic_handle_msi_irq (void ) +static void mpic_handle_msi_irq (struct mpic *mpic) {unsigned long cause;unsigned int i;
@@ -628,11 +646,11 @@ static void mpic_handle_msi_irq(void)generic_handle_domain_irq (mpic->msi_inner_domain, i - mpic->msi_doorbell_start); }#else -static void mpic_handle_msi_irq (void ) {} +static void mpic_handle_msi_irq (struct mpic *mpic) {}#endif #ifdef CONFIG_SMP -static void mpic_handle_ipi_irq (void ) +static void mpic_handle_ipi_irq (struct mpic *mpic) {unsigned long cause;irq_hw_number_t i;
@@ -644,11 +662,12 @@ static void mpic_handle_ipi_irq(void) generic_handle_domain_irq(mpic->ipi_domain, i); }#else -static inline void mpic_handle_ipi_irq (void ) {} +static inline void mpic_handle_ipi_irq (struct mpic *mpic) {}#endif static void mpic_handle_cascade_irq (struct irq_desc *desc) { +struct mpic *mpic =irq_desc_get_handler_data (desc);struct irq_chip *chip =irq_desc_get_chip (desc);unsigned long cause;u32 irqsrc, cpuid;
@@ -669,7 +688,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc)continue ;if (i ==0 || i ==1 ) { -mpic_handle_msi_irq (); +mpic_handle_msi_irq (mpic);continue ; }
@@ -681,6 +700,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc) static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs) { +struct mpic *mpic =irq_get_default_host ()->host_data;irq_hw_number_t i;u32 irqstat;
@@ -696,16 +716,18 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs)/* MSI handling */ if (i ==1 ) -mpic_handle_msi_irq (); +mpic_handle_msi_irq (mpic);/* IPI Handling */ if (i ==0 ) -mpic_handle_ipi_irq (); +mpic_handle_ipi_irq (mpic); }while (1 ); }static int mpic_suspend (void ) { +struct mpic *mpic = &mpic_data; + mpic->doorbell_mask =readl (mpic->per_cpu +MPIC_IN_DRBEL_MASK );return 0 ;
@@ -713,6 +735,7 @@ static int mpic_suspend(void)static void mpic_resume (void ) { +struct mpic *mpic = &mpic_data;bool src0, src1;/* Re-enable interrupts */
@@ -746,7 +769,7 @@ static void mpic_resume(void)/* Reconfigure doorbells for IPIs and MSIs */ writel (mpic->doorbell_mask, mpic->per_cpu +MPIC_IN_DRBEL_MASK ); -if (mpic_is_ipi_available ()) { +if (mpic_is_ipi_available (mpic)) { src0 = mpic->doorbell_mask &IPI_DOORBELL_MASK ; src1 = mpic->doorbell_mask &PCI_MSI_DOORBELL_MASK ; }else {
@@ -759,8 +782,8 @@ static void mpic_resume(void)if (src1)writel (1 , mpic->per_cpu +MPIC_INT_CLEAR_MASK ); -if (mpic_is_ipi_available ()) -mpic_ipi_resume (); +if (mpic_is_ipi_available (mpic)) +mpic_ipi_resume (mpic); }static struct syscore_ops mpic_syscore_ops = {
@@ -801,6 +824,7 @@ static int __init mpic_map_region(struct device_node *np, int index,static int __init mpic_of_init (struct device_node *node,struct device_node *parent) { +struct mpic *mpic = &mpic_data;phys_addr_t phys_base;unsigned int nr_irqs;int err;
@@ -818,7 +842,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *parfor (irq_hw_number_t i =0 ; i < nr_irqs; i++)writel (i, mpic->base +MPIC_INT_CLEAR_ENABLE ); - mpic->domain =irq_domain_add_linear (node, nr_irqs, &mpic_irq_ops,NULL ); + mpic->domain =irq_domain_add_linear (node, nr_irqs, &mpic_irq_ops, mpic);if (!mpic->domain) {pr_err ("%pOF: Unable to add IRQ domain\n" , node);return -ENOMEM ;
@@ -833,10 +857,10 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par mpic->parent_irq =irq_of_parse_and_map (node,0 );/* Setup for the boot CPU */ -mpic_perf_init (); -mpic_smp_cpu_init (); +mpic_perf_init (mpic); +mpic_smp_cpu_init (mpic); - err =mpic_msi_init (node, phys_base); + err =mpic_msi_init (mpic, node, phys_base);if (err) {pr_err ("%pOF: Unable to initialize MSI domain\n" , node);return err;
@@ -846,7 +870,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *parirq_set_default_host (mpic->domain);set_handle_irq (mpic_handle_irq);#ifdef CONFIG_SMP - err =mpic_ipi_init (node); + err =mpic_ipi_init (mpic, node);if (err) {pr_err ("%pOF: Unable to initialize IPI domain\n" , node);return err;
@@ -862,7 +886,8 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par"irqchip/armada/cascade:starting" , mpic_cascaded_starting_cpu, NULL);#endif -irq_set_chained_handler (mpic->parent_irq, mpic_handle_cascade_irq); +irq_set_chained_handler_and_data (mpic->parent_irq, + mpic_handle_cascade_irq, mpic); }register_syscore_ops (&mpic_syscore_ops);
Signature · 1 line
2.44.2
PATCH v2 8/12 irqchip/armada-370-xp: Dynamically allocate the driver private structure
In reply to Marek BehúnDynamically allocate the driver private structure. This concludes the conversion of this driver to modern style.
--- drivers/irqchip/irq-armada-370-xp.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +11 -5
@@ -187,7 +187,7 @@ struct mpic {u32 doorbell_mask; }; -static struct mpic mpic_data; +static struct mpic *mpic_data__ro_after_init ;static inline bool mpic_is_ipi_available (struct mpic *mpic) {
@@ -575,7 +575,7 @@ static int mpic_starting_cpu(unsigned int cpu)static int mpic_cascaded_starting_cpu (unsigned int cpu) { -struct mpic *mpic = &mpic_data; +struct mpic *mpic = mpic_data;mpic_perf_init (mpic);mpic_reenable_percpu (mpic);
@@ -726,7 +726,7 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs)static int mpic_suspend (void ) { -struct mpic *mpic = &mpic_data; +struct mpic *mpic = mpic_data; mpic->doorbell_mask =readl (mpic->per_cpu +MPIC_IN_DRBEL_MASK );
@@ -735,7 +735,7 @@ static int mpic_suspend(void)static void mpic_resume (void ) { -struct mpic *mpic = &mpic_data; +struct mpic *mpic = mpic_data;bool src0, src1;/* Re-enable interrupts */
@@ -824,11 +824,17 @@ static int __init mpic_map_region(struct device_node *np, int index,static int __init mpic_of_init (struct device_node *node,struct device_node *parent) { -struct mpic *mpic = &mpic_data;phys_addr_t phys_base;unsigned int nr_irqs; +struct mpic *mpic;int err; + mpic =kzalloc (sizeof (*mpic),GFP_KERNEL ); +if (WARN_ON (!mpic)) +return -ENOMEM ; + + mpic_data = mpic; + err =mpic_map_region (node,0 , &mpic->base, &phys_base);if (err)return err;
Signature · 1 line
2.44.2
PATCH v2 9/12 irqchip/armada-370-xp: Fix reenabling last per-CPU interrupt
In reply to Marek BehúnThe number of per-CPU interrupts is 29 (0 to 28). This is described by the constant MPIC_MAX_PER_CPU_IRQS, set to 28 (the maximum per-CPU interrupt).
Commit 0fa4ce746d1d ("irqchip/armada-370-xp: Re-enable per-CPU interrupts at resume time") used the constant incorrectly in the for-loop, it used the operator < instead of <=, causing it to iterate only the first 28 interrupts (0 to 27), ignoring the last, 28th, per-CPU interrupt.
To avoid this kind of confusions, fix this issue by renaming the constant to MPIC_PER_CPU_IRQS_NR and set it to 29, the number of per-CPU IRQs. Update its use in mpic_is_percpu_irq() accordingly.
---
Thomas, I have added the stable+noautosel Cc so that this patch won't be autoselected for stable releases, as described in Documentation/process/stable-kernel-rules.rst. This way I can keep the Fixes tag.
--- drivers/irqchip/irq-armada-370-xp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +3 -3
@@ -133,7 +133,7 @@#define MPIC_INT_FABRIC_MASK 0x54#define MPIC_INT_CAUSE_PERF (cpu) BIT(cpu) -#define MPIC_MAX_PER_CPU_IRQS 28 +#define MPIC_PER_CPU_IRQS_NR 29/* IPI and MSI interrupt definitions for IPI platforms */ #define IPI_DOORBELL_NR 8
@@ -202,7 +202,7 @@ static inline bool mpic_is_ipi_available(struct mpic *mpic)static inline bool mpic_is_percpu_irq (irq_hw_number_t hwirq) { -return hwirq <=MPIC_MAX_PER_CPU_IRQS ; +return hwirq <MPIC_PER_CPU_IRQS_NR ; }/*
@@ -545,7 +545,7 @@ static void mpic_smp_cpu_init(struct mpic *mpic)static void mpic_reenable_percpu (struct mpic *mpic) {/* Re-enable per-CPU interrupts that were enabled before suspend */ -for (irq_hw_number_t i =0 ; i <MPIC_MAX_PER_CPU_IRQS ; i++) { +for (irq_hw_number_t i =0 ; i <MPIC_PER_CPU_IRQS_NR ; i++) {unsigned int virq =irq_linear_revmap (mpic->domain, i);struct irq_data *d;
Signature · 1 line
2.44.2
PATCH v2 10/12 irqchip/armada-370-xp: Iterate only valid bits of the per-CPU interrupt cause register
In reply to Marek BehúnUse MPIC_PER_CPU_IRQS_NR (29) bound instead of BITS_PER_LONG (32) when iterating the bits of the per-CPU interrupt cause register, since there are only 29 per-CPU interrupts. The top 3 bits are always zero anyway.
--- drivers/irqchip/irq-armada-370-xp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/irqchip/irq-armada-370-xp.c +1 -1
@@ -678,7 +678,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc) cause =readl_relaxed (mpic->per_cpu +MPIC_PPI_CAUSE ); cpuid =cpu_logical_map (smp_processor_id ()); -for_each_set_bit (i, &cause,BITS_PER_LONG ) { +for_each_set_bit (i, &cause,MPIC_PER_CPU_IRQS_NR ) { irqsrc =readl_relaxed (mpic->base +MPIC_INT_SOURCE_CTL (i));/* Check if the interrupt is not masked on current CPU.
Signature · 1 line
2.44.2
PATCH v2 11/12 irqchip/armada-370-xp: Allow mapping only per-CPU interrupts
In reply to Marek BehúnOn platforms where MPIC is not the top-level interrupt controller the driver currently only supports handling of the per-CPU interrupts (the first 29 interrupts). This is obvious from the code of mpic_handle_cascade_irq(), which reads only one cause register.
Bound the number of available interrupts in the IRQ domain to 29 for these platforms.
The corresponding device-trees refer only to per-CPU interrupts via MPIC, the other interrupts are referred to via GIC.
--- drivers/irqchip/irq-armada-370-xp.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
drivers/irqchip/irq-armada-370-xp.c +13 -6
@@ -848,6 +848,19 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *parfor (irq_hw_number_t i =0 ; i < nr_irqs; i++)writel (i, mpic->base +MPIC_INT_CLEAR_ENABLE ); +/* +* Initialize mpic->parent_irq before calling any other functions, since +* it is used to distinguish between IPI and non-IPI platforms. +*/ + mpic->parent_irq =irq_of_parse_and_map (node,0 ); + +/* +* On non-IPI platforms the driver currently supports only the per-CPU +* interrupts (the first 29 interrupts). See mpic_handle_cascade_irq(). +*/ +if (!mpic_is_ipi_available (mpic)) + nr_irqs =MPIC_PER_CPU_IRQS_NR ; + mpic->domain =irq_domain_add_linear (node, nr_irqs, &mpic_irq_ops, mpic);if (!mpic->domain) {pr_err ("%pOF: Unable to add IRQ domain\n" , node);
@@ -856,12 +869,6 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *parirq_domain_update_bus_token (mpic->domain,DOMAIN_BUS_WIRED ); -/* -* Initialize mpic->parent_irq before calling any other functions, since -* it is used to distinguish between IPI and non-IPI platforms. -*/ - mpic->parent_irq =irq_of_parse_and_map (node,0 ); -/* Setup for the boot CPU */ mpic_perf_init (mpic);mpic_smp_cpu_init (mpic);
Signature · 1 line
2.44.2
PATCH v2 12/12 irqchip/armada-370-xp: Use the mpic_is_ipi_available() helper in one more case
In reply to Marek BehúnThere is one last case where we can use the helper function mpic_is_ipi_available() instead of hardcoding the condition.
--- drivers/irqchip/irq-armada-370-xp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/irqchip/irq-armada-370-xp.c +1 -1
@@ -879,7 +879,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *parreturn err; } -if (mpic->parent_irq <=0 ) { +if (mpic_is_ipi_available (mpic)) {irq_set_default_host (mpic->domain);set_handle_irq (mpic_handle_irq);#ifdef CONFIG_SMP
Signature · 1 line
2.44.2