Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch irq/irqdomain-locking into irq/irqchip-next

* irq/irqdomain-locking:
: .
: irqdomain locking overhaul courtesy of Johan Hovold.
:
: From the cover letter:
:
: "Parallel probing (e.g. due to asynchronous probing) of devices that
: share interrupts can currently result in two mappings for the same
: hardware interrupt to be created.
:
: This series fixes this mapping race and reworks the irqdomain locking so
: that in the end the global irq_domain_mutex is only used for managing
: the likewise global irq_domain_list, while domain operations (e.g. IRQ
: allocations) use per-domain (hierarchy) locking."
: .
irqdomain: Switch to per-domain locking
irqchip/mvebu-odmi: Use irq_domain_create_hierarchy()
irqchip/loongson-pch-msi: Use irq_domain_create_hierarchy()
irqchip/gic-v3-mbi: Use irq_domain_create_hierarchy()
irqchip/gic-v3-its: Use irq_domain_create_hierarchy()
irqchip/gic-v2m: Use irq_domain_create_hierarchy()
irqchip/alpine-msi: Use irq_domain_add_hierarchy()
x86/uv: Use irq_domain_create_hierarchy()
x86/ioapic: Use irq_domain_create_hierarchy()
irqdomain: Clean up irq_domain_push/pop_irq()
irqdomain: Drop leftover brackets
irqdomain: Drop dead domain-name assignment
irqdomain: Drop revmap mutex
irqdomain: Fix domain registration race
irqdomain: Fix mapping-creation race
irqdomain: Refactor __irq_domain_alloc_irqs()
irqdomain: Look for existing mapping only once
irqdomain: Drop bogus fwspec-mapping error handling
irqdomain: Fix disassociation race
irqdomain: Fix association race

Signed-off-by: Marc Zyngier <maz@kernel.org>

+282 -205
+2 -5
arch/x86/kernel/apic/io_apic.c
··· 2364 2364 return -ENODEV; 2365 2365 } 2366 2366 2367 - ip->irqdomain = irq_domain_create_linear(fn, hwirqs, cfg->ops, 2368 - (void *)(long)ioapic); 2369 - 2367 + ip->irqdomain = irq_domain_create_hierarchy(parent, 0, hwirqs, fn, cfg->ops, 2368 + (void *)(long)ioapic); 2370 2369 if (!ip->irqdomain) { 2371 2370 /* Release fw handle if it was allocated above */ 2372 2371 if (!cfg->dev) 2373 2372 irq_domain_free_fwnode(fn); 2374 2373 return -ENOMEM; 2375 2374 } 2376 - 2377 - ip->irqdomain->parent = parent; 2378 2375 2379 2376 if (cfg->type == IOAPIC_DOMAIN_LEGACY || 2380 2377 cfg->type == IOAPIC_DOMAIN_STRICT)
+3 -4
arch/x86/platform/uv/uv_irq.c
··· 166 166 if (!fn) 167 167 goto out; 168 168 169 - uv_domain = irq_domain_create_tree(fn, &uv_domain_ops, NULL); 170 - if (uv_domain) 171 - uv_domain->parent = x86_vector_domain; 172 - else 169 + uv_domain = irq_domain_create_hierarchy(x86_vector_domain, 0, 0, fn, 170 + &uv_domain_ops, NULL); 171 + if (!uv_domain) 173 172 irq_domain_free_fwnode(fn); 174 173 out: 175 174 mutex_unlock(&uv_lock);
+3 -5
drivers/irqchip/irq-alpine-msi.c
··· 205 205 return -ENXIO; 206 206 } 207 207 208 - middle_domain = irq_domain_add_tree(NULL, 209 - &alpine_msix_middle_domain_ops, 210 - priv); 208 + middle_domain = irq_domain_add_hierarchy(gic_domain, 0, 0, NULL, 209 + &alpine_msix_middle_domain_ops, 210 + priv); 211 211 if (!middle_domain) { 212 212 pr_err("Failed to create the MSIX middle domain\n"); 213 213 return -ENOMEM; 214 214 } 215 - 216 - middle_domain->parent = gic_domain; 217 215 218 216 msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), 219 217 &alpine_msix_domain_info,
+2 -3
drivers/irqchip/irq-gic-v2m.c
··· 287 287 if (!v2m) 288 288 return 0; 289 289 290 - inner_domain = irq_domain_create_tree(v2m->fwnode, 291 - &gicv2m_domain_ops, v2m); 290 + inner_domain = irq_domain_create_hierarchy(parent, 0, 0, v2m->fwnode, 291 + &gicv2m_domain_ops, v2m); 292 292 if (!inner_domain) { 293 293 pr_err("Failed to create GICv2m domain\n"); 294 294 return -ENOMEM; 295 295 } 296 296 297 297 irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS); 298 - inner_domain->parent = parent; 299 298 pci_domain = pci_msi_create_irq_domain(v2m->fwnode, 300 299 &gicv2m_msi_domain_info, 301 300 inner_domain);
+7 -6
drivers/irqchip/irq-gic-v3-its.c
··· 4909 4909 if (!info) 4910 4910 return -ENOMEM; 4911 4911 4912 - inner_domain = irq_domain_create_tree(handle, &its_domain_ops, its); 4912 + info->ops = &its_msi_domain_ops; 4913 + info->data = its; 4914 + 4915 + inner_domain = irq_domain_create_hierarchy(its_parent, 4916 + its->msi_domain_flags, 0, 4917 + handle, &its_domain_ops, 4918 + info); 4913 4919 if (!inner_domain) { 4914 4920 kfree(info); 4915 4921 return -ENOMEM; 4916 4922 } 4917 4923 4918 - inner_domain->parent = its_parent; 4919 4924 irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS); 4920 - inner_domain->flags |= its->msi_domain_flags; 4921 - info->ops = &its_msi_domain_ops; 4922 - info->data = its; 4923 - inner_domain->host_data = info; 4924 4925 4925 4926 return 0; 4926 4927 }
+2 -3
drivers/irqchip/irq-gic-v3-mbi.c
··· 233 233 struct irq_domain *nexus_domain, *pci_domain, *plat_domain; 234 234 int err; 235 235 236 - nexus_domain = irq_domain_create_tree(parent->fwnode, 237 - &mbi_domain_ops, NULL); 236 + nexus_domain = irq_domain_create_hierarchy(parent, 0, 0, parent->fwnode, 237 + &mbi_domain_ops, NULL); 238 238 if (!nexus_domain) 239 239 return -ENOMEM; 240 240 241 241 irq_domain_update_bus_token(nexus_domain, DOMAIN_BUS_NEXUS); 242 - nexus_domain->parent = parent; 243 242 244 243 err = mbi_allocate_pci_domain(nexus_domain, &pci_domain); 245 244
+4 -5
drivers/irqchip/irq-loongson-pch-msi.c
··· 163 163 { 164 164 struct irq_domain *middle_domain, *msi_domain; 165 165 166 - middle_domain = irq_domain_create_linear(domain_handle, 167 - priv->num_irqs, 168 - &pch_msi_middle_domain_ops, 169 - priv); 166 + middle_domain = irq_domain_create_hierarchy(parent, 0, priv->num_irqs, 167 + domain_handle, 168 + &pch_msi_middle_domain_ops, 169 + priv); 170 170 if (!middle_domain) { 171 171 pr_err("Failed to create the MSI middle domain\n"); 172 172 return -ENOMEM; 173 173 } 174 174 175 - middle_domain->parent = parent; 176 175 irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS); 177 176 178 177 msi_domain = pci_msi_create_irq_domain(domain_handle,
+7 -6
drivers/irqchip/irq-mvebu-odmi.c
··· 161 161 static int __init mvebu_odmi_init(struct device_node *node, 162 162 struct device_node *parent) 163 163 { 164 - struct irq_domain *inner_domain, *plat_domain; 164 + struct irq_domain *parent_domain, *inner_domain, *plat_domain; 165 165 int ret, i; 166 166 167 167 if (of_property_read_u32(node, "marvell,odmi-frames", &odmis_count)) ··· 197 197 } 198 198 } 199 199 200 - inner_domain = irq_domain_create_linear(of_node_to_fwnode(node), 201 - odmis_count * NODMIS_PER_FRAME, 202 - &odmi_domain_ops, NULL); 200 + parent_domain = irq_find_host(parent); 201 + 202 + inner_domain = irq_domain_create_hierarchy(parent_domain, 0, 203 + odmis_count * NODMIS_PER_FRAME, 204 + of_node_to_fwnode(node), 205 + &odmi_domain_ops, NULL); 203 206 if (!inner_domain) { 204 207 ret = -ENOMEM; 205 208 goto err_unmap; 206 209 } 207 - 208 - inner_domain->parent = irq_find_host(parent); 209 210 210 211 plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node), 211 212 &odmi_msi_domain_info,
+4 -2
include/linux/irqdomain.h
··· 125 125 * core code. 126 126 * @flags: Per irq_domain flags 127 127 * @mapcount: The number of mapped interrupts 128 + * @mutex: Domain lock, hierarchical domains use root domain's lock 129 + * @root: Pointer to root domain, or containing structure if non-hierarchical 128 130 * 129 131 * Optional elements: 130 132 * @fwnode: Pointer to firmware node associated with the irq_domain. Pretty easy ··· 145 143 * Revmap data, used internally by the irq domain code: 146 144 * @revmap_size: Size of the linear map table @revmap[] 147 145 * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map 148 - * @revmap_mutex: Lock for the revmap 149 146 * @revmap: Linear table of irq_data pointers 150 147 */ 151 148 struct irq_domain { ··· 154 153 void *host_data; 155 154 unsigned int flags; 156 155 unsigned int mapcount; 156 + struct mutex mutex; 157 + struct irq_domain *root; 157 158 158 159 /* Optional data */ 159 160 struct fwnode_handle *fwnode; ··· 174 171 irq_hw_number_t hwirq_max; 175 172 unsigned int revmap_size; 176 173 struct radix_tree_root revmap_tree; 177 - struct mutex revmap_mutex; 178 174 struct irq_data __rcu *revmap[]; 179 175 }; 180 176
+248 -166
kernel/irq/irqdomain.c
··· 25 25 26 26 static struct irq_domain *irq_default_domain; 27 27 28 + static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base, 29 + unsigned int nr_irqs, int node, void *arg, 30 + bool realloc, const struct irq_affinity_desc *affinity); 28 31 static void irq_domain_check_hierarchy(struct irq_domain *domain); 29 32 30 33 struct irqchip_fwid { ··· 126 123 } 127 124 EXPORT_SYMBOL_GPL(irq_domain_free_fwnode); 128 125 129 - /** 130 - * __irq_domain_add() - Allocate a new irq_domain data structure 131 - * @fwnode: firmware node for the interrupt controller 132 - * @size: Size of linear map; 0 for radix mapping only 133 - * @hwirq_max: Maximum number of interrupts supported by controller 134 - * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no 135 - * direct mapping 136 - * @ops: domain callbacks 137 - * @host_data: Controller private data pointer 138 - * 139 - * Allocates and initializes an irq_domain structure. 140 - * Returns pointer to IRQ domain, or NULL on failure. 141 - */ 142 - struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int size, 143 - irq_hw_number_t hwirq_max, int direct_max, 144 - const struct irq_domain_ops *ops, 145 - void *host_data) 126 + static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode, 127 + unsigned int size, 128 + irq_hw_number_t hwirq_max, 129 + int direct_max, 130 + const struct irq_domain_ops *ops, 131 + void *host_data) 146 132 { 147 133 struct irqchip_fwid *fwid; 148 134 struct irq_domain *domain; ··· 206 214 207 215 /* Fill structure */ 208 216 INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL); 209 - mutex_init(&domain->revmap_mutex); 210 217 domain->ops = ops; 211 218 domain->host_data = host_data; 212 219 domain->hwirq_max = hwirq_max; 213 220 214 - if (direct_max) { 221 + if (direct_max) 215 222 domain->flags |= IRQ_DOMAIN_FLAG_NO_MAP; 216 - } 217 223 218 224 domain->revmap_size = size; 219 225 226 + /* 227 + * Hierarchical domains use the domain lock of the root domain 228 + * (innermost domain). 229 + * 230 + * For non-hierarchical domains (as for root domains), the root 231 + * pointer is set to the domain itself so that &domain->root->mutex 232 + * always points to the right lock. 233 + */ 234 + mutex_init(&domain->mutex); 235 + domain->root = domain; 236 + 220 237 irq_domain_check_hierarchy(domain); 221 238 239 + return domain; 240 + } 241 + 242 + static void __irq_domain_publish(struct irq_domain *domain) 243 + { 222 244 mutex_lock(&irq_domain_mutex); 223 245 debugfs_add_domain_dir(domain); 224 246 list_add(&domain->link, &irq_domain_list); 225 247 mutex_unlock(&irq_domain_mutex); 226 248 227 249 pr_debug("Added domain %s\n", domain->name); 250 + } 251 + 252 + /** 253 + * __irq_domain_add() - Allocate a new irq_domain data structure 254 + * @fwnode: firmware node for the interrupt controller 255 + * @size: Size of linear map; 0 for radix mapping only 256 + * @hwirq_max: Maximum number of interrupts supported by controller 257 + * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no 258 + * direct mapping 259 + * @ops: domain callbacks 260 + * @host_data: Controller private data pointer 261 + * 262 + * Allocates and initializes an irq_domain structure. 263 + * Returns pointer to IRQ domain, or NULL on failure. 264 + */ 265 + struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, unsigned int size, 266 + irq_hw_number_t hwirq_max, int direct_max, 267 + const struct irq_domain_ops *ops, 268 + void *host_data) 269 + { 270 + struct irq_domain *domain; 271 + 272 + domain = __irq_domain_create(fwnode, size, hwirq_max, direct_max, 273 + ops, host_data); 274 + if (domain) 275 + __irq_domain_publish(domain); 276 + 228 277 return domain; 229 278 } 230 279 EXPORT_SYMBOL_GPL(__irq_domain_add); ··· 535 502 static void irq_domain_clear_mapping(struct irq_domain *domain, 536 503 irq_hw_number_t hwirq) 537 504 { 505 + lockdep_assert_held(&domain->root->mutex); 506 + 538 507 if (irq_domain_is_nomap(domain)) 539 508 return; 540 509 541 - mutex_lock(&domain->revmap_mutex); 542 510 if (hwirq < domain->revmap_size) 543 511 rcu_assign_pointer(domain->revmap[hwirq], NULL); 544 512 else 545 513 radix_tree_delete(&domain->revmap_tree, hwirq); 546 - mutex_unlock(&domain->revmap_mutex); 547 514 } 548 515 549 516 static void irq_domain_set_mapping(struct irq_domain *domain, 550 517 irq_hw_number_t hwirq, 551 518 struct irq_data *irq_data) 552 519 { 520 + /* 521 + * This also makes sure that all domains point to the same root when 522 + * called from irq_domain_insert_irq() for each domain in a hierarchy. 523 + */ 524 + lockdep_assert_held(&domain->root->mutex); 525 + 553 526 if (irq_domain_is_nomap(domain)) 554 527 return; 555 528 556 - mutex_lock(&domain->revmap_mutex); 557 529 if (hwirq < domain->revmap_size) 558 530 rcu_assign_pointer(domain->revmap[hwirq], irq_data); 559 531 else 560 532 radix_tree_insert(&domain->revmap_tree, hwirq, irq_data); 561 - mutex_unlock(&domain->revmap_mutex); 562 533 } 563 534 564 535 static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq) ··· 575 538 return; 576 539 577 540 hwirq = irq_data->hwirq; 541 + 542 + mutex_lock(&domain->root->mutex); 543 + 578 544 irq_set_status_flags(irq, IRQ_NOREQUEST); 579 545 580 546 /* remove chip and handler */ ··· 597 557 598 558 /* Clear reverse map for this hwirq */ 599 559 irq_domain_clear_mapping(domain, hwirq); 560 + 561 + mutex_unlock(&domain->root->mutex); 600 562 } 601 563 602 - int irq_domain_associate(struct irq_domain *domain, unsigned int virq, 603 - irq_hw_number_t hwirq) 564 + static int irq_domain_associate_locked(struct irq_domain *domain, unsigned int virq, 565 + irq_hw_number_t hwirq) 604 566 { 605 567 struct irq_data *irq_data = irq_get_irq_data(virq); 606 568 int ret; ··· 615 573 if (WARN(irq_data->domain, "error: virq%i is already associated", virq)) 616 574 return -EINVAL; 617 575 618 - mutex_lock(&irq_domain_mutex); 619 576 irq_data->hwirq = hwirq; 620 577 irq_data->domain = domain; 621 578 if (domain->ops->map) { ··· 631 590 } 632 591 irq_data->domain = NULL; 633 592 irq_data->hwirq = 0; 634 - mutex_unlock(&irq_domain_mutex); 635 593 return ret; 636 594 } 637 - 638 - /* If not already assigned, give the domain the chip's name */ 639 - if (!domain->name && irq_data->chip) 640 - domain->name = irq_data->chip->name; 641 595 } 642 596 643 597 domain->mapcount++; 644 598 irq_domain_set_mapping(domain, hwirq, irq_data); 645 - mutex_unlock(&irq_domain_mutex); 646 599 647 600 irq_clear_status_flags(virq, IRQ_NOREQUEST); 648 601 649 602 return 0; 603 + } 604 + 605 + int irq_domain_associate(struct irq_domain *domain, unsigned int virq, 606 + irq_hw_number_t hwirq) 607 + { 608 + int ret; 609 + 610 + mutex_lock(&domain->root->mutex); 611 + ret = irq_domain_associate_locked(domain, virq, hwirq); 612 + mutex_unlock(&domain->root->mutex); 613 + 614 + return ret; 650 615 } 651 616 EXPORT_SYMBOL_GPL(irq_domain_associate); 652 617 ··· 666 619 pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__, 667 620 of_node_full_name(of_node), irq_base, (int)hwirq_base, count); 668 621 669 - for (i = 0; i < count; i++) { 622 + for (i = 0; i < count; i++) 670 623 irq_domain_associate(domain, irq_base + i, hwirq_base + i); 671 - } 672 624 } 673 625 EXPORT_SYMBOL_GPL(irq_domain_associate_many); 674 626 ··· 714 668 EXPORT_SYMBOL_GPL(irq_create_direct_mapping); 715 669 #endif 716 670 671 + static unsigned int irq_create_mapping_affinity_locked(struct irq_domain *domain, 672 + irq_hw_number_t hwirq, 673 + const struct irq_affinity_desc *affinity) 674 + { 675 + struct device_node *of_node = irq_domain_get_of_node(domain); 676 + int virq; 677 + 678 + pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq); 679 + 680 + /* Allocate a virtual interrupt number */ 681 + virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), 682 + affinity); 683 + if (virq <= 0) { 684 + pr_debug("-> virq allocation failed\n"); 685 + return 0; 686 + } 687 + 688 + if (irq_domain_associate_locked(domain, virq, hwirq)) { 689 + irq_free_desc(virq); 690 + return 0; 691 + } 692 + 693 + pr_debug("irq %lu on domain %s mapped to virtual irq %u\n", 694 + hwirq, of_node_full_name(of_node), virq); 695 + 696 + return virq; 697 + } 698 + 717 699 /** 718 700 * irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space 719 701 * @domain: domain owning this hardware interrupt or NULL for default domain ··· 754 680 * on the number returned from that call. 755 681 */ 756 682 unsigned int irq_create_mapping_affinity(struct irq_domain *domain, 757 - irq_hw_number_t hwirq, 758 - const struct irq_affinity_desc *affinity) 683 + irq_hw_number_t hwirq, 684 + const struct irq_affinity_desc *affinity) 759 685 { 760 - struct device_node *of_node; 761 686 int virq; 762 - 763 - pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq); 764 687 765 688 /* Look for default domain if necessary */ 766 689 if (domain == NULL) ··· 766 695 WARN(1, "%s(, %lx) called with NULL domain\n", __func__, hwirq); 767 696 return 0; 768 697 } 769 - pr_debug("-> using domain @%p\n", domain); 770 698 771 - of_node = irq_domain_get_of_node(domain); 699 + mutex_lock(&domain->root->mutex); 772 700 773 701 /* Check if mapping already exists */ 774 702 virq = irq_find_mapping(domain, hwirq); 775 703 if (virq) { 776 - pr_debug("-> existing mapping on virq %d\n", virq); 777 - return virq; 704 + pr_debug("existing mapping on virq %d\n", virq); 705 + goto out; 778 706 } 779 707 780 - /* Allocate a virtual interrupt number */ 781 - virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), 782 - affinity); 783 - if (virq <= 0) { 784 - pr_debug("-> virq allocation failed\n"); 785 - return 0; 786 - } 787 - 788 - if (irq_domain_associate(domain, virq, hwirq)) { 789 - irq_free_desc(virq); 790 - return 0; 791 - } 792 - 793 - pr_debug("irq %lu on domain %s mapped to virtual irq %u\n", 794 - hwirq, of_node_full_name(of_node), virq); 708 + virq = irq_create_mapping_affinity_locked(domain, hwirq, affinity); 709 + out: 710 + mutex_unlock(&domain->root->mutex); 795 711 796 712 return virq; 797 713 } ··· 847 789 if (WARN_ON(type & ~IRQ_TYPE_SENSE_MASK)) 848 790 type &= IRQ_TYPE_SENSE_MASK; 849 791 792 + mutex_lock(&domain->root->mutex); 793 + 850 794 /* 851 795 * If we've already configured this interrupt, 852 796 * don't do it again, or hell will break loose. ··· 861 801 * interrupt number. 862 802 */ 863 803 if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq)) 864 - return virq; 804 + goto out; 865 805 866 806 /* 867 807 * If the trigger type has not been set yet, then set ··· 869 809 */ 870 810 if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) { 871 811 irq_data = irq_get_irq_data(virq); 872 - if (!irq_data) 873 - return 0; 812 + if (!irq_data) { 813 + virq = 0; 814 + goto out; 815 + } 874 816 875 817 irqd_set_trigger_type(irq_data, type); 876 - return virq; 818 + goto out; 877 819 } 878 820 879 821 pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n", 880 822 hwirq, of_node_full_name(to_of_node(fwspec->fwnode))); 881 - return 0; 823 + virq = 0; 824 + goto out; 882 825 } 883 826 884 827 if (irq_domain_is_hierarchy(domain)) { 885 - virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec); 886 - if (virq <= 0) 887 - return 0; 828 + virq = irq_domain_alloc_irqs_locked(domain, -1, 1, NUMA_NO_NODE, 829 + fwspec, false, NULL); 830 + if (virq <= 0) { 831 + virq = 0; 832 + goto out; 833 + } 888 834 } else { 889 835 /* Create mapping */ 890 - virq = irq_create_mapping(domain, hwirq); 836 + virq = irq_create_mapping_affinity_locked(domain, hwirq, NULL); 891 837 if (!virq) 892 - return virq; 838 + goto out; 893 839 } 894 840 895 841 irq_data = irq_get_irq_data(virq); 896 - if (!irq_data) { 897 - if (irq_domain_is_hierarchy(domain)) 898 - irq_domain_free_irqs(virq, 1); 899 - else 900 - irq_dispose_mapping(virq); 901 - return 0; 842 + if (WARN_ON(!irq_data)) { 843 + virq = 0; 844 + goto out; 902 845 } 903 846 904 847 /* Store trigger type */ 905 848 irqd_set_trigger_type(irq_data, type); 849 + out: 850 + mutex_unlock(&domain->root->mutex); 906 851 907 852 return virq; 908 853 } ··· 1167 1102 struct irq_domain *domain; 1168 1103 1169 1104 if (size) 1170 - domain = irq_domain_create_linear(fwnode, size, ops, host_data); 1105 + domain = __irq_domain_create(fwnode, size, size, 0, ops, host_data); 1171 1106 else 1172 - domain = irq_domain_create_tree(fwnode, ops, host_data); 1107 + domain = __irq_domain_create(fwnode, 0, ~0, 0, ops, host_data); 1108 + 1173 1109 if (domain) { 1110 + domain->root = parent->root; 1174 1111 domain->parent = parent; 1175 1112 domain->flags |= flags; 1113 + 1114 + __irq_domain_publish(domain); 1176 1115 } 1177 1116 1178 1117 return domain; ··· 1192 1123 1193 1124 domain->mapcount++; 1194 1125 irq_domain_set_mapping(domain, data->hwirq, data); 1195 - 1196 - /* If not already assigned, give the domain the chip's name */ 1197 - if (!domain->name && data->chip) 1198 - domain->name = data->chip->name; 1199 1126 } 1200 1127 1201 1128 irq_clear_status_flags(virq, IRQ_NOREQUEST); ··· 1491 1426 return domain->ops->alloc(domain, irq_base, nr_irqs, arg); 1492 1427 } 1493 1428 1429 + static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base, 1430 + unsigned int nr_irqs, int node, void *arg, 1431 + bool realloc, const struct irq_affinity_desc *affinity) 1432 + { 1433 + int i, ret, virq; 1434 + 1435 + if (realloc && irq_base >= 0) { 1436 + virq = irq_base; 1437 + } else { 1438 + virq = irq_domain_alloc_descs(irq_base, nr_irqs, 0, node, 1439 + affinity); 1440 + if (virq < 0) { 1441 + pr_debug("cannot allocate IRQ(base %d, count %d)\n", 1442 + irq_base, nr_irqs); 1443 + return virq; 1444 + } 1445 + } 1446 + 1447 + if (irq_domain_alloc_irq_data(domain, virq, nr_irqs)) { 1448 + pr_debug("cannot allocate memory for IRQ%d\n", virq); 1449 + ret = -ENOMEM; 1450 + goto out_free_desc; 1451 + } 1452 + 1453 + ret = irq_domain_alloc_irqs_hierarchy(domain, virq, nr_irqs, arg); 1454 + if (ret < 0) 1455 + goto out_free_irq_data; 1456 + 1457 + for (i = 0; i < nr_irqs; i++) { 1458 + ret = irq_domain_trim_hierarchy(virq + i); 1459 + if (ret) 1460 + goto out_free_irq_data; 1461 + } 1462 + 1463 + for (i = 0; i < nr_irqs; i++) 1464 + irq_domain_insert_irq(virq + i); 1465 + 1466 + return virq; 1467 + 1468 + out_free_irq_data: 1469 + irq_domain_free_irq_data(virq, nr_irqs); 1470 + out_free_desc: 1471 + irq_free_descs(virq, nr_irqs); 1472 + return ret; 1473 + } 1474 + 1494 1475 /** 1495 1476 * __irq_domain_alloc_irqs - Allocate IRQs from domain 1496 1477 * @domain: domain to allocate from ··· 1563 1452 unsigned int nr_irqs, int node, void *arg, 1564 1453 bool realloc, const struct irq_affinity_desc *affinity) 1565 1454 { 1566 - int i, ret, virq; 1455 + int ret; 1567 1456 1568 1457 if (domain == NULL) { 1569 1458 domain = irq_default_domain; ··· 1571 1460 return -EINVAL; 1572 1461 } 1573 1462 1574 - if (realloc && irq_base >= 0) { 1575 - virq = irq_base; 1576 - } else { 1577 - virq = irq_domain_alloc_descs(irq_base, nr_irqs, 0, node, 1578 - affinity); 1579 - if (virq < 0) { 1580 - pr_debug("cannot allocate IRQ(base %d, count %d)\n", 1581 - irq_base, nr_irqs); 1582 - return virq; 1583 - } 1584 - } 1463 + mutex_lock(&domain->root->mutex); 1464 + ret = irq_domain_alloc_irqs_locked(domain, irq_base, nr_irqs, node, arg, 1465 + realloc, affinity); 1466 + mutex_unlock(&domain->root->mutex); 1585 1467 1586 - if (irq_domain_alloc_irq_data(domain, virq, nr_irqs)) { 1587 - pr_debug("cannot allocate memory for IRQ%d\n", virq); 1588 - ret = -ENOMEM; 1589 - goto out_free_desc; 1590 - } 1591 - 1592 - mutex_lock(&irq_domain_mutex); 1593 - ret = irq_domain_alloc_irqs_hierarchy(domain, virq, nr_irqs, arg); 1594 - if (ret < 0) { 1595 - mutex_unlock(&irq_domain_mutex); 1596 - goto out_free_irq_data; 1597 - } 1598 - 1599 - for (i = 0; i < nr_irqs; i++) { 1600 - ret = irq_domain_trim_hierarchy(virq + i); 1601 - if (ret) { 1602 - mutex_unlock(&irq_domain_mutex); 1603 - goto out_free_irq_data; 1604 - } 1605 - } 1606 - 1607 - for (i = 0; i < nr_irqs; i++) 1608 - irq_domain_insert_irq(virq + i); 1609 - mutex_unlock(&irq_domain_mutex); 1610 - 1611 - return virq; 1612 - 1613 - out_free_irq_data: 1614 - irq_domain_free_irq_data(virq, nr_irqs); 1615 - out_free_desc: 1616 - irq_free_descs(virq, nr_irqs); 1617 1468 return ret; 1618 1469 } 1619 1470 EXPORT_SYMBOL_GPL(__irq_domain_alloc_irqs); ··· 1585 1512 { 1586 1513 void __rcu **slot; 1587 1514 1515 + lockdep_assert_held(&d->domain->root->mutex); 1516 + 1588 1517 if (irq_domain_is_nomap(d->domain)) 1589 1518 return; 1590 1519 1591 1520 /* Fix up the revmap. */ 1592 - mutex_lock(&d->domain->revmap_mutex); 1593 1521 if (d->hwirq < d->domain->revmap_size) { 1594 1522 /* Not using radix tree */ 1595 1523 rcu_assign_pointer(d->domain->revmap[d->hwirq], d); ··· 1599 1525 if (slot) 1600 1526 radix_tree_replace_slot(&d->domain->revmap_tree, slot, d); 1601 1527 } 1602 - mutex_unlock(&d->domain->revmap_mutex); 1603 1528 } 1604 1529 1605 1530 /** ··· 1614 1541 */ 1615 1542 int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg) 1616 1543 { 1617 - struct irq_data *child_irq_data; 1618 - struct irq_data *root_irq_data = irq_get_irq_data(virq); 1544 + struct irq_data *irq_data = irq_get_irq_data(virq); 1545 + struct irq_data *parent_irq_data; 1619 1546 struct irq_desc *desc; 1620 1547 int rv = 0; 1621 1548 ··· 1640 1567 if (WARN_ON(!irq_domain_is_hierarchy(domain))) 1641 1568 return -EINVAL; 1642 1569 1643 - if (!root_irq_data) 1570 + if (!irq_data) 1644 1571 return -EINVAL; 1645 1572 1646 - if (domain->parent != root_irq_data->domain) 1573 + if (domain->parent != irq_data->domain) 1647 1574 return -EINVAL; 1648 1575 1649 - child_irq_data = kzalloc_node(sizeof(*child_irq_data), GFP_KERNEL, 1650 - irq_data_get_node(root_irq_data)); 1651 - if (!child_irq_data) 1576 + parent_irq_data = kzalloc_node(sizeof(*parent_irq_data), GFP_KERNEL, 1577 + irq_data_get_node(irq_data)); 1578 + if (!parent_irq_data) 1652 1579 return -ENOMEM; 1653 1580 1654 - mutex_lock(&irq_domain_mutex); 1581 + mutex_lock(&domain->root->mutex); 1655 1582 1656 1583 /* Copy the original irq_data. */ 1657 - *child_irq_data = *root_irq_data; 1584 + *parent_irq_data = *irq_data; 1658 1585 1659 1586 /* 1660 - * Overwrite the root_irq_data, which is embedded in struct 1661 - * irq_desc, with values for this domain. 1587 + * Overwrite the irq_data, which is embedded in struct irq_desc, with 1588 + * values for this domain. 1662 1589 */ 1663 - root_irq_data->parent_data = child_irq_data; 1664 - root_irq_data->domain = domain; 1665 - root_irq_data->mask = 0; 1666 - root_irq_data->hwirq = 0; 1667 - root_irq_data->chip = NULL; 1668 - root_irq_data->chip_data = NULL; 1590 + irq_data->parent_data = parent_irq_data; 1591 + irq_data->domain = domain; 1592 + irq_data->mask = 0; 1593 + irq_data->hwirq = 0; 1594 + irq_data->chip = NULL; 1595 + irq_data->chip_data = NULL; 1669 1596 1670 1597 /* May (probably does) set hwirq, chip, etc. */ 1671 1598 rv = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg); 1672 1599 if (rv) { 1673 1600 /* Restore the original irq_data. */ 1674 - *root_irq_data = *child_irq_data; 1675 - kfree(child_irq_data); 1601 + *irq_data = *parent_irq_data; 1602 + kfree(parent_irq_data); 1676 1603 goto error; 1677 1604 } 1678 1605 1679 - irq_domain_fix_revmap(child_irq_data); 1680 - irq_domain_set_mapping(domain, root_irq_data->hwirq, root_irq_data); 1681 - 1606 + irq_domain_fix_revmap(parent_irq_data); 1607 + irq_domain_set_mapping(domain, irq_data->hwirq, irq_data); 1682 1608 error: 1683 - mutex_unlock(&irq_domain_mutex); 1609 + mutex_unlock(&domain->root->mutex); 1684 1610 1685 1611 return rv; 1686 1612 } ··· 1695 1623 */ 1696 1624 int irq_domain_pop_irq(struct irq_domain *domain, int virq) 1697 1625 { 1698 - struct irq_data *root_irq_data = irq_get_irq_data(virq); 1699 - struct irq_data *child_irq_data; 1626 + struct irq_data *irq_data = irq_get_irq_data(virq); 1627 + struct irq_data *parent_irq_data; 1700 1628 struct irq_data *tmp_irq_data; 1701 1629 struct irq_desc *desc; 1702 1630 ··· 1718 1646 if (domain == NULL) 1719 1647 return -EINVAL; 1720 1648 1721 - if (!root_irq_data) 1649 + if (!irq_data) 1722 1650 return -EINVAL; 1723 1651 1724 1652 tmp_irq_data = irq_domain_get_irq_data(domain, virq); 1725 1653 1726 1654 /* We can only "pop" if this domain is at the top of the list */ 1727 - if (WARN_ON(root_irq_data != tmp_irq_data)) 1655 + if (WARN_ON(irq_data != tmp_irq_data)) 1728 1656 return -EINVAL; 1729 1657 1730 - if (WARN_ON(root_irq_data->domain != domain)) 1658 + if (WARN_ON(irq_data->domain != domain)) 1731 1659 return -EINVAL; 1732 1660 1733 - child_irq_data = root_irq_data->parent_data; 1734 - if (WARN_ON(!child_irq_data)) 1661 + parent_irq_data = irq_data->parent_data; 1662 + if (WARN_ON(!parent_irq_data)) 1735 1663 return -EINVAL; 1736 1664 1737 - mutex_lock(&irq_domain_mutex); 1665 + mutex_lock(&domain->root->mutex); 1738 1666 1739 - root_irq_data->parent_data = NULL; 1667 + irq_data->parent_data = NULL; 1740 1668 1741 - irq_domain_clear_mapping(domain, root_irq_data->hwirq); 1669 + irq_domain_clear_mapping(domain, irq_data->hwirq); 1742 1670 irq_domain_free_irqs_hierarchy(domain, virq, 1); 1743 1671 1744 1672 /* Restore the original irq_data. */ 1745 - *root_irq_data = *child_irq_data; 1673 + *irq_data = *parent_irq_data; 1746 1674 1747 - irq_domain_fix_revmap(root_irq_data); 1675 + irq_domain_fix_revmap(irq_data); 1748 1676 1749 - mutex_unlock(&irq_domain_mutex); 1677 + mutex_unlock(&domain->root->mutex); 1750 1678 1751 - kfree(child_irq_data); 1679 + kfree(parent_irq_data); 1752 1680 1753 1681 return 0; 1754 1682 } ··· 1762 1690 void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs) 1763 1691 { 1764 1692 struct irq_data *data = irq_get_irq_data(virq); 1693 + struct irq_domain *domain; 1765 1694 int i; 1766 1695 1767 1696 if (WARN(!data || !data->domain || !data->domain->ops->free, 1768 1697 "NULL pointer, cannot free irq\n")) 1769 1698 return; 1770 1699 1771 - mutex_lock(&irq_domain_mutex); 1700 + domain = data->domain; 1701 + 1702 + mutex_lock(&domain->root->mutex); 1772 1703 for (i = 0; i < nr_irqs; i++) 1773 1704 irq_domain_remove_irq(virq + i); 1774 - irq_domain_free_irqs_hierarchy(data->domain, virq, nr_irqs); 1775 - mutex_unlock(&irq_domain_mutex); 1705 + irq_domain_free_irqs_hierarchy(domain, virq, nr_irqs); 1706 + mutex_unlock(&domain->root->mutex); 1776 1707 1777 1708 irq_domain_free_irq_data(virq, nr_irqs); 1778 1709 irq_free_descs(virq, nr_irqs); ··· 1938 1863 irq_set_chip_and_handler_name(virq, chip, handler, handler_name); 1939 1864 irq_set_chip_data(virq, chip_data); 1940 1865 irq_set_handler_data(virq, handler_data); 1866 + } 1867 + 1868 + static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base, 1869 + unsigned int nr_irqs, int node, void *arg, 1870 + bool realloc, const struct irq_affinity_desc *affinity) 1871 + { 1872 + return -EINVAL; 1941 1873 } 1942 1874 1943 1875 static void irq_domain_check_hierarchy(struct irq_domain *domain)