@@ -246,6 +246,8 @@ void *platform_msi_get_host_data(struct irq_domain *domain)
246246 return data -> host_data ;
247247}
248248
249+ static struct lock_class_key platform_device_msi_lock_class ;
250+
249251/**
250252 * __platform_msi_create_device_domain - Create a platform-msi device domain
251253 *
@@ -278,6 +280,13 @@ __platform_msi_create_device_domain(struct device *dev,
278280 if (err )
279281 return NULL ;
280282
283+ /*
284+ * Use a separate lock class for the MSI descriptor mutex on
285+ * platform MSI device domains because the descriptor mutex nests
286+ * into the domain mutex. See alloc/free below.
287+ */
288+ lockdep_set_class (& dev -> msi .data -> mutex , & platform_device_msi_lock_class );
289+
281290 data = dev -> msi .data -> platform_data ;
282291 data -> host_data = host_data ;
283292 domain = irq_domain_create_hierarchy (dev -> msi .domain , 0 ,
@@ -300,75 +309,23 @@ __platform_msi_create_device_domain(struct device *dev,
300309 return NULL ;
301310}
302311
303- static void platform_msi_free_descs (struct device * dev , int base , int nvec )
304- {
305- struct msi_desc * desc , * tmp ;
306-
307- list_for_each_entry_safe (desc , tmp , dev_to_msi_list (dev ), list ) {
308- if (desc -> msi_index >= base &&
309- desc -> msi_index < (base + nvec )) {
310- list_del (& desc -> list );
311- free_msi_entry (desc );
312- }
313- }
314- }
315-
316- static int platform_msi_alloc_descs_with_irq (struct device * dev , int virq ,
317- int nvec )
318- {
319- struct msi_desc * desc ;
320- int i , base = 0 ;
321-
322- if (!list_empty (dev_to_msi_list (dev ))) {
323- desc = list_last_entry (dev_to_msi_list (dev ),
324- struct msi_desc , list );
325- base = desc -> msi_index + 1 ;
326- }
327-
328- for (i = 0 ; i < nvec ; i ++ ) {
329- desc = alloc_msi_entry (dev , 1 , NULL );
330- if (!desc )
331- break ;
332-
333- desc -> msi_index = base + i ;
334- desc -> irq = virq + i ;
335-
336- list_add_tail (& desc -> list , dev_to_msi_list (dev ));
337- }
338-
339- if (i != nvec ) {
340- /* Clean up the mess */
341- platform_msi_free_descs (dev , base , nvec );
342- return - ENOMEM ;
343- }
344-
345- return 0 ;
346- }
347-
348312/**
349313 * platform_msi_device_domain_free - Free interrupts associated with a platform-msi
350314 * device domain
351315 *
352316 * @domain: The platform-msi device domain
353317 * @virq: The base irq from which to perform the free operation
354- * @nvec : How many interrupts to free from @virq
318+ * @nr_irqs : How many interrupts to free from @virq
355319 */
356320void platform_msi_device_domain_free (struct irq_domain * domain , unsigned int virq ,
357- unsigned int nvec )
321+ unsigned int nr_irqs )
358322{
359323 struct platform_msi_priv_data * data = domain -> host_data ;
360- struct msi_desc * desc , * tmp ;
361324
362- for_each_msi_entry_safe (desc , tmp , data -> dev ) {
363- if (WARN_ON (!desc -> irq || desc -> nvec_used != 1 ))
364- return ;
365- if (!(desc -> irq >= virq && desc -> irq < (virq + nvec )))
366- continue ;
367-
368- irq_domain_free_irqs_common (domain , desc -> irq , 1 );
369- list_del (& desc -> list );
370- free_msi_entry (desc );
371- }
325+ msi_lock_descs (data -> dev );
326+ irq_domain_free_irqs_common (domain , virq , nr_irqs );
327+ msi_free_msi_descs_range (data -> dev , MSI_DESC_ALL , virq , virq + nr_irqs - 1 );
328+ msi_unlock_descs (data -> dev );
372329}
373330
374331/**
@@ -377,7 +334,7 @@ void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int vir
377334 *
378335 * @domain: The platform-msi device domain
379336 * @virq: The base irq from which to perform the allocate operation
380- * @nr_irqs: How many interrupts to free from @virq
337+ * @nr_irqs: How many interrupts to allocate from @virq
381338 *
382339 * Return 0 on success, or an error code on failure. Must be called
383340 * with irq_domain_mutex held (which can only be done as part of a
@@ -387,16 +344,7 @@ int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int vir
387344 unsigned int nr_irqs )
388345{
389346 struct platform_msi_priv_data * data = domain -> host_data ;
390- int err ;
391-
392- err = platform_msi_alloc_descs_with_irq (data -> dev , virq , nr_irqs );
393- if (err )
394- return err ;
395-
396- err = msi_domain_populate_irqs (domain -> parent , data -> dev ,
397- virq , nr_irqs , & data -> arg );
398- if (err )
399- platform_msi_device_domain_free (domain , virq , nr_irqs );
347+ struct device * dev = data -> dev ;
400348
401- return err ;
349+ return msi_domain_populate_irqs ( domain -> parent , dev , virq , nr_irqs , & data -> arg ) ;
402350}
0 commit comments