Create struct msi_device_data and add a pointer of that type to struct dev_msi_info, which is part of struct device. Provide an allocator function which can be invoked from the MSI interrupt allocation code pathes. Add a properties field to the data structure as a first member so the allocation size is not zero bytes. The field will be uses later on.
Unified · Split
| @@ -45,6 +45,7 @@ struct iommu_ops; · 44 unmodified lines | ||
| 45 | 45 | struct iommu_group; |
| 46 | 46 | struct dev_pin_info; |
| 47 | 47 | struct dev_iommu; |
| 48 | +struct msi_device_data; | |
| 48 | 49 | |
| 49 | 50 | /** |
| 50 | 51 | * struct subsys_interface - interfaces to device functions |
| @@ -374,11 +375,15 @@ struct dev_links_info { · 323 unmodified lines | ||
| 374 | 375 | /** |
| 375 | 376 | * struct dev_msi_info - Device data related to MSI |
| 376 | 377 | * @domain: The MSI interrupt domain associated to the device |
| 378 | + * @data: Pointer to MSI device data | |
| 377 | 379 | */ |
| 378 | 380 | struct dev_msi_info { |
| 379 | 381 | #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN |
| 380 | 382 | struct irq_domain *domain; |
| 381 | 383 | #endif |
| 384 | +#ifdef CONFIG_GENERIC_MSI_IRQ | |
| 385 | + struct msi_device_data *data; | |
| 386 | +#endif | |
| 382 | 387 | }; |
| 383 | 388 | |
| 384 | 389 | /** |
| @@ -171,6 +171,16 @@ struct msi_desc { · 170 unmodified lines | ||
| 171 | 171 | }; |
| 172 | 172 | }; |
| 173 | 173 | |
| 174 | +/** | |
| 175 | + * msi_device_data - MSI per device data | |
| 176 | + * @properties: MSI properties which are interesting to drivers | |
| 177 | + */ | |
| 178 | +struct msi_device_data { | |
| 179 | + unsigned long properties; | |
| 180 | +}; | |
| 181 | + | |
| 182 | +int msi_setup_device_data(struct device *dev); | |
| 183 | + | |
| 174 | 184 | /* Helpers to hide struct msi_desc implementation details */ |
| 175 | 185 | #define msi_desc_to_dev(desc) ((desc)->dev) |
| 176 | 186 | #define dev_to_msi_list(dev) (&(dev)->msi_list) |
| @@ -233,10 +243,16 @@ void pci_msi_mask_irq(struct irq_data *data); · 56 unmodified lines | ||
| 233 | 243 | void pci_msi_unmask_irq(struct irq_data *data); |
| 234 | 244 | |
| 235 | 245 | #ifdef CONFIG_SYSFS |
| 246 | +int msi_device_populate_sysfs(struct device *dev); | |
| 247 | +void msi_device_destroy_sysfs(struct device *dev); | |
| 248 | + | |
| 236 | 249 | const struct attribute_group **msi_populate_sysfs(struct device *dev); |
| 237 | 250 | void msi_destroy_sysfs(struct device *dev, |
| 238 | 251 | const struct attribute_group **msi_irq_groups); |
| 239 | 252 | #else |
| 253 | +static inline int msi_device_populate_sysfs(struct device *dev) { return 0; } | |
| 254 | +static inline void msi_device_destroy_sysfs(struct device *dev) { } | |
| 255 | + | |
| 240 | 256 | static inline const struct attribute_group **msi_populate_sysfs(struct device *dev) |
| 241 | 257 | { |
| 242 | 258 | return NULL; |
| @@ -384,6 +400,8 @@ enum { · 141 unmodified lines | ||
| 384 | 400 | MSI_FLAG_MUST_REACTIVATE = (1 << 5), |
| 385 | 401 | /* Is level-triggered capable, using two messages */ |
| 386 | 402 | MSI_FLAG_LEVEL_CAPABLE = (1 << 6), |
| 403 | + /* Populate sysfs on alloc() and destroy it on free() */ | |
| 404 | + MSI_FLAG_DEV_SYSFS = (1 << 7), | |
| 387 | 405 | }; |
| 388 | 406 | |
| 389 | 407 | int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, |
| @@ -73,6 +73,38 @@ void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg) · 72 unmodified lines | ||
| 73 | 73 | } |
| 74 | 74 | EXPORT_SYMBOL_GPL(get_cached_msi_msg); |
| 75 | 75 | |
| 76 | +static void msi_device_data_release(struct device *dev, void *res) | |
| 77 | +{ | |
| 78 | + WARN_ON_ONCE(!list_empty(&dev->msi_list)); | |
| 79 | + dev->msi.data = NULL; | |
| 80 | +} | |
| 81 | + | |
| 82 | +/** | |
| 83 | + * msi_setup_device_data - Setup MSI device data | |
| 84 | + * @dev: Device for which MSI device data should be set up | |
| 85 | + * | |
| 86 | + * Return: 0 on success, appropriate error code otherwise | |
| 87 | + * | |
| 88 | + * This can be called more than once for @dev. If the MSI device data is | |
| 89 | + * already allocated the call succeeds. The allocated memory is | |
| 90 | + * automatically released when the device is destroyed. | |
| 91 | + */ | |
| 92 | +int msi_setup_device_data(struct device *dev) | |
| 93 | +{ | |
| 94 | + struct msi_device_data *md; | |
| 95 | + | |
| 96 | + if (dev->msi.data) | |
| 97 | + return 0; | |
| 98 | + | |
| 99 | + md = devres_alloc(msi_device_data_release, sizeof(*md), GFP_KERNEL); | |
| 100 | + if (!md) | |
| 101 | + return -ENOMEM; | |
| 102 | + | |
| 103 | + dev->msi.data = md; | |
| 104 | + devres_add(dev, md); | |
| 105 | + return 0; | |
| 106 | +} | |
| 107 | + | |
| 76 | 108 | #ifdef CONFIG_SYSFS |
| 77 | 109 | static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr, |
| 78 | 110 | char *buf) |