diff options
Diffstat (limited to 'kernel/irq/irqdesc.c')
-rw-r--r-- | kernel/irq/irqdesc.c | 24 |
1 files changed, 7 insertions, 17 deletions
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 73be2b3909bd..82afb7ed369f 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
@@ -421,10 +421,8 @@ static void free_desc(unsigned int irq) | |||
421 | * The sysfs entry must be serialized against a concurrent | 421 | * The sysfs entry must be serialized against a concurrent |
422 | * irq_sysfs_init() as well. | 422 | * irq_sysfs_init() as well. |
423 | */ | 423 | */ |
424 | mutex_lock(&sparse_irq_lock); | ||
425 | kobject_del(&desc->kobj); | 424 | kobject_del(&desc->kobj); |
426 | delete_irq_desc(irq); | 425 | delete_irq_desc(irq); |
427 | mutex_unlock(&sparse_irq_lock); | ||
428 | 426 | ||
429 | /* | 427 | /* |
430 | * We free the descriptor, masks and stat fields via RCU. That | 428 | * We free the descriptor, masks and stat fields via RCU. That |
@@ -462,20 +460,15 @@ static int alloc_descs(unsigned int start, unsigned int cnt, int node, | |||
462 | desc = alloc_desc(start + i, node, flags, mask, owner); | 460 | desc = alloc_desc(start + i, node, flags, mask, owner); |
463 | if (!desc) | 461 | if (!desc) |
464 | goto err; | 462 | goto err; |
465 | mutex_lock(&sparse_irq_lock); | ||
466 | irq_insert_desc(start + i, desc); | 463 | irq_insert_desc(start + i, desc); |
467 | irq_sysfs_add(start + i, desc); | 464 | irq_sysfs_add(start + i, desc); |
468 | mutex_unlock(&sparse_irq_lock); | ||
469 | } | 465 | } |
466 | bitmap_set(allocated_irqs, start, cnt); | ||
470 | return start; | 467 | return start; |
471 | 468 | ||
472 | err: | 469 | err: |
473 | for (i--; i >= 0; i--) | 470 | for (i--; i >= 0; i--) |
474 | free_desc(start + i); | 471 | free_desc(start + i); |
475 | |||
476 | mutex_lock(&sparse_irq_lock); | ||
477 | bitmap_clear(allocated_irqs, start, cnt); | ||
478 | mutex_unlock(&sparse_irq_lock); | ||
479 | return -ENOMEM; | 472 | return -ENOMEM; |
480 | } | 473 | } |
481 | 474 | ||
@@ -575,6 +568,7 @@ static inline int alloc_descs(unsigned int start, unsigned int cnt, int node, | |||
575 | 568 | ||
576 | desc->owner = owner; | 569 | desc->owner = owner; |
577 | } | 570 | } |
571 | bitmap_set(allocated_irqs, start, cnt); | ||
578 | return start; | 572 | return start; |
579 | } | 573 | } |
580 | 574 | ||
@@ -670,10 +664,10 @@ void irq_free_descs(unsigned int from, unsigned int cnt) | |||
670 | if (from >= nr_irqs || (from + cnt) > nr_irqs) | 664 | if (from >= nr_irqs || (from + cnt) > nr_irqs) |
671 | return; | 665 | return; |
672 | 666 | ||
667 | mutex_lock(&sparse_irq_lock); | ||
673 | for (i = 0; i < cnt; i++) | 668 | for (i = 0; i < cnt; i++) |
674 | free_desc(from + i); | 669 | free_desc(from + i); |
675 | 670 | ||
676 | mutex_lock(&sparse_irq_lock); | ||
677 | bitmap_clear(allocated_irqs, from, cnt); | 671 | bitmap_clear(allocated_irqs, from, cnt); |
678 | mutex_unlock(&sparse_irq_lock); | 672 | mutex_unlock(&sparse_irq_lock); |
679 | } | 673 | } |
@@ -720,19 +714,15 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, | |||
720 | from, cnt, 0); | 714 | from, cnt, 0); |
721 | ret = -EEXIST; | 715 | ret = -EEXIST; |
722 | if (irq >=0 && start != irq) | 716 | if (irq >=0 && start != irq) |
723 | goto err; | 717 | goto unlock; |
724 | 718 | ||
725 | if (start + cnt > nr_irqs) { | 719 | if (start + cnt > nr_irqs) { |
726 | ret = irq_expand_nr_irqs(start + cnt); | 720 | ret = irq_expand_nr_irqs(start + cnt); |
727 | if (ret) | 721 | if (ret) |
728 | goto err; | 722 | goto unlock; |
729 | } | 723 | } |
730 | 724 | ret = alloc_descs(start, cnt, node, affinity, owner); | |
731 | bitmap_set(allocated_irqs, start, cnt); | 725 | unlock: |
732 | mutex_unlock(&sparse_irq_lock); | ||
733 | return alloc_descs(start, cnt, node, affinity, owner); | ||
734 | |||
735 | err: | ||
736 | mutex_unlock(&sparse_irq_lock); | 726 | mutex_unlock(&sparse_irq_lock); |
737 | return ret; | 727 | return ret; |
738 | } | 728 | } |