diff options
Diffstat (limited to 'kernel/irq/manage.c')
| -rw-r--r-- | kernel/irq/manage.c | 17 | 
1 files changed, 13 insertions, 4 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0a7840aeb0f..9b956fa2030 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -883,6 +883,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)  	if (desc->irq_data.chip == &no_irq_chip)  		return -ENOSYS; +	if (!try_module_get(desc->owner)) +		return -ENODEV;  	/*  	 * Some drivers like serial.c use request_irq() heavily,  	 * so we have to be careful not to interfere with a @@ -906,8 +908,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)  	 */  	nested = irq_settings_is_nested_thread(desc);  	if (nested) { -		if (!new->thread_fn) -			return -EINVAL; +		if (!new->thread_fn) { +			ret = -EINVAL; +			goto out_mput; +		}  		/*  		 * Replace the primary handler which was provided from  		 * the driver for non nested interrupt handling by the @@ -929,8 +933,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)  		t = kthread_create(irq_thread, new, "irq/%d-%s", irq,  				   new->name); -		if (IS_ERR(t)) -			return PTR_ERR(t); +		if (IS_ERR(t)) { +			ret = PTR_ERR(t); +			goto out_mput; +		}  		/*  		 * We keep the reference to the task struct even if  		 * the thread dies to avoid that the interrupt code @@ -1095,6 +1101,8 @@ out_thread:  			kthread_stop(t);  		put_task_struct(t);  	} +out_mput: +	module_put(desc->owner);  	return ret;  } @@ -1203,6 +1211,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)  		put_task_struct(action->thread);  	} +	module_put(desc->owner);  	return action;  }  | 
