diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-13 17:33:11 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-13 17:33:11 -0800 | 
| commit | 670310dfbae0eefe7318ff6a61e29e67a7a7bbce (patch) | |
| tree | eb3ce3aa3e6786a64fec93d410bb6f0b9a56be77 /kernel/irq/irqdomain.c | |
| parent | 43ff2f4db9d0f76452b77cfa645f02b471143b24 (diff) | |
| parent | ffc661c99f621152d5fdcf53f9df0d48c326318b (diff) | |
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq core updates from Thomas Gleixner:
 "A rather large update for the interrupt core code and the irq chip drivers:
   - Add a new bitmap matrix allocator and supporting changes, which is
     used to replace the x86 vector allocator which comes with separate
     pull request. This allows to replace the convoluted nested loop
     allocation function in x86 with a facility which supports the
     recently added property of managed interrupts proper and allows to
     switch to a best effort vector reservation scheme, which addresses
     problems with vector exhaustion.
   - A large update to the ARM GIC-V3-ITS driver adding support for
     range selectors.
   - New interrupt controllers:
       - Meson and Meson8 GPIO
       - BCM7271 L2
       - Socionext EXIU
     If you expected that this will stop at some point, I have to
     disappoint you. There are new ones posted already. Sigh!
   - STM32 interrupt controller support for new platforms.
   - A pile of fixes, cleanups and updates to the MIPS GIC driver
   - The usual small fixes, cleanups and updates all over the place.
     Most visible one is to move the irq chip drivers Kconfig switches
     into a separate Kconfig menu"
* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (70 commits)
  genirq: Fix type of shifting literal 1 in __setup_irq()
  irqdomain: Drop pointless NULL check in virq_debug_show_one
  genirq/proc: Return proper error code when irq_set_affinity() fails
  irq/work: Use llist_for_each_entry_safe
  irqchip: mips-gic: Print warning if inherited GIC base is used
  irqchip/mips-gic: Add pr_fmt and reword pr_* messages
  irqchip/stm32: Move the wakeup on interrupt mask
  irqchip/stm32: Fix initial values
  irqchip/stm32: Add stm32h7 support
  dt-bindings/interrupt-controllers: Add compatible string for stm32h7
  irqchip/stm32: Add multi-bank management
  irqchip/stm32: Select GENERIC_IRQ_CHIP
  irqchip/exiu: Add support for Socionext Synquacer EXIU controller
  dt-bindings: Add description of Socionext EXIU interrupt controller
  irqchip/gic-v3-its: Fix VPE activate callback return value
  irqchip: mips-gic: Make IPI bitmaps static
  irqchip: mips-gic: Share register writes in gic_set_type()
  irqchip: mips-gic: Remove gic_vpes variable
  irqchip: mips-gic: Use num_possible_cpus() to reserve IPIs
  irqchip: mips-gic: Configure EIC when CPUs come online
  ...
Diffstat (limited to 'kernel/irq/irqdomain.c')
| -rw-r--r-- | kernel/irq/irqdomain.c | 60 | 
1 files changed, 36 insertions, 24 deletions
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index ac4644e92b49..4f4f60015e8a 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -21,7 +21,6 @@  static LIST_HEAD(irq_domain_list);  static DEFINE_MUTEX(irq_domain_mutex); -static DEFINE_MUTEX(revmap_trees_mutex);  static struct irq_domain *irq_default_domain;  static void irq_domain_check_hierarchy(struct irq_domain *domain); @@ -211,6 +210,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,  	/* Fill structure */  	INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL); +	mutex_init(&domain->revmap_tree_mutex);  	domain->ops = ops;  	domain->host_data = host_data;  	domain->hwirq_max = hwirq_max; @@ -462,9 +462,9 @@ static void irq_domain_clear_mapping(struct irq_domain *domain,  	if (hwirq < domain->revmap_size) {  		domain->linear_revmap[hwirq] = 0;  	} else { -		mutex_lock(&revmap_trees_mutex); +		mutex_lock(&domain->revmap_tree_mutex);  		radix_tree_delete(&domain->revmap_tree, hwirq); -		mutex_unlock(&revmap_trees_mutex); +		mutex_unlock(&domain->revmap_tree_mutex);  	}  } @@ -475,9 +475,9 @@ static void irq_domain_set_mapping(struct irq_domain *domain,  	if (hwirq < domain->revmap_size) {  		domain->linear_revmap[hwirq] = irq_data->irq;  	} else { -		mutex_lock(&revmap_trees_mutex); +		mutex_lock(&domain->revmap_tree_mutex);  		radix_tree_insert(&domain->revmap_tree, hwirq, irq_data); -		mutex_unlock(&revmap_trees_mutex); +		mutex_unlock(&domain->revmap_tree_mutex);  	}  } @@ -921,8 +921,7 @@ static void virq_debug_show_one(struct seq_file *m, struct irq_desc *desc)  		chip = irq_data_get_irq_chip(data);  		seq_printf(m, "%-15s  ", (chip && chip->name) ? chip->name : "none"); -		seq_printf(m, data ? "0x%p  " : "  %p  ", -			   irq_data_get_irq_chip_data(data)); +		seq_printf(m, "0x%p  ", irq_data_get_irq_chip_data(data));  		seq_printf(m, "   %c    ", (desc->action && desc->action->handler) ? '*' : ' ');  		direct = (irq == hwirq) && (irq < domain->revmap_direct_max_irq); @@ -1459,11 +1458,11 @@ static void irq_domain_fix_revmap(struct irq_data *d)  		return; /* Not using radix tree. */  	/* Fix up the revmap. */ -	mutex_lock(&revmap_trees_mutex); +	mutex_lock(&d->domain->revmap_tree_mutex);  	slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq);  	if (slot)  		radix_tree_replace_slot(&d->domain->revmap_tree, slot, d); -	mutex_unlock(&revmap_trees_mutex); +	mutex_unlock(&d->domain->revmap_tree_mutex);  }  /** @@ -1682,28 +1681,36 @@ void irq_domain_free_irqs_parent(struct irq_domain *domain,  }  EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent); -static void __irq_domain_activate_irq(struct irq_data *irq_data) +static void __irq_domain_deactivate_irq(struct irq_data *irq_data)  {  	if (irq_data && irq_data->domain) {  		struct irq_domain *domain = irq_data->domain; +		if (domain->ops->deactivate) +			domain->ops->deactivate(domain, irq_data);  		if (irq_data->parent_data) -			__irq_domain_activate_irq(irq_data->parent_data); -		if (domain->ops->activate) -			domain->ops->activate(domain, irq_data); +			__irq_domain_deactivate_irq(irq_data->parent_data);  	}  } -static void __irq_domain_deactivate_irq(struct irq_data *irq_data) +static int __irq_domain_activate_irq(struct irq_data *irqd, bool early)  { -	if (irq_data && irq_data->domain) { -		struct irq_domain *domain = irq_data->domain; +	int ret = 0; -		if (domain->ops->deactivate) -			domain->ops->deactivate(domain, irq_data); -		if (irq_data->parent_data) -			__irq_domain_deactivate_irq(irq_data->parent_data); +	if (irqd && irqd->domain) { +		struct irq_domain *domain = irqd->domain; + +		if (irqd->parent_data) +			ret = __irq_domain_activate_irq(irqd->parent_data, +							early); +		if (!ret && domain->ops->activate) { +			ret = domain->ops->activate(domain, irqd, early); +			/* Rollback in case of error */ +			if (ret && irqd->parent_data) +				__irq_domain_deactivate_irq(irqd->parent_data); +		}  	} +	return ret;  }  /** @@ -1714,12 +1721,15 @@ static void __irq_domain_deactivate_irq(struct irq_data *irq_data)   * This is the second step to call domain_ops->activate to program interrupt   * controllers, so the interrupt could actually get delivered.   */ -void irq_domain_activate_irq(struct irq_data *irq_data) +int irq_domain_activate_irq(struct irq_data *irq_data, bool early)  { -	if (!irqd_is_activated(irq_data)) { -		__irq_domain_activate_irq(irq_data); +	int ret = 0; + +	if (!irqd_is_activated(irq_data)) +		ret = __irq_domain_activate_irq(irq_data, early); +	if (!ret)  		irqd_set_activated(irq_data); -	} +	return ret;  }  /** @@ -1810,6 +1820,8 @@ irq_domain_debug_show_one(struct seq_file *m, struct irq_domain *d, int ind)  		   d->revmap_size + d->revmap_direct_max_irq);  	seq_printf(m, "%*smapped: %u\n", ind + 1, "", d->mapcount);  	seq_printf(m, "%*sflags:  0x%08x\n", ind +1 , "", d->flags); +	if (d->ops && d->ops->debug_show) +		d->ops->debug_show(m, d, NULL, ind + 1);  #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY  	if (!d->parent)  		return;  | 
