@@ -246,6 +246,8 @@ void *platform_msi_get_host_data(struct irq_domain *domain)
246
246
return data -> host_data ;
247
247
}
248
248
249
+ static struct lock_class_key platform_device_msi_lock_class ;
250
+
249
251
/**
250
252
* __platform_msi_create_device_domain - Create a platform-msi device domain
251
253
*
@@ -278,6 +280,13 @@ __platform_msi_create_device_domain(struct device *dev,
278
280
if (err )
279
281
return NULL ;
280
282
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
+
281
290
data = dev -> msi .data -> platform_data ;
282
291
data -> host_data = host_data ;
283
292
domain = irq_domain_create_hierarchy (dev -> msi .domain , 0 ,
@@ -300,75 +309,23 @@ __platform_msi_create_device_domain(struct device *dev,
300
309
return NULL ;
301
310
}
302
311
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
-
348
312
/**
349
313
* platform_msi_device_domain_free - Free interrupts associated with a platform-msi
350
314
* device domain
351
315
*
352
316
* @domain: The platform-msi device domain
353
317
* @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
355
319
*/
356
320
void platform_msi_device_domain_free (struct irq_domain * domain , unsigned int virq ,
357
- unsigned int nvec )
321
+ unsigned int nr_irqs )
358
322
{
359
323
struct platform_msi_priv_data * data = domain -> host_data ;
360
- struct msi_desc * desc , * tmp ;
361
324
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 );
372
329
}
373
330
374
331
/**
@@ -377,7 +334,7 @@ void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int vir
377
334
*
378
335
* @domain: The platform-msi device domain
379
336
* @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
381
338
*
382
339
* Return 0 on success, or an error code on failure. Must be called
383
340
* 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
387
344
unsigned int nr_irqs )
388
345
{
389
346
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 ;
400
348
401
- return err ;
349
+ return msi_domain_populate_irqs ( domain -> parent , dev , virq , nr_irqs , & data -> arg ) ;
402
350
}
0 commit comments