1919
2020#include "internals.h"
2121
22+ static inline int msi_sysfs_create_group (struct device * dev );
2223#define dev_to_msi_list (dev ) (&(dev)->msi.data->list)
2324
2425/**
@@ -178,6 +179,7 @@ static void msi_device_data_release(struct device *dev, void *res)
178179int msi_setup_device_data (struct device * dev )
179180{
180181 struct msi_device_data * md ;
182+ int ret ;
181183
182184 if (dev -> msi .data )
183185 return 0 ;
@@ -186,6 +188,12 @@ int msi_setup_device_data(struct device *dev)
186188 if (!md )
187189 return - ENOMEM ;
188190
191+ ret = msi_sysfs_create_group (dev );
192+ if (ret ) {
193+ devres_free (md );
194+ return ret ;
195+ }
196+
189197 INIT_LIST_HEAD (& md -> list );
190198 mutex_init (& md -> mutex );
191199 dev -> msi .data = md ;
@@ -351,6 +359,20 @@ unsigned int msi_get_virq(struct device *dev, unsigned int index)
351359EXPORT_SYMBOL_GPL (msi_get_virq );
352360
353361#ifdef CONFIG_SYSFS
362+ static struct attribute * msi_dev_attrs [] = {
363+ NULL
364+ };
365+
366+ static const struct attribute_group msi_irqs_group = {
367+ .name = "msi_irqs" ,
368+ .attrs = msi_dev_attrs ,
369+ };
370+
371+ static inline int msi_sysfs_create_group (struct device * dev )
372+ {
373+ return devm_device_add_group (dev , & msi_irqs_group );
374+ }
375+
354376static ssize_t msi_mode_show (struct device * dev , struct device_attribute * attr ,
355377 char * buf )
356378{
@@ -360,97 +382,74 @@ static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
360382 return sysfs_emit (buf , "%s\n" , is_msix ? "msix" : "msi" );
361383}
362384
363- /**
364- * msi_populate_sysfs - Populate msi_irqs sysfs entries for devices
365- * @dev: The device(PCI, platform etc) who will get sysfs entries
366- */
367- static const struct attribute_group * * msi_populate_sysfs (struct device * dev )
385+ static void msi_sysfs_remove_desc (struct device * dev , struct msi_desc * desc )
368386{
369- const struct attribute_group * * msi_irq_groups ;
370- struct attribute * * msi_attrs , * msi_attr ;
371- struct device_attribute * msi_dev_attr ;
372- struct attribute_group * msi_irq_group ;
373- struct msi_desc * entry ;
374- int ret = - ENOMEM ;
375- int num_msi = 0 ;
376- int count = 0 ;
387+ struct device_attribute * attrs = desc -> sysfs_attrs ;
377388 int i ;
378389
379- /* Determine how many msi entries we have */
380- msi_for_each_desc (entry , dev , MSI_DESC_ALL )
381- num_msi += entry -> nvec_used ;
382- if (!num_msi )
383- return NULL ;
390+ if (!attrs )
391+ return ;
384392
385- /* Dynamically create the MSI attributes for the device */
386- msi_attrs = kcalloc (num_msi + 1 , sizeof (void * ), GFP_KERNEL );
387- if (!msi_attrs )
388- return ERR_PTR (- ENOMEM );
389-
390- msi_for_each_desc (entry , dev , MSI_DESC_ALL ) {
391- for (i = 0 ; i < entry -> nvec_used ; i ++ ) {
392- msi_dev_attr = kzalloc (sizeof (* msi_dev_attr ), GFP_KERNEL );
393- if (!msi_dev_attr )
394- goto error_attrs ;
395- msi_attrs [count ] = & msi_dev_attr -> attr ;
396-
397- sysfs_attr_init (& msi_dev_attr -> attr );
398- msi_dev_attr -> attr .name = kasprintf (GFP_KERNEL , "%d" ,
399- entry -> irq + i );
400- if (!msi_dev_attr -> attr .name )
401- goto error_attrs ;
402- msi_dev_attr -> attr .mode = 0444 ;
403- msi_dev_attr -> show = msi_mode_show ;
404- ++ count ;
405- }
393+ desc -> sysfs_attrs = NULL ;
394+ for (i = 0 ; i < desc -> nvec_used ; i ++ ) {
395+ if (attrs [i ].show )
396+ sysfs_remove_file_from_group (& dev -> kobj , & attrs [i ].attr , msi_irqs_group .name );
397+ kfree (attrs [i ].attr .name );
406398 }
399+ kfree (attrs );
400+ }
407401
408- msi_irq_group = kzalloc (sizeof (* msi_irq_group ), GFP_KERNEL );
409- if (!msi_irq_group )
410- goto error_attrs ;
411- msi_irq_group -> name = "msi_irqs" ;
412- msi_irq_group -> attrs = msi_attrs ;
402+ static int msi_sysfs_populate_desc (struct device * dev , struct msi_desc * desc )
403+ {
404+ struct device_attribute * attrs ;
405+ int ret , i ;
413406
414- msi_irq_groups = kcalloc (2 , sizeof (void * ), GFP_KERNEL );
415- if (!msi_irq_groups )
416- goto error_irq_group ;
417- msi_irq_groups [0 ] = msi_irq_group ;
407+ attrs = kcalloc (desc -> nvec_used , sizeof (* attrs ), GFP_KERNEL );
408+ if (!attrs )
409+ return - ENOMEM ;
418410
419- ret = sysfs_create_groups (& dev -> kobj , msi_irq_groups );
420- if (ret )
421- goto error_irq_groups ;
422-
423- return msi_irq_groups ;
424-
425- error_irq_groups :
426- kfree (msi_irq_groups );
427- error_irq_group :
428- kfree (msi_irq_group );
429- error_attrs :
430- count = 0 ;
431- msi_attr = msi_attrs [count ];
432- while (msi_attr ) {
433- msi_dev_attr = container_of (msi_attr , struct device_attribute , attr );
434- kfree (msi_attr -> name );
435- kfree (msi_dev_attr );
436- ++ count ;
437- msi_attr = msi_attrs [count ];
411+ desc -> sysfs_attrs = attrs ;
412+ for (i = 0 ; i < desc -> nvec_used ; i ++ ) {
413+ sysfs_attr_init (& attrs [i ].attr );
414+ attrs [i ].attr .name = kasprintf (GFP_KERNEL , "%d" , desc -> irq + i );
415+ if (!attrs [i ].attr .name ) {
416+ ret = - ENOMEM ;
417+ goto fail ;
418+ }
419+
420+ attrs [i ].attr .mode = 0444 ;
421+ attrs [i ].show = msi_mode_show ;
422+
423+ ret = sysfs_add_file_to_group (& dev -> kobj , & attrs [i ].attr , msi_irqs_group .name );
424+ if (ret ) {
425+ attrs [i ].show = NULL ;
426+ goto fail ;
427+ }
438428 }
439- kfree (msi_attrs );
440- return ERR_PTR (ret );
429+ return 0 ;
430+
431+ fail :
432+ msi_sysfs_remove_desc (dev , desc );
433+ return ret ;
441434}
442435
436+ #ifdef CONFIG_PCI_MSI_ARCH_FALLBACKS
443437/**
444438 * msi_device_populate_sysfs - Populate msi_irqs sysfs entries for a device
445439 * @dev: The device (PCI, platform etc) which will get sysfs entries
446440 */
447441int msi_device_populate_sysfs (struct device * dev )
448442{
449- const struct attribute_group * * group = msi_populate_sysfs (dev );
443+ struct msi_desc * desc ;
444+ int ret ;
450445
451- if (IS_ERR (group ))
452- return PTR_ERR (group );
453- dev -> msi .data -> attrs = group ;
446+ msi_for_each_desc (desc , dev , MSI_DESC_ASSOCIATED ) {
447+ if (desc -> sysfs_attrs )
448+ continue ;
449+ ret = msi_sysfs_populate_desc (dev , desc );
450+ if (ret )
451+ return ret ;
452+ }
454453 return 0 ;
455454}
456455
@@ -461,28 +460,17 @@ int msi_device_populate_sysfs(struct device *dev)
461460 */
462461void msi_device_destroy_sysfs (struct device * dev )
463462{
464- const struct attribute_group * * msi_irq_groups = dev -> msi .data -> attrs ;
465- struct device_attribute * dev_attr ;
466- struct attribute * * msi_attrs ;
467- int count = 0 ;
468-
469- dev -> msi .data -> attrs = NULL ;
470- if (!msi_irq_groups )
471- return ;
463+ struct msi_desc * desc ;
472464
473- sysfs_remove_groups (& dev -> kobj , msi_irq_groups );
474- msi_attrs = msi_irq_groups [0 ]-> attrs ;
475- while (msi_attrs [count ]) {
476- dev_attr = container_of (msi_attrs [count ], struct device_attribute , attr );
477- kfree (dev_attr -> attr .name );
478- kfree (dev_attr );
479- ++ count ;
480- }
481- kfree (msi_attrs );
482- kfree (msi_irq_groups [0 ]);
483- kfree (msi_irq_groups );
465+ msi_for_each_desc (desc , dev , MSI_DESC_ALL )
466+ msi_sysfs_remove_desc (dev , desc );
484467}
485- #endif
468+ #endif /* CONFIG_PCI_MSI_ARCH_FALLBACK */
469+ #else /* CONFIG_SYSFS */
470+ static inline int msi_sysfs_create_group (struct device * dev ) { return 0 ; }
471+ static inline int msi_sysfs_populate_desc (struct device * dev , struct msi_desc * desc ) { return 0 ; }
472+ static inline void msi_sysfs_remove_desc (struct device * dev , struct msi_desc * desc ) { }
473+ #endif /* !CONFIG_SYSFS */
486474
487475#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
488476static inline void irq_chip_write_msi_msg (struct irq_data * data ,
@@ -914,6 +902,12 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
914902 ret = msi_init_virq (domain , virq + i , vflags );
915903 if (ret )
916904 return ret ;
905+
906+ if (info -> flags & MSI_FLAG_DEV_SYSFS ) {
907+ ret = msi_sysfs_populate_desc (dev , desc );
908+ if (ret )
909+ return ret ;
910+ }
917911 }
918912 allocated ++ ;
919913 }
@@ -958,18 +952,7 @@ int msi_domain_alloc_irqs_descs_locked(struct irq_domain *domain, struct device
958952
959953 ret = ops -> domain_alloc_irqs (domain , dev , nvec );
960954 if (ret )
961- goto cleanup ;
962-
963- if (!(info -> flags & MSI_FLAG_DEV_SYSFS ))
964- return 0 ;
965-
966- ret = msi_device_populate_sysfs (dev );
967- if (ret )
968- goto cleanup ;
969- return 0 ;
970-
971- cleanup :
972- msi_domain_free_irqs_descs_locked (domain , dev );
955+ msi_domain_free_irqs_descs_locked (domain , dev );
973956 return ret ;
974957}
975958
@@ -994,6 +977,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, int nve
994977
995978void __msi_domain_free_irqs (struct irq_domain * domain , struct device * dev )
996979{
980+ struct msi_domain_info * info = domain -> host_data ;
997981 struct irq_data * irqd ;
998982 struct msi_desc * desc ;
999983 int i ;
@@ -1008,6 +992,8 @@ void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
1008992 }
1009993
1010994 irq_domain_free_irqs (desc -> irq , desc -> nvec_used );
995+ if (info -> flags & MSI_FLAG_DEV_SYSFS )
996+ msi_sysfs_remove_desc (dev , desc );
1011997 desc -> irq = 0 ;
1012998 }
1013999}
@@ -1036,8 +1022,6 @@ void msi_domain_free_irqs_descs_locked(struct irq_domain *domain, struct device
10361022
10371023 lockdep_assert_held (& dev -> msi .data -> mutex );
10381024
1039- if (info -> flags & MSI_FLAG_DEV_SYSFS )
1040- msi_device_destroy_sysfs (dev );
10411025 ops -> domain_free_irqs (domain , dev );
10421026 msi_domain_free_msi_descs (info , dev );
10431027}
0 commit comments