Lines Matching +full:interrupt +full:- +full:affinity

1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/interrupt.h>
30 bool realloc, const struct irq_affinity_desc *affinity);
53 return fwid->name; in irqchip_fwnode_get_name()
62 * __irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
67 * @pa: Optional user-provided physical address
91 n = kasprintf(GFP_KERNEL, "%s-%d", name, id); in __irq_domain_alloc_fwnode()
104 fwid->type = type; in __irq_domain_alloc_fwnode()
105 fwid->name = n; in __irq_domain_alloc_fwnode()
106 fwid->pa = pa; in __irq_domain_alloc_fwnode()
107 fwnode_init(&fwid->fwnode, &irqchip_fwnode_ops); in __irq_domain_alloc_fwnode()
108 return &fwid->fwnode; in __irq_domain_alloc_fwnode()
113 * irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle
126 kfree(fwid->name); in irq_domain_free_fwnode()
134 domain->name = kasprintf(GFP_KERNEL, "%s", base); in alloc_name()
136 domain->name = kasprintf(GFP_KERNEL, "%s-%d", base, bus_token); in alloc_name()
137 if (!domain->name) in alloc_name()
138 return -ENOMEM; in alloc_name()
140 domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; in alloc_name()
147 const char *sep = suffix ? "-" : ""; in alloc_fwnode_name()
154 name = kasprintf(GFP_KERNEL, "%pfw%s%s-%d", fwnode, sep, suf, bus_token); in alloc_fwnode_name()
156 return -ENOMEM; in alloc_fwnode_name()
163 domain->name = strreplace(name, '/', ':'); in alloc_fwnode_name()
164 domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; in alloc_fwnode_name()
174 domain->name = kasprintf(GFP_KERNEL, "unknown-%d", id); in alloc_unknown_name()
176 domain->name = kasprintf(GFP_KERNEL, "unknown-%d-%d", id, bus_token); in alloc_unknown_name()
177 if (!domain->name) in alloc_unknown_name()
178 return -ENOMEM; in alloc_unknown_name()
180 domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; in alloc_unknown_name()
186 enum irq_domain_bus_token bus_token = info->bus_token; in irq_domain_set_name()
187 const struct fwnode_handle *fwnode = info->fwnode; in irq_domain_set_name()
196 * (Typical use-case is regmap-IRQ controllers for devices in irq_domain_set_name()
198 * need to use name_suffix with irqchip-fwnode. in irq_domain_set_name()
200 if (info->name_suffix) in irq_domain_set_name()
201 return -EINVAL; in irq_domain_set_name()
203 switch (fwid->type) { in irq_domain_set_name()
206 return alloc_name(domain, fwid->name, bus_token); in irq_domain_set_name()
208 domain->name = fwid->name; in irq_domain_set_name()
210 return alloc_name(domain, fwid->name, bus_token); in irq_domain_set_name()
214 return alloc_fwnode_name(domain, fwnode, bus_token, info->name_suffix); in irq_domain_set_name()
217 if (domain->name) in irq_domain_set_name()
230 if (WARN_ON((info->size && info->direct_max) || in __irq_domain_create()
231 (!IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) && info->direct_max) || in __irq_domain_create()
232 (info->direct_max && info->direct_max != info->hwirq_max))) in __irq_domain_create()
233 return ERR_PTR(-EINVAL); in __irq_domain_create()
235 domain = kzalloc_node(struct_size(domain, revmap, info->size), in __irq_domain_create()
236 GFP_KERNEL, of_node_to_nid(to_of_node(info->fwnode))); in __irq_domain_create()
238 return ERR_PTR(-ENOMEM); in __irq_domain_create()
246 domain->fwnode = fwnode_handle_get(info->fwnode); in __irq_domain_create()
247 fwnode_dev_initialized(domain->fwnode, true); in __irq_domain_create()
250 INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL); in __irq_domain_create()
251 domain->ops = info->ops; in __irq_domain_create()
252 domain->host_data = info->host_data; in __irq_domain_create()
253 domain->bus_token = info->bus_token; in __irq_domain_create()
254 domain->hwirq_max = info->hwirq_max; in __irq_domain_create()
256 if (info->direct_max) in __irq_domain_create()
257 domain->flags |= IRQ_DOMAIN_FLAG_NO_MAP; in __irq_domain_create()
259 domain->revmap_size = info->size; in __irq_domain_create()
265 * For non-hierarchical domains (as for root domains), the root in __irq_domain_create()
266 * pointer is set to the domain itself so that &domain->root->mutex in __irq_domain_create()
269 mutex_init(&domain->mutex); in __irq_domain_create()
270 domain->root = domain; in __irq_domain_create()
281 list_add(&domain->link, &irq_domain_list); in __irq_domain_publish()
284 pr_debug("Added domain %s\n", domain->name); in __irq_domain_publish()
289 fwnode_dev_initialized(domain->fwnode, false); in irq_domain_free()
290 fwnode_handle_put(domain->fwnode); in irq_domain_free()
291 if (domain->flags & IRQ_DOMAIN_NAME_ALLOCATED) in irq_domain_free()
292 kfree(domain->name); in irq_domain_free()
301 if (irq_alloc_descs(info->virq_base, info->virq_base, info->size, in irq_domain_instantiate_descs()
302 of_node_to_nid(to_of_node(info->fwnode))) < 0) { in irq_domain_instantiate_descs()
303 pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", in irq_domain_instantiate_descs()
304 info->virq_base); in irq_domain_instantiate_descs()
318 domain->flags |= info->domain_flags; in __irq_domain_instantiate()
319 domain->exit = info->exit; in __irq_domain_instantiate()
322 if (info->parent) { in __irq_domain_instantiate()
323 domain->root = info->parent->root; in __irq_domain_instantiate()
324 domain->parent = info->parent; in __irq_domain_instantiate()
328 if (info->dgc_info) { in __irq_domain_instantiate()
329 err = irq_domain_alloc_generic_chips(domain, info->dgc_info); in __irq_domain_instantiate()
334 if (info->init) { in __irq_domain_instantiate()
335 err = info->init(domain); in __irq_domain_instantiate()
342 if (cond_alloc_descs && info->virq_base > 0) in __irq_domain_instantiate()
346 * Legacy interrupt domains have a fixed Linux interrupt number in __irq_domain_instantiate()
347 * associated. Other interrupt domains can request association by in __irq_domain_instantiate()
348 * providing a Linux interrupt number > 0. in __irq_domain_instantiate()
350 if (force_associate || info->virq_base > 0) { in __irq_domain_instantiate()
351 irq_domain_associate_many(domain, info->virq_base, info->hwirq_base, in __irq_domain_instantiate()
352 info->size - info->hwirq_base); in __irq_domain_instantiate()
358 if (info->dgc_info) in __irq_domain_instantiate()
366 * irq_domain_instantiate() - Instantiate a new irq domain data structure
378 * irq_domain_remove() - Remove an irq domain.
387 if (domain->exit) in irq_domain_remove()
388 domain->exit(domain); in irq_domain_remove()
393 WARN_ON(!radix_tree_empty(&domain->revmap_tree)); in irq_domain_remove()
395 list_del(&domain->link); in irq_domain_remove()
405 if (domain->flags & IRQ_DOMAIN_FLAG_DESTROY_GC) in irq_domain_remove()
408 pr_debug("Removed domain %s\n", domain->name); in irq_domain_remove()
418 if (domain->bus_token == bus_token) in irq_domain_update_bus_token()
423 domain->bus_token = bus_token; in irq_domain_update_bus_token()
425 name = kasprintf(GFP_KERNEL, "%s-%d", domain->name, bus_token); in irq_domain_update_bus_token()
433 if (domain->flags & IRQ_DOMAIN_NAME_ALLOCATED) in irq_domain_update_bus_token()
434 kfree(domain->name); in irq_domain_update_bus_token()
436 domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; in irq_domain_update_bus_token()
438 domain->name = name; in irq_domain_update_bus_token()
446 * irq_domain_create_simple() - Register an irq_domain and optionally map a range of irqs
447 * @fwnode: firmware node for the interrupt controller
450 * pass zero to assign irqs on-the-fly. If first_irq is non-zero, then
451 * pre-map all of the irqs in the domain to virqs starting at first_irq.
459 * interrupt controllers. If device tree is used, then first_irq will be 0 and
461 * static virq assignments (non-DT boot) then it will set that up correctly.
484 * irq_domain_add_legacy() - Allocate and register a legacy revmap irq_domain.
485 * @of_node: pointer to interrupt controller's device tree node.
533 * irq_find_matching_fwspec() - Locates a domain for a given fwspec
534 * @fwspec: FW specifier for an interrupt
535 * @bus_token: domain-specific data
541 struct fwnode_handle *fwnode = fwspec->fwnode; in irq_find_matching_fwspec()
556 if (h->ops->select && bus_token != DOMAIN_BUS_ANY) in irq_find_matching_fwspec()
557 rc = h->ops->select(h, fwspec, bus_token); in irq_find_matching_fwspec()
558 else if (h->ops->match) in irq_find_matching_fwspec()
559 rc = h->ops->match(h, to_of_node(fwnode), bus_token); in irq_find_matching_fwspec()
561 rc = ((fwnode != NULL) && (h->fwnode == fwnode) && in irq_find_matching_fwspec()
563 (h->bus_token == bus_token))); in irq_find_matching_fwspec()
576 * irq_set_default_host() - Set a "default" irq domain
581 * platforms that want to manipulate a few hard coded interrupt numbers that
582 * aren't properly represented in the device-tree.
593 * irq_get_default_host() - Retrieve the "default" irq domain
598 * systems that cannot implement a firmware->fwnode mapping (which
610 (domain->flags & IRQ_DOMAIN_FLAG_NO_MAP); in irq_domain_is_nomap()
616 lockdep_assert_held(&domain->root->mutex); in irq_domain_clear_mapping()
621 if (hwirq < domain->revmap_size) in irq_domain_clear_mapping()
622 rcu_assign_pointer(domain->revmap[hwirq], NULL); in irq_domain_clear_mapping()
624 radix_tree_delete(&domain->revmap_tree, hwirq); in irq_domain_clear_mapping()
635 lockdep_assert_held(&domain->root->mutex); in irq_domain_set_mapping()
640 if (hwirq < domain->revmap_size) in irq_domain_set_mapping()
641 rcu_assign_pointer(domain->revmap[hwirq], irq_data); in irq_domain_set_mapping()
643 radix_tree_insert(&domain->revmap_tree, hwirq, irq_data); in irq_domain_set_mapping()
651 if (WARN(!irq_data || irq_data->domain != domain, in irq_domain_disassociate()
655 hwirq = irq_data->hwirq; in irq_domain_disassociate()
657 mutex_lock(&domain->root->mutex); in irq_domain_disassociate()
668 if (domain->ops->unmap) in irq_domain_disassociate()
669 domain->ops->unmap(domain, irq); in irq_domain_disassociate()
672 irq_data->domain = NULL; in irq_domain_disassociate()
673 irq_data->hwirq = 0; in irq_domain_disassociate()
674 domain->mapcount--; in irq_domain_disassociate()
679 mutex_unlock(&domain->root->mutex); in irq_domain_disassociate()
688 if (WARN(hwirq >= domain->hwirq_max, in irq_domain_associate_locked()
689 "error: hwirq 0x%x is too large for %s\n", (int)hwirq, domain->name)) in irq_domain_associate_locked()
690 return -EINVAL; in irq_domain_associate_locked()
692 return -EINVAL; in irq_domain_associate_locked()
693 if (WARN(irq_data->domain, "error: virq%i is already associated", virq)) in irq_domain_associate_locked()
694 return -EINVAL; in irq_domain_associate_locked()
696 irq_data->hwirq = hwirq; in irq_domain_associate_locked()
697 irq_data->domain = domain; in irq_domain_associate_locked()
698 if (domain->ops->map) { in irq_domain_associate_locked()
699 ret = domain->ops->map(domain, virq, hwirq); in irq_domain_associate_locked()
702 * If map() returns -EPERM, this interrupt is protected in irq_domain_associate_locked()
706 if (ret != -EPERM) { in irq_domain_associate_locked()
707 pr_info("%s didn't like hwirq-0x%lx to VIRQ%i mapping (rc=%d)\n", in irq_domain_associate_locked()
708 domain->name, hwirq, virq, ret); in irq_domain_associate_locked()
710 irq_data->domain = NULL; in irq_domain_associate_locked()
711 irq_data->hwirq = 0; in irq_domain_associate_locked()
716 domain->mapcount++; in irq_domain_associate_locked()
729 mutex_lock(&domain->root->mutex); in irq_domain_associate()
731 mutex_unlock(&domain->root->mutex); in irq_domain_associate()
754 * irq_create_direct_mapping() - Allocate an irq for direct mapping
758 * interrupt numbers they generate. In such a case it's simplest to use
759 * the linux irq as the hardware interrupt number. It still uses the linear
777 if (virq >= domain->hwirq_max) { in irq_create_direct_mapping()
779 domain->hwirq_max); in irq_create_direct_mapping()
797 const struct irq_affinity_desc *affinity) in irq_create_mapping_affinity_locked() argument
804 /* Allocate a virtual interrupt number */ in irq_create_mapping_affinity_locked()
805 virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), in irq_create_mapping_affinity_locked()
806 affinity); in irq_create_mapping_affinity_locked()
808 pr_debug("-> virq allocation failed\n"); in irq_create_mapping_affinity_locked()
824 * irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space
825 * @domain: domain owning this hardware interrupt or NULL for default domain
827 * @affinity: irq affinity
829 * Only one mapping per hardware interrupt is permitted. Returns a linux
836 const struct irq_affinity_desc *affinity) in irq_create_mapping_affinity() argument
848 mutex_lock(&domain->root->mutex); in irq_create_mapping_affinity()
857 virq = irq_create_mapping_affinity_locked(domain, hwirq, affinity); in irq_create_mapping_affinity()
859 mutex_unlock(&domain->root->mutex); in irq_create_mapping_affinity()
870 if (d->ops->translate) in irq_domain_translate()
871 return d->ops->translate(d, fwspec, hwirq, type); in irq_domain_translate()
873 if (d->ops->xlate) in irq_domain_translate()
874 return d->ops->xlate(d, to_of_node(fwspec->fwnode), in irq_domain_translate()
875 fwspec->param, fwspec->param_count, in irq_domain_translate()
878 /* If domain has no translation, then we assume interrupt line */ in irq_domain_translate()
879 *hwirq = fwspec->param[0]; in irq_domain_translate()
888 fwspec->fwnode = of_node_to_fwnode(np); in of_phandle_args_to_fwspec()
889 fwspec->param_count = count; in of_phandle_args_to_fwspec()
892 fwspec->param[i] = args[i]; in of_phandle_args_to_fwspec()
904 if (fwspec->fwnode) { in irq_create_fwspec_mapping()
914 of_node_full_name(to_of_node(fwspec->fwnode))); in irq_create_fwspec_mapping()
928 mutex_lock(&domain->root->mutex); in irq_create_fwspec_mapping()
931 * If we've already configured this interrupt, in irq_create_fwspec_mapping()
939 * interrupt number. in irq_create_fwspec_mapping()
946 * it now and return the interrupt number. in irq_create_fwspec_mapping()
959 pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n", in irq_create_fwspec_mapping()
960 hwirq, of_node_full_name(to_of_node(fwspec->fwnode))); in irq_create_fwspec_mapping()
967 mutex_unlock(&domain->root->mutex); in irq_create_fwspec_mapping()
969 mutex_lock(&domain->root->mutex); in irq_create_fwspec_mapping()
971 virq = irq_domain_alloc_irqs_locked(domain, -1, 1, NUMA_NO_NODE, in irq_create_fwspec_mapping()
993 mutex_unlock(&domain->root->mutex); in irq_create_fwspec_mapping()
1003 of_phandle_args_to_fwspec(irq_data->np, irq_data->args, in irq_create_of_mapping()
1004 irq_data->args_count, &fwspec); in irq_create_of_mapping()
1011 * irq_dispose_mapping() - Unmap an interrupt
1012 * @virq: linux irq number of the interrupt to unmap
1023 domain = irq_data->domain; in irq_dispose_mapping()
1037 * __irq_resolve_mapping() - Find a linux irq from a hw irq number.
1038 * @domain: domain owning this hardware interrupt
1042 * Returns the interrupt descriptor.
1058 if (hwirq < domain->hwirq_max) { in __irq_resolve_mapping()
1060 if (data && data->hwirq == hwirq) in __irq_resolve_mapping()
1071 if (hwirq < domain->revmap_size) in __irq_resolve_mapping()
1072 data = rcu_dereference(domain->revmap[hwirq]); in __irq_resolve_mapping()
1074 data = radix_tree_lookup(&domain->revmap_tree, hwirq); in __irq_resolve_mapping()
1079 *irq = data->irq; in __irq_resolve_mapping()
1088 * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings
1089 * @d: Interrupt domain involved in the translation
1090 * @ctrlr: The device tree node for the device whose interrupt is translated
1091 * @intspec: The interrupt specifier data from the device tree
1093 * @out_hwirq: Pointer to storage for the hardware interrupt number
1094 * @out_type: Pointer to storage for the interrupt type
1104 return -EINVAL; in irq_domain_xlate_onecell()
1112 * irq_domain_xlate_twocell() - Generic xlate for direct two cell bindings
1113 * @d: Interrupt domain involved in the translation
1114 * @ctrlr: The device tree node for the device whose interrupt is translated
1115 * @intspec: The interrupt specifier data from the device tree
1117 * @out_hwirq: Pointer to storage for the hardware interrupt number
1118 * @out_type: Pointer to storage for the interrupt type
1136 * irq_domain_xlate_onetwocell() - Generic xlate for one or two cell bindings
1137 * @d: Interrupt domain involved in the translation
1138 * @ctrlr: The device tree node for the device whose interrupt is translated
1139 * @intspec: The interrupt specifier data from the device tree
1141 * @out_hwirq: Pointer to storage for the hardware interrupt number
1142 * @out_type: Pointer to storage for the interrupt type
1148 * Note: don't use this function unless your interrupt controller explicitly
1158 return -EINVAL; in irq_domain_xlate_onetwocell()
1174 * irq_domain_translate_onecell() - Generic translate for direct one cell
1176 * @d: Interrupt domain involved in the translation
1177 * @fwspec: The firmware interrupt specifier to translate
1178 * @out_hwirq: Pointer to storage for the hardware interrupt number
1179 * @out_type: Pointer to storage for the interrupt type
1186 if (WARN_ON(fwspec->param_count < 1)) in irq_domain_translate_onecell()
1187 return -EINVAL; in irq_domain_translate_onecell()
1188 *out_hwirq = fwspec->param[0]; in irq_domain_translate_onecell()
1195 * irq_domain_translate_twocell() - Generic translate for direct two cell
1197 * @d: Interrupt domain involved in the translation
1198 * @fwspec: The firmware interrupt specifier to translate
1199 * @out_hwirq: Pointer to storage for the hardware interrupt number
1200 * @out_type: Pointer to storage for the interrupt type
1211 if (WARN_ON(fwspec->param_count < 2)) in irq_domain_translate_twocell()
1212 return -EINVAL; in irq_domain_translate_twocell()
1213 *out_hwirq = fwspec->param[0]; in irq_domain_translate_twocell()
1214 *out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; in irq_domain_translate_twocell()
1220 int node, const struct irq_affinity_desc *affinity) in irq_domain_alloc_descs() argument
1226 affinity); in irq_domain_alloc_descs()
1231 virq = __irq_alloc_descs(-1, hint, cnt, node, THIS_MODULE, in irq_domain_alloc_descs()
1232 affinity); in irq_domain_alloc_descs()
1234 virq = __irq_alloc_descs(-1, 1, cnt, node, THIS_MODULE, in irq_domain_alloc_descs()
1235 affinity); in irq_domain_alloc_descs()
1243 * irq_domain_reset_irq_data - Clear hwirq, chip and chip_data in @irq_data
1248 irq_data->hwirq = 0; in irq_domain_reset_irq_data()
1249 irq_data->chip = &no_irq_chip; in irq_domain_reset_irq_data()
1250 irq_data->chip_data = NULL; in irq_domain_reset_irq_data()
1256 * irq_domain_create_hierarchy - Add a irqdomain into the hierarchy
1260 * @fwnode: Optional fwnode of the interrupt controller
1261 * @ops: Pointer to the interrupt domain callbacks
1300 for (data = irq_get_irq_data(virq); data; data = data->parent_data) { in irq_domain_insert_irq()
1301 struct irq_domain *domain = data->domain; in irq_domain_insert_irq()
1303 domain->mapcount++; in irq_domain_insert_irq()
1304 irq_domain_set_mapping(domain, data->hwirq, data); in irq_domain_insert_irq()
1319 for (data = irq_get_irq_data(virq); data; data = data->parent_data) { in irq_domain_remove_irq()
1320 struct irq_domain *domain = data->domain; in irq_domain_remove_irq()
1321 irq_hw_number_t hwirq = data->hwirq; in irq_domain_remove_irq()
1323 domain->mapcount--; in irq_domain_remove_irq()
1336 child->parent_data = irq_data; in irq_domain_insert_irq_data()
1337 irq_data->irq = child->irq; in irq_domain_insert_irq_data()
1338 irq_data->common = child->common; in irq_domain_insert_irq_data()
1339 irq_data->domain = domain; in irq_domain_insert_irq_data()
1351 irq_data = irq_data->parent_data; in __irq_domain_free_hierarchy()
1363 tmp = irq_data->parent_data; in irq_domain_free_irq_data()
1364 irq_data->parent_data = NULL; in irq_domain_free_irq_data()
1365 irq_data->domain = NULL; in irq_domain_free_irq_data()
1372 * irq_domain_disconnect_hierarchy - Mark the first unused level of a hierarchy
1377 * Returns -EINVAL if @virq doesn't have a valid irq_data pointing
1381 * have any real meaning for this interrupt, and that the driver marks
1391 return -EINVAL; in irq_domain_disconnect_hierarchy()
1393 irqd->chip = ERR_PTR(-ENOTCONN); in irq_domain_disconnect_hierarchy()
1406 if (IS_ERR_OR_NULL(irq_data->chip)) in irq_domain_trim_hierarchy()
1407 return -EINVAL; in irq_domain_trim_hierarchy()
1413 for (irqd = irq_data->parent_data; irqd; irq_data = irqd, irqd = irqd->parent_data) { in irq_domain_trim_hierarchy()
1415 if (irqd->chip && tail) in irq_domain_trim_hierarchy()
1416 return -EINVAL; in irq_domain_trim_hierarchy()
1419 if (!irqd->chip && !tail) in irq_domain_trim_hierarchy()
1420 return -EINVAL; in irq_domain_trim_hierarchy()
1422 if (IS_ERR(irqd->chip)) { in irq_domain_trim_hierarchy()
1423 /* Only -ENOTCONN is a valid trim marker */ in irq_domain_trim_hierarchy()
1424 if (PTR_ERR(irqd->chip) != -ENOTCONN) in irq_domain_trim_hierarchy()
1425 return -EINVAL; in irq_domain_trim_hierarchy()
1436 virq, tail->parent_data->domain->name); in irq_domain_trim_hierarchy()
1440 tail = tail->parent_data; in irq_domain_trim_hierarchy()
1441 irqd->parent_data = NULL; in irq_domain_trim_hierarchy()
1457 irq_data->domain = domain; in irq_domain_alloc_irq_data()
1459 for (parent = domain->parent; parent; parent = parent->parent) { in irq_domain_alloc_irq_data()
1463 return -ENOMEM; in irq_domain_alloc_irq_data()
1472 * irq_domain_get_irq_data - Get irq_data associated with @virq and @domain
1482 irq_data = irq_data->parent_data) in irq_domain_get_irq_data()
1483 if (irq_data->domain == domain) in irq_domain_get_irq_data()
1491 * irq_domain_set_hwirq_and_chip - Set hwirq and irqchip of @virq at @domain
1492 * @domain: Interrupt domain to match
1495 * @chip: The associated interrupt chip
1506 return -ENOENT; in irq_domain_set_hwirq_and_chip()
1508 irq_data->hwirq = hwirq; in irq_domain_set_hwirq_and_chip()
1509 irq_data->chip = (struct irq_chip *)(chip ? chip : &no_irq_chip); in irq_domain_set_hwirq_and_chip()
1510 irq_data->chip_data = chip_data; in irq_domain_set_hwirq_and_chip()
1517 * irq_domain_set_info - Set the complete data for a @virq in @domain
1518 * @domain: Interrupt domain to match
1520 * @hwirq: The hardware interrupt number
1521 * @chip: The associated interrupt chip
1522 * @chip_data: The associated interrupt chip data
1523 * @handler: The interrupt flow handler
1524 * @handler_data: The interrupt flow handler data
1525 * @handler_name: The interrupt handler name
1539 * irq_domain_free_irqs_common - Clear irq_data and free the parent
1540 * @domain: Interrupt domain to match
1560 * irq_domain_free_irqs_top - Clear handler and handler data, clear irqdata and free parent
1561 * @domain: Interrupt domain to match
1583 if (!domain->ops->free) in irq_domain_free_irqs_hierarchy()
1588 domain->ops->free(domain, irq_base + i, 1); in irq_domain_free_irqs_hierarchy()
1596 if (!domain->ops->alloc) { in irq_domain_alloc_irqs_hierarchy()
1597 pr_debug("domain->ops->alloc() is NULL\n"); in irq_domain_alloc_irqs_hierarchy()
1598 return -ENOSYS; in irq_domain_alloc_irqs_hierarchy()
1601 return domain->ops->alloc(domain, irq_base, nr_irqs, arg); in irq_domain_alloc_irqs_hierarchy()
1606 bool realloc, const struct irq_affinity_desc *affinity) in irq_domain_alloc_irqs_locked() argument
1614 affinity); in irq_domain_alloc_irqs_locked()
1624 ret = -ENOMEM; in irq_domain_alloc_irqs_locked()
1651 * __irq_domain_alloc_irqs - Allocate IRQs from domain
1658 * @affinity: Optional irq affinity mask for multiqueue devices
1674 bool realloc, const struct irq_affinity_desc *affinity) in __irq_domain_alloc_irqs() argument
1681 return -EINVAL; in __irq_domain_alloc_irqs()
1684 mutex_lock(&domain->root->mutex); in __irq_domain_alloc_irqs()
1686 realloc, affinity); in __irq_domain_alloc_irqs()
1687 mutex_unlock(&domain->root->mutex); in __irq_domain_alloc_irqs()
1698 lockdep_assert_held(&d->domain->root->mutex); in irq_domain_fix_revmap()
1700 if (irq_domain_is_nomap(d->domain)) in irq_domain_fix_revmap()
1704 if (d->hwirq < d->domain->revmap_size) { in irq_domain_fix_revmap()
1706 rcu_assign_pointer(d->domain->revmap[d->hwirq], d); in irq_domain_fix_revmap()
1708 slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq); in irq_domain_fix_revmap()
1710 radix_tree_replace_slot(&d->domain->revmap_tree, slot, d); in irq_domain_fix_revmap()
1715 * irq_domain_push_irq() - Push a domain in to the top of a hierarchy.
1735 * races between interrupt handling and maintaining the in irq_domain_push_irq()
1738 * calls to struct irq_domain_ops->alloc(), which could lead in irq_domain_push_irq()
1743 return -EINVAL; in irq_domain_push_irq()
1744 if (WARN_ON(desc->action)) in irq_domain_push_irq()
1745 return -EBUSY; in irq_domain_push_irq()
1748 return -EINVAL; in irq_domain_push_irq()
1751 return -EINVAL; in irq_domain_push_irq()
1754 return -EINVAL; in irq_domain_push_irq()
1756 if (domain->parent != irq_data->domain) in irq_domain_push_irq()
1757 return -EINVAL; in irq_domain_push_irq()
1762 return -ENOMEM; in irq_domain_push_irq()
1764 mutex_lock(&domain->root->mutex); in irq_domain_push_irq()
1773 irq_data->parent_data = parent_irq_data; in irq_domain_push_irq()
1774 irq_data->domain = domain; in irq_domain_push_irq()
1775 irq_data->mask = 0; in irq_domain_push_irq()
1776 irq_data->hwirq = 0; in irq_domain_push_irq()
1777 irq_data->chip = NULL; in irq_domain_push_irq()
1778 irq_data->chip_data = NULL; in irq_domain_push_irq()
1790 irq_domain_set_mapping(domain, irq_data->hwirq, irq_data); in irq_domain_push_irq()
1792 mutex_unlock(&domain->root->mutex); in irq_domain_push_irq()
1799 * irq_domain_pop_irq() - Remove a domain from the top of a hierarchy.
1816 * between interrupt handling and maintaining the hierarchy. in irq_domain_pop_irq()
1819 * struct irq_domain_ops->free(), which could lead to in irq_domain_pop_irq()
1824 return -EINVAL; in irq_domain_pop_irq()
1825 if (WARN_ON(desc->action)) in irq_domain_pop_irq()
1826 return -EBUSY; in irq_domain_pop_irq()
1829 return -EINVAL; in irq_domain_pop_irq()
1832 return -EINVAL; in irq_domain_pop_irq()
1838 return -EINVAL; in irq_domain_pop_irq()
1840 if (WARN_ON(irq_data->domain != domain)) in irq_domain_pop_irq()
1841 return -EINVAL; in irq_domain_pop_irq()
1843 parent_irq_data = irq_data->parent_data; in irq_domain_pop_irq()
1845 return -EINVAL; in irq_domain_pop_irq()
1847 mutex_lock(&domain->root->mutex); in irq_domain_pop_irq()
1849 irq_data->parent_data = NULL; in irq_domain_pop_irq()
1851 irq_domain_clear_mapping(domain, irq_data->hwirq); in irq_domain_pop_irq()
1859 mutex_unlock(&domain->root->mutex); in irq_domain_pop_irq()
1868 * irq_domain_free_irqs - Free IRQ number and associated data structures
1878 if (WARN(!data || !data->domain || !data->domain->ops->free, in irq_domain_free_irqs()
1882 domain = data->domain; in irq_domain_free_irqs()
1884 mutex_lock(&domain->root->mutex); in irq_domain_free_irqs()
1888 mutex_unlock(&domain->root->mutex); in irq_domain_free_irqs()
1903 * irq_domain_alloc_irqs_parent - Allocate interrupts from parent domain
1913 if (!domain->parent) in irq_domain_alloc_irqs_parent()
1914 return -ENOSYS; in irq_domain_alloc_irqs_parent()
1916 return irq_domain_alloc_irqs_hierarchy(domain->parent, irq_base, in irq_domain_alloc_irqs_parent()
1922 * irq_domain_free_irqs_parent - Free interrupts from parent domain
1930 if (!domain->parent) in irq_domain_free_irqs_parent()
1933 irq_domain_free_irqs_hierarchy(domain->parent, irq_base, nr_irqs); in irq_domain_free_irqs_parent()
1939 if (irq_data && irq_data->domain) { in __irq_domain_deactivate_irq()
1940 struct irq_domain *domain = irq_data->domain; in __irq_domain_deactivate_irq()
1942 if (domain->ops->deactivate) in __irq_domain_deactivate_irq()
1943 domain->ops->deactivate(domain, irq_data); in __irq_domain_deactivate_irq()
1944 if (irq_data->parent_data) in __irq_domain_deactivate_irq()
1945 __irq_domain_deactivate_irq(irq_data->parent_data); in __irq_domain_deactivate_irq()
1953 if (irqd && irqd->domain) { in __irq_domain_activate_irq()
1954 struct irq_domain *domain = irqd->domain; in __irq_domain_activate_irq()
1956 if (irqd->parent_data) in __irq_domain_activate_irq()
1957 ret = __irq_domain_activate_irq(irqd->parent_data, in __irq_domain_activate_irq()
1959 if (!ret && domain->ops->activate) { in __irq_domain_activate_irq()
1960 ret = domain->ops->activate(domain, irqd, reserve); in __irq_domain_activate_irq()
1962 if (ret && irqd->parent_data) in __irq_domain_activate_irq()
1963 __irq_domain_deactivate_irq(irqd->parent_data); in __irq_domain_activate_irq()
1970 * irq_domain_activate_irq - Call domain_ops->activate recursively to activate
1971 * interrupt
1972 * @irq_data: Outermost irq_data associated with interrupt
1973 * @reserve: If set only reserve an interrupt vector instead of assigning one
1975 * This is the second step to call domain_ops->activate to program interrupt
1976 * controllers, so the interrupt could actually get delivered.
1990 * irq_domain_deactivate_irq - Call domain_ops->deactivate recursively to
1991 * deactivate interrupt
1992 * @irq_data: outermost irq_data associated with interrupt
1994 * It calls domain_ops->deactivate to program interrupt controllers to disable
1995 * interrupt delivery.
2008 if (domain->ops->alloc) in irq_domain_check_hierarchy()
2009 domain->flags |= IRQ_DOMAIN_FLAG_HIERARCHY; in irq_domain_check_hierarchy()
2013 * irq_domain_get_irq_data - Get irq_data associated with @virq and @domain
2022 return (irq_data && irq_data->domain == domain) ? irq_data : NULL; in irq_domain_get_irq_data()
2027 * irq_domain_set_info - Set the complete data for a @virq in @domain
2028 * @domain: Interrupt domain to match
2030 * @hwirq: The hardware interrupt number
2031 * @chip: The associated interrupt chip
2032 * @chip_data: The associated interrupt chip data
2033 * @handler: The interrupt flow handler
2034 * @handler_data: The interrupt flow handler data
2035 * @handler_name: The interrupt handler name
2049 bool realloc, const struct irq_affinity_desc *affinity) in irq_domain_alloc_irqs_locked() argument
2051 return -EINVAL; in irq_domain_alloc_irqs_locked()
2079 seq_printf(m, "%*sname: %s\n", ind, "", d->name); in irq_domain_debug_show_one()
2080 seq_printf(m, "%*ssize: %u\n", ind + 1, "", d->revmap_size); in irq_domain_debug_show_one()
2081 seq_printf(m, "%*smapped: %u\n", ind + 1, "", d->mapcount); in irq_domain_debug_show_one()
2082 seq_printf(m, "%*sflags: 0x%08x\n", ind +1 , "", d->flags); in irq_domain_debug_show_one()
2083 irq_debug_show_bits(m, ind, d->flags, irqdomain_flags, ARRAY_SIZE(irqdomain_flags)); in irq_domain_debug_show_one()
2084 if (d->ops && d->ops->debug_show) in irq_domain_debug_show_one()
2085 d->ops->debug_show(m, d, NULL, ind + 1); in irq_domain_debug_show_one()
2087 if (!d->parent) in irq_domain_debug_show_one()
2089 seq_printf(m, "%*sparent: %s\n", ind + 1, "", d->parent->name); in irq_domain_debug_show_one()
2090 irq_domain_debug_show_one(m, d->parent, ind + 4); in irq_domain_debug_show_one()
2096 struct irq_domain *d = m->private; in irq_domain_debug_show()
2111 if (!d->name || !domain_dir) in debugfs_add_domain_dir()
2113 debugfs_create_file(d->name, 0444, domain_dir, d, in debugfs_add_domain_dir()
2119 debugfs_lookup_and_remove(d->name, domain_dir); in debugfs_remove_domain_dir()