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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'irq-domain-24-08-09' into irq/core

Merge the irqdomain changes which are required for regmap to apply
depending patches and therefore tagged.

+121 -85
+8
include/linux/irqdomain.h
··· 291 291 * @hwirq_max: Maximum number of interrupts supported by controller 292 292 * @direct_max: Maximum value of direct maps; 293 293 * Use ~0 for no limit; 0 for no direct mapping 294 + * @hwirq_base: The first hardware interrupt number (legacy domains only) 295 + * @virq_base: The first Linux interrupt number for legacy domains to 296 + * immediately associate the interrupts after domain creation 294 297 * @bus_token: Domain bus token 298 + * @name_suffix: Optional name suffix to avoid collisions when multiple 299 + * domains are added using same fwnode 295 300 * @ops: Domain operation callbacks 296 301 * @host_data: Controller private data pointer 297 302 * @dgc_info: Geneneric chip information structure pointer used to ··· 312 307 unsigned int size; 313 308 irq_hw_number_t hwirq_max; 314 309 int direct_max; 310 + unsigned int hwirq_base; 311 + unsigned int virq_base; 315 312 enum irq_domain_bus_token bus_token; 313 + const char *name_suffix; 316 314 const struct irq_domain_ops *ops; 317 315 void *host_data; 318 316 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+113 -85
kernel/irq/irqdomain.c
··· 128 128 } 129 129 EXPORT_SYMBOL_GPL(irq_domain_free_fwnode); 130 130 131 - static int irq_domain_set_name(struct irq_domain *domain, 132 - const struct fwnode_handle *fwnode, 133 - enum irq_domain_bus_token bus_token) 131 + static int alloc_name(struct irq_domain *domain, char *base, enum irq_domain_bus_token bus_token) 132 + { 133 + domain->name = bus_token ? kasprintf(GFP_KERNEL, "%s-%d", base, bus_token) : 134 + kasprintf(GFP_KERNEL, "%s", base); 135 + if (!domain->name) 136 + return -ENOMEM; 137 + 138 + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; 139 + return 0; 140 + } 141 + 142 + static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_handle *fwnode, 143 + enum irq_domain_bus_token bus_token, const char *suffix) 144 + { 145 + const char *sep = suffix ? "-" : ""; 146 + const char *suf = suffix ? : ""; 147 + char *name; 148 + 149 + name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%s%s%d", fwnode, suf, sep, bus_token) : 150 + kasprintf(GFP_KERNEL, "%pfw-%s", fwnode, suf); 151 + if (!name) 152 + return -ENOMEM; 153 + 154 + /* 155 + * fwnode paths contain '/', which debugfs is legitimately unhappy 156 + * about. Replace them with ':', which does the trick and is not as 157 + * offensive as '\'... 158 + */ 159 + domain->name = strreplace(name, '/', ':'); 160 + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; 161 + return 0; 162 + } 163 + 164 + static int alloc_unknown_name(struct irq_domain *domain, enum irq_domain_bus_token bus_token) 134 165 { 135 166 static atomic_t unknown_domains; 136 - struct irqchip_fwid *fwid; 167 + int id = atomic_inc_return(&unknown_domains); 168 + 169 + domain->name = bus_token ? kasprintf(GFP_KERNEL, "unknown-%d-%d", id, bus_token) : 170 + kasprintf(GFP_KERNEL, "unknown-%d", id); 171 + 172 + if (!domain->name) 173 + return -ENOMEM; 174 + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; 175 + return 0; 176 + } 177 + 178 + static int irq_domain_set_name(struct irq_domain *domain, const struct irq_domain_info *info) 179 + { 180 + enum irq_domain_bus_token bus_token = info->bus_token; 181 + const struct fwnode_handle *fwnode = info->fwnode; 137 182 138 183 if (is_fwnode_irqchip(fwnode)) { 139 - fwid = container_of(fwnode, struct irqchip_fwid, fwnode); 184 + struct irqchip_fwid *fwid = container_of(fwnode, struct irqchip_fwid, fwnode); 185 + 186 + /* 187 + * The name_suffix is only intended to be used to avoid a name 188 + * collision when multiple domains are created for a single 189 + * device and the name is picked using a real device node. 190 + * (Typical use-case is regmap-IRQ controllers for devices 191 + * providing more than one physical IRQ.) There should be no 192 + * need to use name_suffix with irqchip-fwnode. 193 + */ 194 + if (info->name_suffix) 195 + return -EINVAL; 140 196 141 197 switch (fwid->type) { 142 198 case IRQCHIP_FWNODE_NAMED: 143 199 case IRQCHIP_FWNODE_NAMED_ID: 144 - domain->name = bus_token ? 145 - kasprintf(GFP_KERNEL, "%s-%d", 146 - fwid->name, bus_token) : 147 - kstrdup(fwid->name, GFP_KERNEL); 148 - if (!domain->name) 149 - return -ENOMEM; 150 - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; 151 - break; 200 + return alloc_name(domain, fwid->name, bus_token); 152 201 default: 153 202 domain->name = fwid->name; 154 - if (bus_token) { 155 - domain->name = kasprintf(GFP_KERNEL, "%s-%d", 156 - fwid->name, bus_token); 157 - if (!domain->name) 158 - return -ENOMEM; 159 - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; 160 - } 161 - break; 203 + if (bus_token) 204 + return alloc_name(domain, fwid->name, bus_token); 162 205 } 163 - } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || 164 - is_software_node(fwnode)) { 165 - char *name; 166 206 167 - /* 168 - * fwnode paths contain '/', which debugfs is legitimately 169 - * unhappy about. Replace them with ':', which does 170 - * the trick and is not as offensive as '\'... 171 - */ 172 - name = bus_token ? 173 - kasprintf(GFP_KERNEL, "%pfw-%d", fwnode, bus_token) : 174 - kasprintf(GFP_KERNEL, "%pfw", fwnode); 175 - if (!name) 176 - return -ENOMEM; 177 - 178 - domain->name = strreplace(name, '/', ':'); 179 - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; 207 + } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || is_software_node(fwnode)) { 208 + return alloc_fwnode_name(domain, fwnode, bus_token, info->name_suffix); 180 209 } 181 210 182 - if (!domain->name) { 183 - if (fwnode) 184 - pr_err("Invalid fwnode type for irqdomain\n"); 185 - domain->name = bus_token ? 186 - kasprintf(GFP_KERNEL, "unknown-%d-%d", 187 - atomic_inc_return(&unknown_domains), 188 - bus_token) : 189 - kasprintf(GFP_KERNEL, "unknown-%d", 190 - atomic_inc_return(&unknown_domains)); 191 - if (!domain->name) 192 - return -ENOMEM; 193 - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; 194 - } 211 + if (domain->name) 212 + return 0; 195 213 196 - return 0; 214 + if (fwnode) 215 + pr_err("Invalid fwnode type for irqdomain\n"); 216 + return alloc_unknown_name(domain, bus_token); 197 217 } 198 218 199 219 static struct irq_domain *__irq_domain_create(const struct irq_domain_info *info) ··· 231 211 if (!domain) 232 212 return ERR_PTR(-ENOMEM); 233 213 234 - err = irq_domain_set_name(domain, info->fwnode, info->bus_token); 214 + err = irq_domain_set_name(domain, info); 235 215 if (err) { 236 216 kfree(domain); 237 217 return ERR_PTR(err); ··· 287 267 kfree(domain); 288 268 } 289 269 290 - /** 291 - * irq_domain_instantiate() - Instantiate a new irq domain data structure 292 - * @info: Domain information pointer pointing to the information for this domain 293 - * 294 - * Return: A pointer to the instantiated irq domain or an ERR_PTR value. 295 - */ 296 - struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) 270 + static void irq_domain_instantiate_descs(const struct irq_domain_info *info) 271 + { 272 + if (!IS_ENABLED(CONFIG_SPARSE_IRQ)) 273 + return; 274 + 275 + if (irq_alloc_descs(info->virq_base, info->virq_base, info->size, 276 + of_node_to_nid(to_of_node(info->fwnode))) < 0) { 277 + pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", 278 + info->virq_base); 279 + } 280 + } 281 + 282 + static struct irq_domain *__irq_domain_instantiate(const struct irq_domain_info *info, 283 + bool cond_alloc_descs) 297 284 { 298 285 struct irq_domain *domain; 299 286 int err; ··· 333 306 334 307 __irq_domain_publish(domain); 335 308 309 + if (cond_alloc_descs && info->virq_base > 0) 310 + irq_domain_instantiate_descs(info); 311 + 312 + /* Legacy interrupt domains have a fixed Linux interrupt number */ 313 + if (info->virq_base > 0) { 314 + irq_domain_associate_many(domain, info->virq_base, info->hwirq_base, 315 + info->size - info->hwirq_base); 316 + } 317 + 336 318 return domain; 337 319 338 320 err_domain_gc_remove: ··· 350 314 err_domain_free: 351 315 irq_domain_free(domain); 352 316 return ERR_PTR(err); 317 + } 318 + 319 + /** 320 + * irq_domain_instantiate() - Instantiate a new irq domain data structure 321 + * @info: Domain information pointer pointing to the information for this domain 322 + * 323 + * Return: A pointer to the instantiated irq domain or an ERR_PTR value. 324 + */ 325 + struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) 326 + { 327 + return __irq_domain_instantiate(info, false); 353 328 } 354 329 EXPORT_SYMBOL_GPL(irq_domain_instantiate); 355 330 ··· 460 413 .fwnode = fwnode, 461 414 .size = size, 462 415 .hwirq_max = size, 416 + .virq_base = first_irq, 463 417 .ops = ops, 464 418 .host_data = host_data, 465 419 }; 466 - struct irq_domain *domain; 420 + struct irq_domain *domain = __irq_domain_instantiate(&info, true); 467 421 468 - domain = irq_domain_instantiate(&info); 469 - if (IS_ERR(domain)) 470 - return NULL; 471 - 472 - if (first_irq > 0) { 473 - if (IS_ENABLED(CONFIG_SPARSE_IRQ)) { 474 - /* attempt to allocated irq_descs */ 475 - int rc = irq_alloc_descs(first_irq, first_irq, size, 476 - of_node_to_nid(to_of_node(fwnode))); 477 - if (rc < 0) 478 - pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", 479 - first_irq); 480 - } 481 - irq_domain_associate_many(domain, first_irq, 0, size); 482 - } 483 - 484 - return domain; 422 + return IS_ERR(domain) ? NULL : domain; 485 423 } 486 424 EXPORT_SYMBOL_GPL(irq_domain_create_simple); 487 425 ··· 508 476 .fwnode = fwnode, 509 477 .size = first_hwirq + size, 510 478 .hwirq_max = first_hwirq + size, 479 + .hwirq_base = first_hwirq, 480 + .virq_base = first_irq, 511 481 .ops = ops, 512 482 .host_data = host_data, 513 483 }; 514 - struct irq_domain *domain; 484 + struct irq_domain *domain = irq_domain_instantiate(&info); 515 485 516 - domain = irq_domain_instantiate(&info); 517 - if (IS_ERR(domain)) 518 - return NULL; 519 - 520 - irq_domain_associate_many(domain, first_irq, first_hwirq, size); 521 - 522 - return domain; 486 + return IS_ERR(domain) ? NULL : domain; 523 487 } 524 488 EXPORT_SYMBOL_GPL(irq_domain_create_legacy); 525 489