@@ -128,72 +128,92 @@ void irq_domain_free_fwnode(struct fwnode_handle *fwnode)
128128}
129129EXPORT_SYMBOL_GPL (irq_domain_free_fwnode );
130130
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 )
134165{
135166 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 ;
137182
138183 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 ;
140196
141197 switch (fwid -> type ) {
142198 case IRQCHIP_FWNODE_NAMED :
143199 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 );
152201 default :
153202 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 );
162205 }
163- } else if (is_of_node (fwnode ) || is_acpi_device_node (fwnode ) ||
164- is_software_node (fwnode )) {
165- char * name ;
166-
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 ;
177206
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 ) ;
180209 }
181210
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 ;
195213
196- return 0 ;
214+ if (fwnode )
215+ pr_err ("Invalid fwnode type for irqdomain\n" );
216+ return alloc_unknown_name (domain , bus_token );
197217}
198218
199219static struct irq_domain * __irq_domain_create (const struct irq_domain_info * info )
@@ -211,7 +231,7 @@ static struct irq_domain *__irq_domain_create(const struct irq_domain_info *info
211231 if (!domain )
212232 return ERR_PTR (- ENOMEM );
213233
214- err = irq_domain_set_name (domain , info -> fwnode , info -> bus_token );
234+ err = irq_domain_set_name (domain , info );
215235 if (err ) {
216236 kfree (domain );
217237 return ERR_PTR (err );
@@ -267,13 +287,20 @@ static void irq_domain_free(struct irq_domain *domain)
267287 kfree (domain );
268288}
269289
270- /**
271- * irq_domain_instantiate() - Instantiate a new irq domain data structure
272- * @info: Domain information pointer pointing to the information for this domain
273- *
274- * Return: A pointer to the instantiated irq domain or an ERR_PTR value.
275- */
276- struct irq_domain * irq_domain_instantiate (const struct irq_domain_info * info )
290+ static void irq_domain_instantiate_descs (const struct irq_domain_info * info )
291+ {
292+ if (!IS_ENABLED (CONFIG_SPARSE_IRQ ))
293+ return ;
294+
295+ if (irq_alloc_descs (info -> virq_base , info -> virq_base , info -> size ,
296+ of_node_to_nid (to_of_node (info -> fwnode ))) < 0 ) {
297+ pr_info ("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n" ,
298+ info -> virq_base );
299+ }
300+ }
301+
302+ static struct irq_domain * __irq_domain_instantiate (const struct irq_domain_info * info ,
303+ bool cond_alloc_descs )
277304{
278305 struct irq_domain * domain ;
279306 int err ;
@@ -306,6 +333,15 @@ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)
306333
307334 __irq_domain_publish (domain );
308335
336+ if (cond_alloc_descs && info -> virq_base > 0 )
337+ irq_domain_instantiate_descs (info );
338+
339+ /* Legacy interrupt domains have a fixed Linux interrupt number */
340+ if (info -> virq_base > 0 ) {
341+ irq_domain_associate_many (domain , info -> virq_base , info -> hwirq_base ,
342+ info -> size - info -> hwirq_base );
343+ }
344+
309345 return domain ;
310346
311347err_domain_gc_remove :
@@ -315,6 +351,17 @@ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)
315351 irq_domain_free (domain );
316352 return ERR_PTR (err );
317353}
354+
355+ /**
356+ * irq_domain_instantiate() - Instantiate a new irq domain data structure
357+ * @info: Domain information pointer pointing to the information for this domain
358+ *
359+ * Return: A pointer to the instantiated irq domain or an ERR_PTR value.
360+ */
361+ struct irq_domain * irq_domain_instantiate (const struct irq_domain_info * info )
362+ {
363+ return __irq_domain_instantiate (info , false);
364+ }
318365EXPORT_SYMBOL_GPL (irq_domain_instantiate );
319366
320367/**
@@ -413,28 +460,13 @@ struct irq_domain *irq_domain_create_simple(struct fwnode_handle *fwnode,
413460 .fwnode = fwnode ,
414461 .size = size ,
415462 .hwirq_max = size ,
463+ .virq_base = first_irq ,
416464 .ops = ops ,
417465 .host_data = host_data ,
418466 };
419- struct irq_domain * domain ;
420-
421- domain = irq_domain_instantiate (& info );
422- if (IS_ERR (domain ))
423- return NULL ;
467+ struct irq_domain * domain = __irq_domain_instantiate (& info , true);
424468
425- if (first_irq > 0 ) {
426- if (IS_ENABLED (CONFIG_SPARSE_IRQ )) {
427- /* attempt to allocated irq_descs */
428- int rc = irq_alloc_descs (first_irq , first_irq , size ,
429- of_node_to_nid (to_of_node (fwnode )));
430- if (rc < 0 )
431- pr_info ("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n" ,
432- first_irq );
433- }
434- irq_domain_associate_many (domain , first_irq , 0 , size );
435- }
436-
437- return domain ;
469+ return IS_ERR (domain ) ? NULL : domain ;
438470}
439471EXPORT_SYMBOL_GPL (irq_domain_create_simple );
440472
@@ -476,18 +508,14 @@ struct irq_domain *irq_domain_create_legacy(struct fwnode_handle *fwnode,
476508 .fwnode = fwnode ,
477509 .size = first_hwirq + size ,
478510 .hwirq_max = first_hwirq + size ,
511+ .hwirq_base = first_hwirq ,
512+ .virq_base = first_irq ,
479513 .ops = ops ,
480514 .host_data = host_data ,
481515 };
482- struct irq_domain * domain ;
516+ struct irq_domain * domain = irq_domain_instantiate ( & info ) ;
483517
484- domain = irq_domain_instantiate (& info );
485- if (IS_ERR (domain ))
486- return NULL ;
487-
488- irq_domain_associate_many (domain , first_irq , first_hwirq , size );
489-
490- return domain ;
518+ return IS_ERR (domain ) ? NULL : domain ;
491519}
492520EXPORT_SYMBOL_GPL (irq_domain_create_legacy );
493521
0 commit comments