linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH v2 08/11] irqdomain: Refactor irq_domain_associate_many()
       [not found] ` <1371244086-9189-9-git-send-email-grant.likely@linaro.org>
@ 2013-06-18  1:20   ` Michael Neuling
  2013-06-18  1:25     ` Michael Neuling
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Neuling @ 2013-06-18  1:20 UTC (permalink / raw)
  To: Grant Likely
  Cc: sfr, linux-kernel, Linux PPC dev, linux-next, Thomas Gleixner

Grant,

In next-20130617 we are getting the below crash on POWER7.  Bisecting,
points to this patch (d39046ec72 in next)

Any clues?

Mikey


Using pSeries machine description
Page sizes from device-tree:
base_shift=12: shift=12, sllp=0x0000, avpnm=0x00000000, tlbiel=1, penc=0
base_shift=24: shift=24, sllp=0x0100, avpnm=0x00000001, tlbiel=0, penc=0
base_shift=16: shift=16, sllp=0x0110, avpnm=0x00000000, tlbiel=1, penc=1
base_shift=20: shift=20, sllp=0x0111, avpnm=0x00000000, tlbiel=0, penc=2
base_shift=34: shift=34, sllp=0x0120, avpnm=0x000007ff, tlbiel=0, penc=3
Using 1TB segments
Found initrd at 0xc000000002e60000:0xc000000002e60600
CPU maps initialized for 1 thread per core
Starting Linux PPC64 #48 SMP Tue Jun 18 11:10:17 EST 2013
-----------------------------------------------------
ppc64_pft_size                = 0x0
physicalMemorySize            = 0x80000000
htab_address                  = 0xc00000007fe00000
htab_hash_mask                = 0x3fff
-----------------------------------------------------
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpuacct
Linux version 3.10.0-rc5-14354-gd39046e (mikey@ka1) (gcc version 4.6.0 (GCC) ) #48 SMP Tue Jun 18 11:10:17 EST 2013
[boot]0012 Setup Arch
Zone ranges:
  DMA      [mem 0x00000000-0x7fffffff]
  Normal   empty
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x00000000-0x7fffffff]
[boot]0015 Setup Done
PERCPU: Embedded 2 pages/cpu @c000000002100000 s88448 r0 d42624 u1048576
Built 1 zonelists in Node order, mobility grouping on.  Total pages: 32740
Policy zone: DMA
Kernel command line: ipr.enabled=0
PID hash table entries: 4096 (order: -1, 32768 bytes)
Sorting __ex_table...
freeing bootmem node 0
Memory: 2061696k/2097152k available (11840k kernel code, 35456k reserved, 1792k data, 1072k bss, 704k init)
SLUB: HWalign=128, Order=0-3, MinObjects=0, CPUs=1, Nodes=256
Hierarchical RCU implementation.
	RCU restricting CPUs from NR_CPUS=2048 to nr_cpu_ids=1.
NR_IRQS:512 nr_irqs:512 16
error: reading the clock failed (-1)
clocksource: timebase mult[86bca1b] shift[23] registered
Console: colour dummy device 80x25
console [tty0] enabled
console [hvc0] enabled
pid_max: default: 32768 minimum: 301
Dentry cache hash table entries: 262144 (order: 5, 2097152 bytes)
Inode-cache hash table entries: 131072 (order: 4, 1048576 bytes)
Mount-cache hash table entries: 4096
Initializing cgroup subsys devices
Initializing cgroup subsys freezer
error: hwirq 0x2 is too large for (null)
------------[ cut here ]------------
WARNING: at /scratch/mikey/src/linux-next/kernel/irq/irqdomain.c:276
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.0-rc5-14354-gd39046e #48
task: c00000007e500000 ti: c00000007e520000 task.ti: c00000007e520000
NIP: c00000000011433c LR: c000000000114338 CTR: c000000000422310
REGS: c00000007e523780 TRAP: 0700   Not tainted  (3.10.0-rc5-14354-gd39046e)
MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI>  CR: 28000084  XER: 02000000
SOFTE: 1
CFAR: c0000000007b0ab8

GPR00: c000000000114338 c00000007e523a00 c000000000cb9570 0000000000000028 
GPR04: 0000000000000000 0000000000000043 ffffffffffffffff 0000000000000000 
GPR08: 076507200766076f c000000000be3790 0000000000000720 0000000000000000 
GPR12: 0000000028000082 c00000000fe00000 c00000000000be60 0000000000000000 
GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
GPR20: 0000000000000000 0000000000000000 0000000000000000 c000000000b704b0 
GPR24: c000000000d44a80 c000000000cb9570 0000000000000010 0000000000000002 
GPR28: c00000007e0c0000 0000000000000000 c00000007e0c0000 c00000007e052400 
NIP [c00000000011433c] .irq_domain_associate+0x1ec/0x260
LR [c000000000114338] .irq_domain_associate+0x1e8/0x260
PACATMSCRATCH [9000000032009032]
Call Trace:
[c00000007e523a00] [c000000000114338] .irq_domain_associate+0x1e8/0x260 (unreliable)
[c00000007e523aa0] [c000000000114bf0] .irq_create_mapping+0xa0/0x170
[c00000007e523b30] [c000000000af4574] .xics_smp_probe+0x38/0xa4
[c00000007e523ba0] [c000000000af7af0] .pSeries_smp_probe+0x10/0x68
[c00000007e523c10] [c000000000aed740] .smp_prepare_cpus+0x20c/0x244
[c00000007e523cd0] [c000000000ae44c0] .kernel_init_freeable+0x138/0x328
[c00000007e523db0] [c00000000000be7c] .kernel_init+0x1c/0x120
[c00000007e523e30] [c00000000000a05c] .ret_from_kernel_thread+0x5c/0x80
Instruction dump:
482ca915 60000000 7fa3eb78 4868ea09 60000000 4bffff7c 3c62ffd5 e8bc0010 
7f6407b4 3863c108 4869c731 60000000 <0fe00000> 3ba0ffea 4bffff7c 3c62ffd5 
---[ end trace 31fd0ba7d8756001 ]---
------------[ cut here ]------------
kernel BUG at /scratch/mikey/src/linux-next/arch/powerpc/sysdev/xics/xics-common.c:134!
cpu 0x0: Vector: 700 (Program Check) at [c00000007e5238b0]
    pc: c000000000af4580: .xics_smp_probe+0x44/0xa4
    lr: c000000000af4574: .xics_smp_probe+0x38/0xa4
    sp: c00000007e523b30
   msr: 9000000000029032
  current = 0xc00000007e500000
  paca    = 0xc00000000fe00000	 softe: 0	 irq_happened: 0x01
    pid   = 1, comm = swapper/0
kernel BUG at /scratch/mikey/src/linux-next/arch/powerpc/sysdev/xics/xics-common.c:134!
enter ? for help
[c00000007e523ba0] c000000000af7af0 .pSeries_smp_probe+0x10/0x68
[c00000007e523c10] c000000000aed740 .smp_prepare_cpus+0x20c/0x244
[c00000007e523cd0] c000000000ae44c0 .kernel_init_freeable+0x138/0x328
[c00000007e523db0] c00000000000be7c .kernel_init+0x1c/0x120
[c00000007e523e30] c00000000000a05c .ret_from_kernel_thread+0x5c/0x80
0:mon>  <no input ...>
Oops: Exception in kernel mode, sig: 5 [#1]
SMP NR_CPUS=2048 NUMA pSeries
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W    3.10.0-rc5-14354-gd39046e #48
task: c00000007e500000 ti: c00000007e520000 task.ti: c00000007e520000
NIP: c000000000af4580 LR: c000000000af4574 CTR: 0000000000000002
REGS: c00000007e5238b0 TRAP: 0700   Tainted: G        W     (3.10.0-rc5-14354-gd39046e)
MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI>  CR: 28000084  XER: 02000000
SOFTE: 1
CFAR: c000000000114c1c

GPR00: 0000000000000001 c00000007e523b30 c000000000cb9570 0000000000000000 
GPR04: 0000000000000010 0000000000020000 c00000007e052600 c000000000dcdd10 
GPR08: c000000000b85ac8 fffffffffffeffff 0000000000000001 000000000001ffff 
GPR12: 0000000088000084 c00000000fe00000 c00000000000be60 0000000000000000 
GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
GPR20: 0000000000000000 0000000000000000 0000000000000000 c000000000b704b0 
GPR24: c000000000d44a80 c000000000cb9570 c000000000cb9570 c000000000b703b0 
GPR28: c000000000b704b0 c000000000d40858 0000000000004000 0000000000000800 
NIP [c000000000af4580] .xics_smp_probe+0x44/0xa4
LR [c000000000af4574] .xics_smp_probe+0x38/0xa4
PACATMSCRATCH [9000000000029032]
Call Trace:
[c00000007e523b30] [c000000000af4574] .xics_smp_probe+0x38/0xa4 (unreliable)
[c00000007e523ba0] [c000000000af7af0] .pSeries_smp_probe+0x10/0x68
[c00000007e523c10] [c000000000aed740] .smp_prepare_cpus+0x20c/0x244
[c00000007e523cd0] [c000000000ae44c0] .kernel_init_freeable+0x138/0x328
[c00000007e523db0] [c00000000000be7c] .kernel_init+0x1c/0x120
[c00000007e523e30] [c00000000000a05c] .ret_from_kernel_thread+0x5c/0x80
Instruction dump:
39290f80 38800002 e86b0010 f8010010 f821ff91 e80a0028 e9290000 f8090008 
4b6205e1 60000000 7c600074 7800d182 <0b000000> 3d22000d 3ce2ffd3 3929fde0 
---[ end trace 31fd0ba7d8756002 ]---



> Originally, irq_domain_associate_many() was designed to unwind the
> mapped irqs on a failure of any individual association. However, that
> proved to be a problem with certain IRQ controllers. Some of them only
> support a subset of irqs, and will fail when attempting to map a
> reserved IRQ. In those cases we want to map as many IRQs as possible, so
> instead it is better for irq_domain_associate_many() to make a
> best-effort attempt to map irqs, but not fail if any or all of them
> don't succeed. If a caller really cares about how many irqs got
> associated, then it should instead go back and check that all of the
> irqs is cares about were mapped.
> 
> The original design open-coded the individual association code into the
> body of irq_domain_associate_many(), but with no longer needing to
> unwind associations, the code becomes simpler to split out
> irq_domain_associate() to contain the bulk of the logic, and
> irq_domain_associate_many() to be a simple loop wrapper.
> 
> This patch also adds a new error check to the associate path to make
> sure it isn't called for an irq larger than the controller can handle,
> and adds locking so that the irq_domain_mutex is held while setting up a
> new association.
> 
> v2: Fixup x86 warning. irq_domain_associate_many() no longer returns an
>     error code, but reports errors to the printk log directly. In the
>     majority of cases we don't actually want to fail if there is a
>     problem, but rather log it and still try to boot the system.
> 
> Signed-off-by: Grant Likely <grant.likely@linaro.org>
> ---
>  arch/x86/kernel/devicetree.c |   4 +-
>  include/linux/irqdomain.h    |  22 +++--
>  kernel/irq/irqdomain.c       | 185 +++++++++++++++++++++----------------------
>  3 files changed, 102 insertions(+), 109 deletions(-)
> 
> diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
> index b158152..4934890 100644
> --- a/arch/x86/kernel/devicetree.c
> +++ b/arch/x86/kernel/devicetree.c
> @@ -364,9 +364,7 @@ static void dt_add_ioapic_domain(unsigned int ioapic_num,
>  		 * and assigned so we can keep the 1:1 mapping which the ioapic
>  		 * is having.
>  		 */
> -		ret = irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
> -		if (ret)
> -			pr_err("Error mapping legacy IRQs: %d\n", ret);
> +		irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
>  
>  		if (num > NR_IRQS_LEGACY) {
>  			ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY,
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index fd4b26f..f9e8e06 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -103,6 +103,7 @@ struct irq_domain {
>  	struct irq_domain_chip_generic *gc;
>  
>  	/* reverse map data. The linear map gets appended to the irq_domain */
> +	irq_hw_number_t hwirq_max;
>  	unsigned int revmap_direct_max_irq;
>  	unsigned int revmap_size;
>  	struct radix_tree_root revmap_tree;
> @@ -110,8 +111,8 @@ struct irq_domain {
>  };
>  
>  #ifdef CONFIG_IRQ_DOMAIN
> -struct irq_domain *__irq_domain_add(struct device_node *of_node,
> -				    int size, int direct_max,
> +struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
> +				    irq_hw_number_t hwirq_max, int direct_max,
>  				    const struct irq_domain_ops *ops,
>  				    void *host_data);
>  struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
> @@ -140,14 +141,14 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no
>  					 const struct irq_domain_ops *ops,
>  					 void *host_data)
>  {
> -	return __irq_domain_add(of_node, size, 0, ops, host_data);
> +	return __irq_domain_add(of_node, size, size, 0, ops, host_data);
>  }
>  static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
>  					 unsigned int max_irq,
>  					 const struct irq_domain_ops *ops,
>  					 void *host_data)
>  {
> -	return __irq_domain_add(of_node, 0, max_irq, ops, host_data);
> +	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data);
>  }
>  static inline struct irq_domain *irq_domain_add_legacy_isa(
>  				struct device_node *of_node,
> @@ -166,14 +167,11 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
>  
>  extern void irq_domain_remove(struct irq_domain *host);
>  
> -extern int irq_domain_associate_many(struct irq_domain *domain,
> -				     unsigned int irq_base,
> -				     irq_hw_number_t hwirq_base, int count);
> -static inline int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
> -					irq_hw_number_t hwirq)
> -{
> -	return irq_domain_associate_many(domain, irq, hwirq, 1);
> -}
> +extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
> +					irq_hw_number_t hwirq);
> +extern void irq_domain_associate_many(struct irq_domain *domain,
> +				      unsigned int irq_base,
> +				      irq_hw_number_t hwirq_base, int count);
>  
>  extern unsigned int irq_create_mapping(struct irq_domain *host,
>  				       irq_hw_number_t hwirq);
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 280b804..80e9249 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -35,8 +35,8 @@ static struct irq_domain *irq_default_domain;
>   * register allocated irq_domain with irq_domain_register().  Returns pointer
>   * to IRQ domain, or NULL on failure.
>   */
> -struct irq_domain *__irq_domain_add(struct device_node *of_node,
> -				    int size, int direct_max,
> +struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
> +				    irq_hw_number_t hwirq_max, int direct_max,
>  				    const struct irq_domain_ops *ops,
>  				    void *host_data)
>  {
> @@ -52,6 +52,7 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node,
>  	domain->ops = ops;
>  	domain->host_data = host_data;
>  	domain->of_node = of_node_get(of_node);
> +	domain->hwirq_max = hwirq_max;
>  	domain->revmap_size = size;
>  	domain->revmap_direct_max_irq = direct_max;
>  
> @@ -126,7 +127,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
>  {
>  	struct irq_domain *domain;
>  
> -	domain = __irq_domain_add(of_node, size, 0, ops, host_data);
> +	domain = __irq_domain_add(of_node, size, size, 0, ops, host_data);
>  	if (!domain)
>  		return NULL;
>  
> @@ -139,7 +140,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
>  				pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
>  					first_irq);
>  		}
> -		WARN_ON(irq_domain_associate_many(domain, first_irq, 0, size));
> +		irq_domain_associate_many(domain, first_irq, 0, size);
>  	}
>  
>  	return domain;
> @@ -170,11 +171,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
>  {
>  	struct irq_domain *domain;
>  
> -	domain = __irq_domain_add(of_node, first_hwirq + size, 0, ops, host_data);
> +	domain = __irq_domain_add(of_node, first_hwirq + size,
> +				  first_hwirq + size, 0, ops, host_data);
>  	if (!domain)
>  		return NULL;
>  
> -	WARN_ON(irq_domain_associate_many(domain, first_irq, first_hwirq, size));
> +	irq_domain_associate_many(domain, first_irq, first_hwirq, size);
>  
>  	return domain;
>  }
> @@ -228,109 +230,109 @@ void irq_set_default_host(struct irq_domain *domain)
>  }
>  EXPORT_SYMBOL_GPL(irq_set_default_host);
>  
> -static void irq_domain_disassociate_many(struct irq_domain *domain,
> -					 unsigned int irq_base, int count)
> +static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
>  {
> -	/*
> -	 * disassociate in reverse order;
> -	 * not strictly necessary, but nice for unwinding
> -	 */
> -	while (count--) {
> -		int irq = irq_base + count;
> -		struct irq_data *irq_data = irq_get_irq_data(irq);
> -		irq_hw_number_t hwirq;
> +	struct irq_data *irq_data = irq_get_irq_data(irq);
> +	irq_hw_number_t hwirq;
>  
> -		if (WARN_ON(!irq_data || irq_data->domain != domain))
> -			continue;
> +	if (WARN(!irq_data || irq_data->domain != domain,
> +		 "virq%i doesn't exist; cannot disassociate\n", irq))
> +		return;
>  
> -		hwirq = irq_data->hwirq;
> -		irq_set_status_flags(irq, IRQ_NOREQUEST);
> +	hwirq = irq_data->hwirq;
> +	irq_set_status_flags(irq, IRQ_NOREQUEST);
>  
> -		/* remove chip and handler */
> -		irq_set_chip_and_handler(irq, NULL, NULL);
> +	/* remove chip and handler */
> +	irq_set_chip_and_handler(irq, NULL, NULL);
>  
> -		/* Make sure it's completed */
> -		synchronize_irq(irq);
> +	/* Make sure it's completed */
> +	synchronize_irq(irq);
>  
> -		/* Tell the PIC about it */
> -		if (domain->ops->unmap)
> -			domain->ops->unmap(domain, irq);
> -		smp_mb();
> +	/* Tell the PIC about it */
> +	if (domain->ops->unmap)
> +		domain->ops->unmap(domain, irq);
> +	smp_mb();
>  
> -		irq_data->domain = NULL;
> -		irq_data->hwirq = 0;
> +	irq_data->domain = NULL;
> +	irq_data->hwirq = 0;
>  
> -		/* Clear reverse map for this hwirq */
> -		if (hwirq < domain->revmap_size) {
> -			domain->linear_revmap[hwirq] = 0;
> -		} else {
> -			mutex_lock(&revmap_trees_mutex);
> -			radix_tree_delete(&domain->revmap_tree, hwirq);
> -			mutex_unlock(&revmap_trees_mutex);
> -		}
> +	/* Clear reverse map for this hwirq */
> +	if (hwirq < domain->revmap_size) {
> +		domain->linear_revmap[hwirq] = 0;
> +	} else {
> +		mutex_lock(&revmap_trees_mutex);
> +		radix_tree_delete(&domain->revmap_tree, hwirq);
> +		mutex_unlock(&revmap_trees_mutex);
>  	}
>  }
>  
> -int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
> -			      irq_hw_number_t hwirq_base, int count)
> +int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
> +			 irq_hw_number_t hwirq)
>  {
> -	unsigned int virq = irq_base;
> -	irq_hw_number_t hwirq = hwirq_base;
> -	int i, ret;
> +	struct irq_data *irq_data = irq_get_irq_data(virq);
> +	int ret;
>  
> -	pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
> -		of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
> +	if (WARN(hwirq >= domain->hwirq_max,
> +		 "error: hwirq 0x%x is too large for %s\n", (int)hwirq, domain->name))
> +		return -EINVAL;
> +	if (WARN(!irq_data, "error: virq%i is not allocated", virq))
> +		return -EINVAL;
> +	if (WARN(irq_data->domain, "error: virq%i is already associated", virq))
> +		return -EINVAL;
>  
> -	for (i = 0; i < count; i++) {
> -		struct irq_data *irq_data = irq_get_irq_data(virq + i);
> -
> -		if (WARN(!irq_data, "error: irq_desc not allocated; "
> -			 "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i))
> -			return -EINVAL;
> -		if (WARN(irq_data->domain, "error: irq_desc already associated; "
> -			 "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i))
> -			return -EINVAL;
> -	};
> -
> -	for (i = 0; i < count; i++, virq++, hwirq++) {
> -		struct irq_data *irq_data = irq_get_irq_data(virq);
> -
> -		irq_data->hwirq = hwirq;
> -		irq_data->domain = domain;
> -		if (domain->ops->map) {
> -			ret = domain->ops->map(domain, virq, hwirq);
> -			if (ret != 0) {
> -				/*
> -				 * If map() returns -EPERM, this interrupt is protected
> -				 * by the firmware or some other service and shall not
> -				 * be mapped. Don't bother telling the user about it.
> -				 */
> -				if (ret != -EPERM) {
> -					pr_info("%s didn't like hwirq-0x%lx to VIRQ%i mapping (rc=%d)\n",
> -					       domain->name, hwirq, virq, ret);
> -				}
> -				irq_data->domain = NULL;
> -				irq_data->hwirq = 0;
> -				continue;
> +	mutex_lock(&irq_domain_mutex);
> +	irq_data->hwirq = hwirq;
> +	irq_data->domain = domain;
> +	if (domain->ops->map) {
> +		ret = domain->ops->map(domain, virq, hwirq);
> +		if (ret != 0) {
> +			/*
> +			 * If map() returns -EPERM, this interrupt is protected
> +			 * by the firmware or some other service and shall not
> +			 * be mapped. Don't bother telling the user about it.
> +			 */
> +			if (ret != -EPERM) {
> +				pr_info("%s didn't like hwirq-0x%lx to VIRQ%i mapping (rc=%d)\n",
> +				       domain->name, hwirq, virq, ret);
>  			}
> -			/* If not already assigned, give the domain the chip's name */
> -			if (!domain->name && irq_data->chip)
> -				domain->name = irq_data->chip->name;
> +			irq_data->domain = NULL;
> +			irq_data->hwirq = 0;
> +			mutex_unlock(&irq_domain_mutex);
> +			return ret;
>  		}
>  
> -		if (hwirq < domain->revmap_size) {
> -			domain->linear_revmap[hwirq] = virq;
> -		} else {
> -			mutex_lock(&revmap_trees_mutex);
> -			radix_tree_insert(&domain->revmap_tree, hwirq, irq_data);
> -			mutex_unlock(&revmap_trees_mutex);
> -		}
> +		/* If not already assigned, give the domain the chip's name */
> +		if (!domain->name && irq_data->chip)
> +			domain->name = irq_data->chip->name;
> +	}
>  
> -		irq_clear_status_flags(virq, IRQ_NOREQUEST);
> +	if (hwirq < domain->revmap_size) {
> +		domain->linear_revmap[hwirq] = virq;
> +	} else {
> +		mutex_lock(&revmap_trees_mutex);
> +		radix_tree_insert(&domain->revmap_tree, hwirq, irq_data);
> +		mutex_unlock(&revmap_trees_mutex);
>  	}
> +	mutex_unlock(&irq_domain_mutex);
> +
> +	irq_clear_status_flags(virq, IRQ_NOREQUEST);
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(irq_domain_associate);
> +
> +void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
> +			       irq_hw_number_t hwirq_base, int count)
> +{
> +	int i;
> +
> +	pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
> +		of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
> +
> +	for (i = 0; i < count; i++) {
> +		irq_domain_associate(domain, irq_base + i, hwirq_base + i);
> +	}
> +}
>  EXPORT_SYMBOL_GPL(irq_domain_associate_many);
>  
>  /**
> @@ -460,12 +462,7 @@ int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
>  	if (unlikely(ret < 0))
>  		return ret;
>  
> -	ret = irq_domain_associate_many(domain, irq_base, hwirq_base, count);
> -	if (unlikely(ret < 0)) {
> -		irq_free_descs(irq_base, count);
> -		return ret;
> -	}
> -
> +	irq_domain_associate_many(domain, irq_base, hwirq_base, count);
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(irq_create_strict_mappings);
> @@ -535,7 +532,7 @@ void irq_dispose_mapping(unsigned int virq)
>  	if (WARN_ON(domain == NULL))
>  		return;
>  
> -	irq_domain_disassociate_many(domain, virq, 1);
> +	irq_domain_disassociate(domain, virq);
>  	irq_free_desc(virq);
>  }
>  EXPORT_SYMBOL_GPL(irq_dispose_mapping);
> -- 
> 1.8.1.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 08/11] irqdomain: Refactor irq_domain_associate_many()
  2013-06-18  1:20   ` [PATCH v2 08/11] irqdomain: Refactor irq_domain_associate_many() Michael Neuling
@ 2013-06-18  1:25     ` Michael Neuling
  2013-06-18  1:37       ` Stephen Rothwell
  2013-06-18  9:05       ` Grant Likely
  0 siblings, 2 replies; 7+ messages in thread
From: Michael Neuling @ 2013-06-18  1:25 UTC (permalink / raw)
  To: Grant Likely
  Cc: sfr, linux-kernel, Linux PPC dev, linux-next, Thomas Gleixner

Michael Neuling <mikey@neuling.org> wrote:

> Grant,
> 
> In next-20130617 we are getting the below crash on POWER7.  Bisecting,
> points to this patch (d39046ec72 in next)

Also, reverting just d39046ec72 fixes the crash in next-20130617.

Mikey

> 
> Any clues?
> 
> Mikey
> 
> 
> Using pSeries machine description
> Page sizes from device-tree:
> base_shift=12: shift=12, sllp=0x0000, avpnm=0x00000000, tlbiel=1, penc=0
> base_shift=24: shift=24, sllp=0x0100, avpnm=0x00000001, tlbiel=0, penc=0
> base_shift=16: shift=16, sllp=0x0110, avpnm=0x00000000, tlbiel=1, penc=1
> base_shift=20: shift=20, sllp=0x0111, avpnm=0x00000000, tlbiel=0, penc=2
> base_shift=34: shift=34, sllp=0x0120, avpnm=0x000007ff, tlbiel=0, penc=3
> Using 1TB segments
> Found initrd at 0xc000000002e60000:0xc000000002e60600
> CPU maps initialized for 1 thread per core
> Starting Linux PPC64 #48 SMP Tue Jun 18 11:10:17 EST 2013
> -----------------------------------------------------
> ppc64_pft_size                = 0x0
> physicalMemorySize            = 0x80000000
> htab_address                  = 0xc00000007fe00000
> htab_hash_mask                = 0x3fff
> -----------------------------------------------------
> Initializing cgroup subsys cpuset
> Initializing cgroup subsys cpuacct
> Linux version 3.10.0-rc5-14354-gd39046e (mikey@ka1) (gcc version 4.6.0 (GCC) ) #48 SMP Tue Jun 18 11:10:17 EST 2013
> [boot]0012 Setup Arch
> Zone ranges:
>   DMA      [mem 0x00000000-0x7fffffff]
>   Normal   empty
> Movable zone start for each node
> Early memory node ranges
>   node   0: [mem 0x00000000-0x7fffffff]
> [boot]0015 Setup Done
> PERCPU: Embedded 2 pages/cpu @c000000002100000 s88448 r0 d42624 u1048576
> Built 1 zonelists in Node order, mobility grouping on.  Total pages: 32740
> Policy zone: DMA
> Kernel command line: ipr.enabled=0
> PID hash table entries: 4096 (order: -1, 32768 bytes)
> Sorting __ex_table...
> freeing bootmem node 0
> Memory: 2061696k/2097152k available (11840k kernel code, 35456k reserved, 1792k data, 1072k bss, 704k init)
> SLUB: HWalign=128, Order=0-3, MinObjects=0, CPUs=1, Nodes=256
> Hierarchical RCU implementation.
> 	RCU restricting CPUs from NR_CPUS=2048 to nr_cpu_ids=1.
> NR_IRQS:512 nr_irqs:512 16
> error: reading the clock failed (-1)
> clocksource: timebase mult[86bca1b] shift[23] registered
> Console: colour dummy device 80x25
> console [tty0] enabled
> console [hvc0] enabled
> pid_max: default: 32768 minimum: 301
> Dentry cache hash table entries: 262144 (order: 5, 2097152 bytes)
> Inode-cache hash table entries: 131072 (order: 4, 1048576 bytes)
> Mount-cache hash table entries: 4096
> Initializing cgroup subsys devices
> Initializing cgroup subsys freezer
> error: hwirq 0x2 is too large for (null)
> ------------[ cut here ]------------
> WARNING: at /scratch/mikey/src/linux-next/kernel/irq/irqdomain.c:276
> Modules linked in:
> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.0-rc5-14354-gd39046e #48
> task: c00000007e500000 ti: c00000007e520000 task.ti: c00000007e520000
> NIP: c00000000011433c LR: c000000000114338 CTR: c000000000422310
> REGS: c00000007e523780 TRAP: 0700   Not tainted  (3.10.0-rc5-14354-gd39046e)
> MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI>  CR: 28000084  XER: 02000000
> SOFTE: 1
> CFAR: c0000000007b0ab8
> 
> GPR00: c000000000114338 c00000007e523a00 c000000000cb9570 0000000000000028 
> GPR04: 0000000000000000 0000000000000043 ffffffffffffffff 0000000000000000 
> GPR08: 076507200766076f c000000000be3790 0000000000000720 0000000000000000 
> GPR12: 0000000028000082 c00000000fe00000 c00000000000be60 0000000000000000 
> GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
> GPR20: 0000000000000000 0000000000000000 0000000000000000 c000000000b704b0 
> GPR24: c000000000d44a80 c000000000cb9570 0000000000000010 0000000000000002 
> GPR28: c00000007e0c0000 0000000000000000 c00000007e0c0000 c00000007e052400 
> NIP [c00000000011433c] .irq_domain_associate+0x1ec/0x260
> LR [c000000000114338] .irq_domain_associate+0x1e8/0x260
> PACATMSCRATCH [9000000032009032]
> Call Trace:
> [c00000007e523a00] [c000000000114338] .irq_domain_associate+0x1e8/0x260 (unreliable)
> [c00000007e523aa0] [c000000000114bf0] .irq_create_mapping+0xa0/0x170
> [c00000007e523b30] [c000000000af4574] .xics_smp_probe+0x38/0xa4
> [c00000007e523ba0] [c000000000af7af0] .pSeries_smp_probe+0x10/0x68
> [c00000007e523c10] [c000000000aed740] .smp_prepare_cpus+0x20c/0x244
> [c00000007e523cd0] [c000000000ae44c0] .kernel_init_freeable+0x138/0x328
> [c00000007e523db0] [c00000000000be7c] .kernel_init+0x1c/0x120
> [c00000007e523e30] [c00000000000a05c] .ret_from_kernel_thread+0x5c/0x80
> Instruction dump:
> 482ca915 60000000 7fa3eb78 4868ea09 60000000 4bffff7c 3c62ffd5 e8bc0010 
> 7f6407b4 3863c108 4869c731 60000000 <0fe00000> 3ba0ffea 4bffff7c 3c62ffd5 
> ---[ end trace 31fd0ba7d8756001 ]---
> ------------[ cut here ]------------
> kernel BUG at /scratch/mikey/src/linux-next/arch/powerpc/sysdev/xics/xics-common.c:134!
> cpu 0x0: Vector: 700 (Program Check) at [c00000007e5238b0]
>     pc: c000000000af4580: .xics_smp_probe+0x44/0xa4
>     lr: c000000000af4574: .xics_smp_probe+0x38/0xa4
>     sp: c00000007e523b30
>    msr: 9000000000029032
>   current = 0xc00000007e500000
>   paca    = 0xc00000000fe00000	 softe: 0	 irq_happened: 0x01
>     pid   = 1, comm = swapper/0
> kernel BUG at /scratch/mikey/src/linux-next/arch/powerpc/sysdev/xics/xics-common.c:134!
> enter ? for help
> [c00000007e523ba0] c000000000af7af0 .pSeries_smp_probe+0x10/0x68
> [c00000007e523c10] c000000000aed740 .smp_prepare_cpus+0x20c/0x244
> [c00000007e523cd0] c000000000ae44c0 .kernel_init_freeable+0x138/0x328
> [c00000007e523db0] c00000000000be7c .kernel_init+0x1c/0x120
> [c00000007e523e30] c00000000000a05c .ret_from_kernel_thread+0x5c/0x80
> 0:mon>  <no input ...>
> Oops: Exception in kernel mode, sig: 5 [#1]
> SMP NR_CPUS=2048 NUMA pSeries
> Modules linked in:
> CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W    3.10.0-rc5-14354-gd39046e #48
> task: c00000007e500000 ti: c00000007e520000 task.ti: c00000007e520000
> NIP: c000000000af4580 LR: c000000000af4574 CTR: 0000000000000002
> REGS: c00000007e5238b0 TRAP: 0700   Tainted: G        W     (3.10.0-rc5-14354-gd39046e)
> MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI>  CR: 28000084  XER: 02000000
> SOFTE: 1
> CFAR: c000000000114c1c
> 
> GPR00: 0000000000000001 c00000007e523b30 c000000000cb9570 0000000000000000 
> GPR04: 0000000000000010 0000000000020000 c00000007e052600 c000000000dcdd10 
> GPR08: c000000000b85ac8 fffffffffffeffff 0000000000000001 000000000001ffff 
> GPR12: 0000000088000084 c00000000fe00000 c00000000000be60 0000000000000000 
> GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
> GPR20: 0000000000000000 0000000000000000 0000000000000000 c000000000b704b0 
> GPR24: c000000000d44a80 c000000000cb9570 c000000000cb9570 c000000000b703b0 
> GPR28: c000000000b704b0 c000000000d40858 0000000000004000 0000000000000800 
> NIP [c000000000af4580] .xics_smp_probe+0x44/0xa4
> LR [c000000000af4574] .xics_smp_probe+0x38/0xa4
> PACATMSCRATCH [9000000000029032]
> Call Trace:
> [c00000007e523b30] [c000000000af4574] .xics_smp_probe+0x38/0xa4 (unreliable)
> [c00000007e523ba0] [c000000000af7af0] .pSeries_smp_probe+0x10/0x68
> [c00000007e523c10] [c000000000aed740] .smp_prepare_cpus+0x20c/0x244
> [c00000007e523cd0] [c000000000ae44c0] .kernel_init_freeable+0x138/0x328
> [c00000007e523db0] [c00000000000be7c] .kernel_init+0x1c/0x120
> [c00000007e523e30] [c00000000000a05c] .ret_from_kernel_thread+0x5c/0x80
> Instruction dump:
> 39290f80 38800002 e86b0010 f8010010 f821ff91 e80a0028 e9290000 f8090008 
> 4b6205e1 60000000 7c600074 7800d182 <0b000000> 3d22000d 3ce2ffd3 3929fde0 
> ---[ end trace 31fd0ba7d8756002 ]---
> 
> 
> 
> > Originally, irq_domain_associate_many() was designed to unwind the
> > mapped irqs on a failure of any individual association. However, that
> > proved to be a problem with certain IRQ controllers. Some of them only
> > support a subset of irqs, and will fail when attempting to map a
> > reserved IRQ. In those cases we want to map as many IRQs as possible, so
> > instead it is better for irq_domain_associate_many() to make a
> > best-effort attempt to map irqs, but not fail if any or all of them
> > don't succeed. If a caller really cares about how many irqs got
> > associated, then it should instead go back and check that all of the
> > irqs is cares about were mapped.
> > 
> > The original design open-coded the individual association code into the
> > body of irq_domain_associate_many(), but with no longer needing to
> > unwind associations, the code becomes simpler to split out
> > irq_domain_associate() to contain the bulk of the logic, and
> > irq_domain_associate_many() to be a simple loop wrapper.
> > 
> > This patch also adds a new error check to the associate path to make
> > sure it isn't called for an irq larger than the controller can handle,
> > and adds locking so that the irq_domain_mutex is held while setting up a
> > new association.
> > 
> > v2: Fixup x86 warning. irq_domain_associate_many() no longer returns an
> >     error code, but reports errors to the printk log directly. In the
> >     majority of cases we don't actually want to fail if there is a
> >     problem, but rather log it and still try to boot the system.
> > 
> > Signed-off-by: Grant Likely <grant.likely@linaro.org>
> > ---
> >  arch/x86/kernel/devicetree.c |   4 +-
> >  include/linux/irqdomain.h    |  22 +++--
> >  kernel/irq/irqdomain.c       | 185 +++++++++++++++++++++----------------------
> >  3 files changed, 102 insertions(+), 109 deletions(-)
> > 
> > diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
> > index b158152..4934890 100644
> > --- a/arch/x86/kernel/devicetree.c
> > +++ b/arch/x86/kernel/devicetree.c
> > @@ -364,9 +364,7 @@ static void dt_add_ioapic_domain(unsigned int ioapic_num,
> >  		 * and assigned so we can keep the 1:1 mapping which the ioapic
> >  		 * is having.
> >  		 */
> > -		ret = irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
> > -		if (ret)
> > -			pr_err("Error mapping legacy IRQs: %d\n", ret);
> > +		irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
> >  
> >  		if (num > NR_IRQS_LEGACY) {
> >  			ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY,
> > diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> > index fd4b26f..f9e8e06 100644
> > --- a/include/linux/irqdomain.h
> > +++ b/include/linux/irqdomain.h
> > @@ -103,6 +103,7 @@ struct irq_domain {
> >  	struct irq_domain_chip_generic *gc;
> >  
> >  	/* reverse map data. The linear map gets appended to the irq_domain */
> > +	irq_hw_number_t hwirq_max;
> >  	unsigned int revmap_direct_max_irq;
> >  	unsigned int revmap_size;
> >  	struct radix_tree_root revmap_tree;
> > @@ -110,8 +111,8 @@ struct irq_domain {
> >  };
> >  
> >  #ifdef CONFIG_IRQ_DOMAIN
> > -struct irq_domain *__irq_domain_add(struct device_node *of_node,
> > -				    int size, int direct_max,
> > +struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
> > +				    irq_hw_number_t hwirq_max, int direct_max,
> >  				    const struct irq_domain_ops *ops,
> >  				    void *host_data);
> >  struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
> > @@ -140,14 +141,14 @@ static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_no
> >  					 const struct irq_domain_ops *ops,
> >  					 void *host_data)
> >  {
> > -	return __irq_domain_add(of_node, size, 0, ops, host_data);
> > +	return __irq_domain_add(of_node, size, size, 0, ops, host_data);
> >  }
> >  static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
> >  					 unsigned int max_irq,
> >  					 const struct irq_domain_ops *ops,
> >  					 void *host_data)
> >  {
> > -	return __irq_domain_add(of_node, 0, max_irq, ops, host_data);
> > +	return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data);
> >  }
> >  static inline struct irq_domain *irq_domain_add_legacy_isa(
> >  				struct device_node *of_node,
> > @@ -166,14 +167,11 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
> >  
> >  extern void irq_domain_remove(struct irq_domain *host);
> >  
> > -extern int irq_domain_associate_many(struct irq_domain *domain,
> > -				     unsigned int irq_base,
> > -				     irq_hw_number_t hwirq_base, int count);
> > -static inline int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
> > -					irq_hw_number_t hwirq)
> > -{
> > -	return irq_domain_associate_many(domain, irq, hwirq, 1);
> > -}
> > +extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
> > +					irq_hw_number_t hwirq);
> > +extern void irq_domain_associate_many(struct irq_domain *domain,
> > +				      unsigned int irq_base,
> > +				      irq_hw_number_t hwirq_base, int count);
> >  
> >  extern unsigned int irq_create_mapping(struct irq_domain *host,
> >  				       irq_hw_number_t hwirq);
> > diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> > index 280b804..80e9249 100644
> > --- a/kernel/irq/irqdomain.c
> > +++ b/kernel/irq/irqdomain.c
> > @@ -35,8 +35,8 @@ static struct irq_domain *irq_default_domain;
> >   * register allocated irq_domain with irq_domain_register().  Returns pointer
> >   * to IRQ domain, or NULL on failure.
> >   */
> > -struct irq_domain *__irq_domain_add(struct device_node *of_node,
> > -				    int size, int direct_max,
> > +struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
> > +				    irq_hw_number_t hwirq_max, int direct_max,
> >  				    const struct irq_domain_ops *ops,
> >  				    void *host_data)
> >  {
> > @@ -52,6 +52,7 @@ struct irq_domain *__irq_domain_add(struct device_node *of_node,
> >  	domain->ops = ops;
> >  	domain->host_data = host_data;
> >  	domain->of_node = of_node_get(of_node);
> > +	domain->hwirq_max = hwirq_max;
> >  	domain->revmap_size = size;
> >  	domain->revmap_direct_max_irq = direct_max;
> >  
> > @@ -126,7 +127,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
> >  {
> >  	struct irq_domain *domain;
> >  
> > -	domain = __irq_domain_add(of_node, size, 0, ops, host_data);
> > +	domain = __irq_domain_add(of_node, size, size, 0, ops, host_data);
> >  	if (!domain)
> >  		return NULL;
> >  
> > @@ -139,7 +140,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
> >  				pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
> >  					first_irq);
> >  		}
> > -		WARN_ON(irq_domain_associate_many(domain, first_irq, 0, size));
> > +		irq_domain_associate_many(domain, first_irq, 0, size);
> >  	}
> >  
> >  	return domain;
> > @@ -170,11 +171,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
> >  {
> >  	struct irq_domain *domain;
> >  
> > -	domain = __irq_domain_add(of_node, first_hwirq + size, 0, ops, host_data);
> > +	domain = __irq_domain_add(of_node, first_hwirq + size,
> > +				  first_hwirq + size, 0, ops, host_data);
> >  	if (!domain)
> >  		return NULL;
> >  
> > -	WARN_ON(irq_domain_associate_many(domain, first_irq, first_hwirq, size));
> > +	irq_domain_associate_many(domain, first_irq, first_hwirq, size);
> >  
> >  	return domain;
> >  }
> > @@ -228,109 +230,109 @@ void irq_set_default_host(struct irq_domain *domain)
> >  }
> >  EXPORT_SYMBOL_GPL(irq_set_default_host);
> >  
> > -static void irq_domain_disassociate_many(struct irq_domain *domain,
> > -					 unsigned int irq_base, int count)
> > +static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
> >  {
> > -	/*
> > -	 * disassociate in reverse order;
> > -	 * not strictly necessary, but nice for unwinding
> > -	 */
> > -	while (count--) {
> > -		int irq = irq_base + count;
> > -		struct irq_data *irq_data = irq_get_irq_data(irq);
> > -		irq_hw_number_t hwirq;
> > +	struct irq_data *irq_data = irq_get_irq_data(irq);
> > +	irq_hw_number_t hwirq;
> >  
> > -		if (WARN_ON(!irq_data || irq_data->domain != domain))
> > -			continue;
> > +	if (WARN(!irq_data || irq_data->domain != domain,
> > +		 "virq%i doesn't exist; cannot disassociate\n", irq))
> > +		return;
> >  
> > -		hwirq = irq_data->hwirq;
> > -		irq_set_status_flags(irq, IRQ_NOREQUEST);
> > +	hwirq = irq_data->hwirq;
> > +	irq_set_status_flags(irq, IRQ_NOREQUEST);
> >  
> > -		/* remove chip and handler */
> > -		irq_set_chip_and_handler(irq, NULL, NULL);
> > +	/* remove chip and handler */
> > +	irq_set_chip_and_handler(irq, NULL, NULL);
> >  
> > -		/* Make sure it's completed */
> > -		synchronize_irq(irq);
> > +	/* Make sure it's completed */
> > +	synchronize_irq(irq);
> >  
> > -		/* Tell the PIC about it */
> > -		if (domain->ops->unmap)
> > -			domain->ops->unmap(domain, irq);
> > -		smp_mb();
> > +	/* Tell the PIC about it */
> > +	if (domain->ops->unmap)
> > +		domain->ops->unmap(domain, irq);
> > +	smp_mb();
> >  
> > -		irq_data->domain = NULL;
> > -		irq_data->hwirq = 0;
> > +	irq_data->domain = NULL;
> > +	irq_data->hwirq = 0;
> >  
> > -		/* Clear reverse map for this hwirq */
> > -		if (hwirq < domain->revmap_size) {
> > -			domain->linear_revmap[hwirq] = 0;
> > -		} else {
> > -			mutex_lock(&revmap_trees_mutex);
> > -			radix_tree_delete(&domain->revmap_tree, hwirq);
> > -			mutex_unlock(&revmap_trees_mutex);
> > -		}
> > +	/* Clear reverse map for this hwirq */
> > +	if (hwirq < domain->revmap_size) {
> > +		domain->linear_revmap[hwirq] = 0;
> > +	} else {
> > +		mutex_lock(&revmap_trees_mutex);
> > +		radix_tree_delete(&domain->revmap_tree, hwirq);
> > +		mutex_unlock(&revmap_trees_mutex);
> >  	}
> >  }
> >  
> > -int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
> > -			      irq_hw_number_t hwirq_base, int count)
> > +int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
> > +			 irq_hw_number_t hwirq)
> >  {
> > -	unsigned int virq = irq_base;
> > -	irq_hw_number_t hwirq = hwirq_base;
> > -	int i, ret;
> > +	struct irq_data *irq_data = irq_get_irq_data(virq);
> > +	int ret;
> >  
> > -	pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
> > -		of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
> > +	if (WARN(hwirq >= domain->hwirq_max,
> > +		 "error: hwirq 0x%x is too large for %s\n", (int)hwirq, domain->name))
> > +		return -EINVAL;
> > +	if (WARN(!irq_data, "error: virq%i is not allocated", virq))
> > +		return -EINVAL;
> > +	if (WARN(irq_data->domain, "error: virq%i is already associated", virq))
> > +		return -EINVAL;
> >  
> > -	for (i = 0; i < count; i++) {
> > -		struct irq_data *irq_data = irq_get_irq_data(virq + i);
> > -
> > -		if (WARN(!irq_data, "error: irq_desc not allocated; "
> > -			 "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i))
> > -			return -EINVAL;
> > -		if (WARN(irq_data->domain, "error: irq_desc already associated; "
> > -			 "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i))
> > -			return -EINVAL;
> > -	};
> > -
> > -	for (i = 0; i < count; i++, virq++, hwirq++) {
> > -		struct irq_data *irq_data = irq_get_irq_data(virq);
> > -
> > -		irq_data->hwirq = hwirq;
> > -		irq_data->domain = domain;
> > -		if (domain->ops->map) {
> > -			ret = domain->ops->map(domain, virq, hwirq);
> > -			if (ret != 0) {
> > -				/*
> > -				 * If map() returns -EPERM, this interrupt is protected
> > -				 * by the firmware or some other service and shall not
> > -				 * be mapped. Don't bother telling the user about it.
> > -				 */
> > -				if (ret != -EPERM) {
> > -					pr_info("%s didn't like hwirq-0x%lx to VIRQ%i mapping (rc=%d)\n",
> > -					       domain->name, hwirq, virq, ret);
> > -				}
> > -				irq_data->domain = NULL;
> > -				irq_data->hwirq = 0;
> > -				continue;
> > +	mutex_lock(&irq_domain_mutex);
> > +	irq_data->hwirq = hwirq;
> > +	irq_data->domain = domain;
> > +	if (domain->ops->map) {
> > +		ret = domain->ops->map(domain, virq, hwirq);
> > +		if (ret != 0) {
> > +			/*
> > +			 * If map() returns -EPERM, this interrupt is protected
> > +			 * by the firmware or some other service and shall not
> > +			 * be mapped. Don't bother telling the user about it.
> > +			 */
> > +			if (ret != -EPERM) {
> > +				pr_info("%s didn't like hwirq-0x%lx to VIRQ%i mapping (rc=%d)\n",
> > +				       domain->name, hwirq, virq, ret);
> >  			}
> > -			/* If not already assigned, give the domain the chip's name */
> > -			if (!domain->name && irq_data->chip)
> > -				domain->name = irq_data->chip->name;
> > +			irq_data->domain = NULL;
> > +			irq_data->hwirq = 0;
> > +			mutex_unlock(&irq_domain_mutex);
> > +			return ret;
> >  		}
> >  
> > -		if (hwirq < domain->revmap_size) {
> > -			domain->linear_revmap[hwirq] = virq;
> > -		} else {
> > -			mutex_lock(&revmap_trees_mutex);
> > -			radix_tree_insert(&domain->revmap_tree, hwirq, irq_data);
> > -			mutex_unlock(&revmap_trees_mutex);
> > -		}
> > +		/* If not already assigned, give the domain the chip's name */
> > +		if (!domain->name && irq_data->chip)
> > +			domain->name = irq_data->chip->name;
> > +	}
> >  
> > -		irq_clear_status_flags(virq, IRQ_NOREQUEST);
> > +	if (hwirq < domain->revmap_size) {
> > +		domain->linear_revmap[hwirq] = virq;
> > +	} else {
> > +		mutex_lock(&revmap_trees_mutex);
> > +		radix_tree_insert(&domain->revmap_tree, hwirq, irq_data);
> > +		mutex_unlock(&revmap_trees_mutex);
> >  	}
> > +	mutex_unlock(&irq_domain_mutex);
> > +
> > +	irq_clear_status_flags(virq, IRQ_NOREQUEST);
> >  
> >  	return 0;
> >  }
> > +EXPORT_SYMBOL_GPL(irq_domain_associate);
> > +
> > +void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
> > +			       irq_hw_number_t hwirq_base, int count)
> > +{
> > +	int i;
> > +
> > +	pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
> > +		of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
> > +
> > +	for (i = 0; i < count; i++) {
> > +		irq_domain_associate(domain, irq_base + i, hwirq_base + i);
> > +	}
> > +}
> >  EXPORT_SYMBOL_GPL(irq_domain_associate_many);
> >  
> >  /**
> > @@ -460,12 +462,7 @@ int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
> >  	if (unlikely(ret < 0))
> >  		return ret;
> >  
> > -	ret = irq_domain_associate_many(domain, irq_base, hwirq_base, count);
> > -	if (unlikely(ret < 0)) {
> > -		irq_free_descs(irq_base, count);
> > -		return ret;
> > -	}
> > -
> > +	irq_domain_associate_many(domain, irq_base, hwirq_base, count);
> >  	return 0;
> >  }
> >  EXPORT_SYMBOL_GPL(irq_create_strict_mappings);
> > @@ -535,7 +532,7 @@ void irq_dispose_mapping(unsigned int virq)
> >  	if (WARN_ON(domain == NULL))
> >  		return;
> >  
> > -	irq_domain_disassociate_many(domain, virq, 1);
> > +	irq_domain_disassociate(domain, virq);
> >  	irq_free_desc(virq);
> >  }
> >  EXPORT_SYMBOL_GPL(irq_dispose_mapping);
> > -- 
> > 1.8.1.2
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> > 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 08/11] irqdomain: Refactor irq_domain_associate_many()
  2013-06-18  1:25     ` Michael Neuling
@ 2013-06-18  1:37       ` Stephen Rothwell
  2013-06-18  9:05       ` Grant Likely
  1 sibling, 0 replies; 7+ messages in thread
From: Stephen Rothwell @ 2013-06-18  1:37 UTC (permalink / raw)
  To: Michael Neuling
  Cc: linux-kernel, Linux PPC dev, linux-next, Grant Likely, Thomas Gleixner

[-- Attachment #1: Type: text/plain, Size: 463 bytes --]

Hi all,

On Tue, 18 Jun 2013 11:25:34 +1000 Michael Neuling <mikey@neuling.org> wrote:
>
> Michael Neuling <mikey@neuling.org> wrote:
> 
> > In next-20130617 we are getting the below crash on POWER7.  Bisecting,
> > points to this patch (d39046ec72 in next)
> 
> Also, reverting just d39046ec72 fixes the crash in next-20130617.

I will revert that commit in linux-next today.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 08/11] irqdomain: Refactor irq_domain_associate_many()
  2013-06-18  1:25     ` Michael Neuling
  2013-06-18  1:37       ` Stephen Rothwell
@ 2013-06-18  9:05       ` Grant Likely
  2013-06-18  9:46         ` Grant Likely
  1 sibling, 1 reply; 7+ messages in thread
From: Grant Likely @ 2013-06-18  9:05 UTC (permalink / raw)
  To: Michael Neuling
  Cc: Stephen Rothwell, Linux Kernel Mailing List, Linux PPC dev,
	linux-next, Thomas Gleixner

On Tue, Jun 18, 2013 at 2:25 AM, Michael Neuling <mikey@neuling.org> wrote:
> Michael Neuling <mikey@neuling.org> wrote:
>
>> Grant,
>>
>> In next-20130617 we are getting the below crash on POWER7.  Bisecting,
>> points to this patch (d39046ec72 in next)
>
> Also, reverting just d39046ec72 fixes the crash in next-20130617.

Odd. Of all the changes in that series, I would not have expected that
one to cause any problems. I'm digging into it now...

g.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 08/11] irqdomain: Refactor irq_domain_associate_many()
  2013-06-18  9:05       ` Grant Likely
@ 2013-06-18  9:46         ` Grant Likely
  2013-06-18 11:04           ` Michael Neuling
  0 siblings, 1 reply; 7+ messages in thread
From: Grant Likely @ 2013-06-18  9:46 UTC (permalink / raw)
  To: Michael Neuling
  Cc: Stephen Rothwell, Linux Kernel Mailing List, Linux PPC dev,
	linux-next, Thomas Gleixner

On Tue, 18 Jun 2013 10:05:31 +0100, Grant Likely <grant.likely@linaro.org> wrote:
> On Tue, Jun 18, 2013 at 2:25 AM, Michael Neuling <mikey@neuling.org> wrote:
> > Michael Neuling <mikey@neuling.org> wrote:
> >
> >> Grant,
> >>
> >> In next-20130617 we are getting the below crash on POWER7.  Bisecting,
> >> points to this patch (d39046ec72 in next)
> >
> > Also, reverting just d39046ec72 fixes the crash in next-20130617.
> 
> Odd. Of all the changes in that series, I would not have expected that
> one to cause any problems. I'm digging into it now...

Ugh. I flubbed the commit. Try this patch. It should solve the problem:

>From b7ba09c29ed36eda8e16453646b55faea7f9c25f Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@linaro.org>
Date: Tue, 18 Jun 2013 10:15:19 +0100
Subject: [PATCH] irqdomain: Fix flubbed irq_domain_associate_many refactoring

commit d39046ec72, "irqdomain: Refactor irq_domain_associate_many()" was
missing the following hunk which causes a boot failure on anything using
irq_domain_add_tree() to allocate an irq domain.

Signed-off-by: Grant Likely <grant.likely@linaro.org>
Cc: Michael Neuling <mikey@neuling.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>,
Cc: Thomas Gleixner <tglx@linutronix.de>,
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
---
 include/linux/irqdomain.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 02f7658..c983ed1 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -162,7 +162,7 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
 					 const struct irq_domain_ops *ops,
 					 void *host_data)
 {
-	return irq_domain_add_linear(of_node, 0, ops, host_data);
+	return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
 }
 
 extern void irq_domain_remove(struct irq_domain *host);
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 08/11] irqdomain: Refactor irq_domain_associate_many()
  2013-06-18  9:46         ` Grant Likely
@ 2013-06-18 11:04           ` Michael Neuling
  2013-06-18 12:13             ` Grant Likely
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Neuling @ 2013-06-18 11:04 UTC (permalink / raw)
  To: Grant Likely
  Cc: Stephen Rothwell, Linux Kernel Mailing List, Linux PPC dev,
	linux-next, Thomas Gleixner

Grant Likely <grant.likely@linaro.org> wrote:

> On Tue, 18 Jun 2013 10:05:31 +0100, Grant Likely <grant.likely@linaro.org> wrote:
> > On Tue, Jun 18, 2013 at 2:25 AM, Michael Neuling <mikey@neuling.org> wrote:
> > > Michael Neuling <mikey@neuling.org> wrote:
> > >
> > >> Grant,
> > >>
> > >> In next-20130617 we are getting the below crash on POWER7.  Bisecting,
> > >> points to this patch (d39046ec72 in next)
> > >
> > > Also, reverting just d39046ec72 fixes the crash in next-20130617.
> > 
> > Odd. Of all the changes in that series, I would not have expected that
> > one to cause any problems. I'm digging into it now...
> 
> Ugh. I flubbed the commit. Try this patch. It should solve the problem:
> 

Yep, it fixes it.  Thanks.

Mikey

> From b7ba09c29ed36eda8e16453646b55faea7f9c25f Mon Sep 17 00:00:00 2001
> From: Grant Likely <grant.likely@linaro.org>
> Date: Tue, 18 Jun 2013 10:15:19 +0100
> Subject: [PATCH] irqdomain: Fix flubbed irq_domain_associate_many refactoring
> 
> commit d39046ec72, "irqdomain: Refactor irq_domain_associate_many()" was
> missing the following hunk which causes a boot failure on anything using
> irq_domain_add_tree() to allocate an irq domain.
> 
> Signed-off-by: Grant Likely <grant.likely@linaro.org>
> Cc: Michael Neuling <mikey@neuling.org>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>,
> Cc: Thomas Gleixner <tglx@linutronix.de>,
> Cc: Stephen Rothwell <sfr@canb.auug.org.au>
> ---
>  include/linux/irqdomain.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 02f7658..c983ed1 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -162,7 +162,7 @@ static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node
>  					 const struct irq_domain_ops *ops,
>  					 void *host_data)
>  {
> -	return irq_domain_add_linear(of_node, 0, ops, host_data);
> +	return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
>  }
>  
>  extern void irq_domain_remove(struct irq_domain *host);
> -- 
> 1.8.1.2
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 08/11] irqdomain: Refactor irq_domain_associate_many()
  2013-06-18 11:04           ` Michael Neuling
@ 2013-06-18 12:13             ` Grant Likely
  0 siblings, 0 replies; 7+ messages in thread
From: Grant Likely @ 2013-06-18 12:13 UTC (permalink / raw)
  To: Michael Neuling
  Cc: Stephen Rothwell, Linux Kernel Mailing List, Linux PPC dev,
	linux-next, Thomas Gleixner

On Tue, Jun 18, 2013 at 12:04 PM, Michael Neuling <mikey@neuling.org> wrote:
> Grant Likely <grant.likely@linaro.org> wrote:
>
>> On Tue, 18 Jun 2013 10:05:31 +0100, Grant Likely <grant.likely@linaro.org> wrote:
>> > On Tue, Jun 18, 2013 at 2:25 AM, Michael Neuling <mikey@neuling.org> wrote:
>> > > Michael Neuling <mikey@neuling.org> wrote:
>> > >
>> > >> Grant,
>> > >>
>> > >> In next-20130617 we are getting the below crash on POWER7.  Bisecting,
>> > >> points to this patch (d39046ec72 in next)
>> > >
>> > > Also, reverting just d39046ec72 fixes the crash in next-20130617.
>> >
>> > Odd. Of all the changes in that series, I would not have expected that
>> > one to cause any problems. I'm digging into it now...
>>
>> Ugh. I flubbed the commit. Try this patch. It should solve the problem:
>>
>
> Yep, it fixes it.  Thanks.

Excellent, thanks for testing.

g.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-06-18 12:14 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1371244086-9189-1-git-send-email-grant.likely@linaro.org>
     [not found] ` <1371244086-9189-9-git-send-email-grant.likely@linaro.org>
2013-06-18  1:20   ` [PATCH v2 08/11] irqdomain: Refactor irq_domain_associate_many() Michael Neuling
2013-06-18  1:25     ` Michael Neuling
2013-06-18  1:37       ` Stephen Rothwell
2013-06-18  9:05       ` Grant Likely
2013-06-18  9:46         ` Grant Likely
2013-06-18 11:04           ` Michael Neuling
2013-06-18 12:13             ` Grant Likely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).