diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/irq/irq_sim.c | 13 | ||||
| -rw-r--r-- | kernel/irq/irqdesc.c | 17 | ||||
| -rw-r--r-- | kernel/irq/manage.c | 10 | ||||
| -rw-r--r-- | kernel/softirq.c | 82 | 
4 files changed, 63 insertions, 59 deletions
| diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c index 24caabf1a0f7..85690859a2a8 100644 --- a/kernel/irq/irq_sim.c +++ b/kernel/irq/irq_sim.c @@ -7,6 +7,7 @@   * option) any later version.   */ +#include <linux/slab.h>  #include <linux/irq_sim.h>  #include <linux/irq.h> @@ -49,7 +50,8 @@ static void irq_sim_handle_irq(struct irq_work *work)   * @sim:        The interrupt simulator object to initialize.   * @num_irqs:   Number of interrupts to allocate   * - * Returns 0 on success and a negative error number on failure. + * On success: return the base of the allocated interrupt range. + * On failure: a negative errno.   */  int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs)  { @@ -78,7 +80,7 @@ int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs)  	init_irq_work(&sim->work_ctx.work, irq_sim_handle_irq);  	sim->irq_count = num_irqs; -	return 0; +	return sim->irq_base;  }  EXPORT_SYMBOL_GPL(irq_sim_init); @@ -110,7 +112,8 @@ static void devm_irq_sim_release(struct device *dev, void *res)   * @sim:        The interrupt simulator object to initialize.   * @num_irqs:   Number of interrupts to allocate   * - * Returns 0 on success and a negative error number on failure. + * On success: return the base of the allocated interrupt range. + * On failure: a negative errno.   */  int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,  		      unsigned int num_irqs) @@ -123,7 +126,7 @@ int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,  		return -ENOMEM;  	rv = irq_sim_init(sim, num_irqs); -	if (rv) { +	if (rv < 0) {  		devres_free(dr);  		return rv;  	} @@ -131,7 +134,7 @@ int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,  	dr->sim = sim;  	devres_add(dev, dr); -	return 0; +	return rv;  }  EXPORT_SYMBOL_GPL(devm_irq_sim_init); diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 49b54e9979cc..d9ded088d336 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -210,6 +210,22 @@ static ssize_t type_show(struct kobject *kobj,  }  IRQ_ATTR_RO(type); +static ssize_t wakeup_show(struct kobject *kobj, +			   struct kobj_attribute *attr, char *buf) +{ +	struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj); +	ssize_t ret = 0; + +	raw_spin_lock_irq(&desc->lock); +	ret = sprintf(buf, "%s\n", +		      irqd_is_wakeup_set(&desc->irq_data) ? "enabled" : "disabled"); +	raw_spin_unlock_irq(&desc->lock); + +	return ret; + +} +IRQ_ATTR_RO(wakeup); +  static ssize_t name_show(struct kobject *kobj,  			 struct kobj_attribute *attr, char *buf)  { @@ -253,6 +269,7 @@ static struct attribute *irq_attrs[] = {  	&chip_name_attr.attr,  	&hwirq_attr.attr,  	&type_attr.attr, +	&wakeup_attr.attr,  	&name_attr.attr,  	&actions_attr.attr,  	NULL diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0f922729bab9..d2b3c59f1200 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -855,10 +855,14 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)  	 * This code is triggered unconditionally. Check the affinity  	 * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out.  	 */ -	if (cpumask_available(desc->irq_common_data.affinity)) -		cpumask_copy(mask, desc->irq_common_data.affinity); -	else +	if (cpumask_available(desc->irq_common_data.affinity)) { +		const struct cpumask *m; + +		m = irq_data_get_effective_affinity_mask(&desc->irq_data); +		cpumask_copy(mask, m); +	} else {  		valid = false; +	}  	raw_spin_unlock_irq(&desc->lock);  	if (valid) diff --git a/kernel/softirq.c b/kernel/softirq.c index 24d243ef8e71..177de3640c78 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -460,40 +460,46 @@ struct tasklet_head {  static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);  static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec); -void __tasklet_schedule(struct tasklet_struct *t) +static void __tasklet_schedule_common(struct tasklet_struct *t, +				      struct tasklet_head __percpu *headp, +				      unsigned int softirq_nr)  { +	struct tasklet_head *head;  	unsigned long flags;  	local_irq_save(flags); +	head = this_cpu_ptr(headp);  	t->next = NULL; -	*__this_cpu_read(tasklet_vec.tail) = t; -	__this_cpu_write(tasklet_vec.tail, &(t->next)); -	raise_softirq_irqoff(TASKLET_SOFTIRQ); +	*head->tail = t; +	head->tail = &(t->next); +	raise_softirq_irqoff(softirq_nr);  	local_irq_restore(flags);  } + +void __tasklet_schedule(struct tasklet_struct *t) +{ +	__tasklet_schedule_common(t, &tasklet_vec, +				  TASKLET_SOFTIRQ); +}  EXPORT_SYMBOL(__tasklet_schedule);  void __tasklet_hi_schedule(struct tasklet_struct *t)  { -	unsigned long flags; - -	local_irq_save(flags); -	t->next = NULL; -	*__this_cpu_read(tasklet_hi_vec.tail) = t; -	__this_cpu_write(tasklet_hi_vec.tail,  &(t->next)); -	raise_softirq_irqoff(HI_SOFTIRQ); -	local_irq_restore(flags); +	__tasklet_schedule_common(t, &tasklet_hi_vec, +				  HI_SOFTIRQ);  }  EXPORT_SYMBOL(__tasklet_hi_schedule); -static __latent_entropy void tasklet_action(struct softirq_action *a) +static void tasklet_action_common(struct softirq_action *a, +				  struct tasklet_head *tl_head, +				  unsigned int softirq_nr)  {  	struct tasklet_struct *list;  	local_irq_disable(); -	list = __this_cpu_read(tasklet_vec.head); -	__this_cpu_write(tasklet_vec.head, NULL); -	__this_cpu_write(tasklet_vec.tail, this_cpu_ptr(&tasklet_vec.head)); +	list = tl_head->head; +	tl_head->head = NULL; +	tl_head->tail = &tl_head->head;  	local_irq_enable();  	while (list) { @@ -515,47 +521,21 @@ static __latent_entropy void tasklet_action(struct softirq_action *a)  		local_irq_disable();  		t->next = NULL; -		*__this_cpu_read(tasklet_vec.tail) = t; -		__this_cpu_write(tasklet_vec.tail, &(t->next)); -		__raise_softirq_irqoff(TASKLET_SOFTIRQ); +		*tl_head->tail = t; +		tl_head->tail = &t->next; +		__raise_softirq_irqoff(softirq_nr);  		local_irq_enable();  	}  } -static __latent_entropy void tasklet_hi_action(struct softirq_action *a) +static __latent_entropy void tasklet_action(struct softirq_action *a)  { -	struct tasklet_struct *list; - -	local_irq_disable(); -	list = __this_cpu_read(tasklet_hi_vec.head); -	__this_cpu_write(tasklet_hi_vec.head, NULL); -	__this_cpu_write(tasklet_hi_vec.tail, this_cpu_ptr(&tasklet_hi_vec.head)); -	local_irq_enable(); - -	while (list) { -		struct tasklet_struct *t = list; - -		list = list->next; - -		if (tasklet_trylock(t)) { -			if (!atomic_read(&t->count)) { -				if (!test_and_clear_bit(TASKLET_STATE_SCHED, -							&t->state)) -					BUG(); -				t->func(t->data); -				tasklet_unlock(t); -				continue; -			} -			tasklet_unlock(t); -		} +	tasklet_action_common(a, this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ); +} -		local_irq_disable(); -		t->next = NULL; -		*__this_cpu_read(tasklet_hi_vec.tail) = t; -		__this_cpu_write(tasklet_hi_vec.tail, &(t->next)); -		__raise_softirq_irqoff(HI_SOFTIRQ); -		local_irq_enable(); -	} +static __latent_entropy void tasklet_hi_action(struct softirq_action *a) +{ +	tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);  }  void tasklet_init(struct tasklet_struct *t, | 
