Skip to content

Commit 2f17081

Browse files
Barry SongKAGA-KOKO
authored andcommitted
genirq/msi: Move MSI sysfs handling from PCI to MSI core
Move PCI's MSI sysfs code to the irq core so that other busses such as platform can reuse it. Signed-off-by: Barry Song <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Greg Kroah-Hartman <[email protected]> Acked-by: Bjorn Helgaas <[email protected]> Acked-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 88ffe2d commit 2f17081

File tree

3 files changed

+148
-115
lines changed

3 files changed

+148
-115
lines changed

drivers/pci/msi.c

Lines changed: 10 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,7 @@ static void free_msi_irqs(struct pci_dev *dev)
363363
{
364364
struct list_head *msi_list = dev_to_msi_list(&dev->dev);
365365
struct msi_desc *entry, *tmp;
366-
struct attribute **msi_attrs;
367-
struct device_attribute *dev_attr;
368-
int i, count = 0;
366+
int i;
369367

370368
for_each_pci_msi_entry(entry, dev)
371369
if (entry->irq)
@@ -385,18 +383,7 @@ static void free_msi_irqs(struct pci_dev *dev)
385383
}
386384

387385
if (dev->msi_irq_groups) {
388-
sysfs_remove_groups(&dev->dev.kobj, dev->msi_irq_groups);
389-
msi_attrs = dev->msi_irq_groups[0]->attrs;
390-
while (msi_attrs[count]) {
391-
dev_attr = container_of(msi_attrs[count],
392-
struct device_attribute, attr);
393-
kfree(dev_attr->attr.name);
394-
kfree(dev_attr);
395-
++count;
396-
}
397-
kfree(msi_attrs);
398-
kfree(dev->msi_irq_groups[0]);
399-
kfree(dev->msi_irq_groups);
386+
msi_destroy_sysfs(&dev->dev, dev->msi_irq_groups);
400387
dev->msi_irq_groups = NULL;
401388
}
402389
}
@@ -476,102 +463,6 @@ void pci_restore_msi_state(struct pci_dev *dev)
476463
}
477464
EXPORT_SYMBOL_GPL(pci_restore_msi_state);
478465

479-
static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
480-
char *buf)
481-
{
482-
struct msi_desc *entry;
483-
unsigned long irq;
484-
int retval;
485-
486-
retval = kstrtoul(attr->attr.name, 10, &irq);
487-
if (retval)
488-
return retval;
489-
490-
entry = irq_get_msi_desc(irq);
491-
if (!entry)
492-
return -ENODEV;
493-
494-
return sysfs_emit(buf, "%s\n",
495-
entry->msi_attrib.is_msix ? "msix" : "msi");
496-
}
497-
498-
static int populate_msi_sysfs(struct pci_dev *pdev)
499-
{
500-
struct attribute **msi_attrs;
501-
struct attribute *msi_attr;
502-
struct device_attribute *msi_dev_attr;
503-
struct attribute_group *msi_irq_group;
504-
const struct attribute_group **msi_irq_groups;
505-
struct msi_desc *entry;
506-
int ret = -ENOMEM;
507-
int num_msi = 0;
508-
int count = 0;
509-
int i;
510-
511-
/* Determine how many msi entries we have */
512-
for_each_pci_msi_entry(entry, pdev)
513-
num_msi += entry->nvec_used;
514-
if (!num_msi)
515-
return 0;
516-
517-
/* Dynamically create the MSI attributes for the PCI device */
518-
msi_attrs = kcalloc(num_msi + 1, sizeof(void *), GFP_KERNEL);
519-
if (!msi_attrs)
520-
return -ENOMEM;
521-
for_each_pci_msi_entry(entry, pdev) {
522-
for (i = 0; i < entry->nvec_used; i++) {
523-
msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
524-
if (!msi_dev_attr)
525-
goto error_attrs;
526-
msi_attrs[count] = &msi_dev_attr->attr;
527-
528-
sysfs_attr_init(&msi_dev_attr->attr);
529-
msi_dev_attr->attr.name = kasprintf(GFP_KERNEL, "%d",
530-
entry->irq + i);
531-
if (!msi_dev_attr->attr.name)
532-
goto error_attrs;
533-
msi_dev_attr->attr.mode = S_IRUGO;
534-
msi_dev_attr->show = msi_mode_show;
535-
++count;
536-
}
537-
}
538-
539-
msi_irq_group = kzalloc(sizeof(*msi_irq_group), GFP_KERNEL);
540-
if (!msi_irq_group)
541-
goto error_attrs;
542-
msi_irq_group->name = "msi_irqs";
543-
msi_irq_group->attrs = msi_attrs;
544-
545-
msi_irq_groups = kcalloc(2, sizeof(void *), GFP_KERNEL);
546-
if (!msi_irq_groups)
547-
goto error_irq_group;
548-
msi_irq_groups[0] = msi_irq_group;
549-
550-
ret = sysfs_create_groups(&pdev->dev.kobj, msi_irq_groups);
551-
if (ret)
552-
goto error_irq_groups;
553-
pdev->msi_irq_groups = msi_irq_groups;
554-
555-
return 0;
556-
557-
error_irq_groups:
558-
kfree(msi_irq_groups);
559-
error_irq_group:
560-
kfree(msi_irq_group);
561-
error_attrs:
562-
count = 0;
563-
msi_attr = msi_attrs[count];
564-
while (msi_attr) {
565-
msi_dev_attr = container_of(msi_attr, struct device_attribute, attr);
566-
kfree(msi_attr->name);
567-
kfree(msi_dev_attr);
568-
++count;
569-
msi_attr = msi_attrs[count];
570-
}
571-
kfree(msi_attrs);
572-
return ret;
573-
}
574-
575466
static struct msi_desc *
576467
msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd)
577468
{
@@ -667,9 +558,11 @@ static int msi_capability_init(struct pci_dev *dev, int nvec,
667558
if (ret)
668559
goto err;
669560

670-
ret = populate_msi_sysfs(dev);
671-
if (ret)
561+
dev->msi_irq_groups = msi_populate_sysfs(&dev->dev);
562+
if (IS_ERR(dev->msi_irq_groups)) {
563+
ret = PTR_ERR(dev->msi_irq_groups);
672564
goto err;
565+
}
673566

674567
/* Set MSI enabled bits */
675568
pci_intx_for_msi(dev, 0);
@@ -834,9 +727,11 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
834727

835728
msix_update_entries(dev, entries);
836729

837-
ret = populate_msi_sysfs(dev);
838-
if (ret)
730+
dev->msi_irq_groups = msi_populate_sysfs(&dev->dev);
731+
if (IS_ERR(dev->msi_irq_groups)) {
732+
ret = PTR_ERR(dev->msi_irq_groups);
839733
goto out_free;
734+
}
840735

841736
/* Set MSI-X enabled bits and unmask the function */
842737
pci_intx_for_msi(dev, 0);

include/linux/msi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
239239
void pci_msi_mask_irq(struct irq_data *data);
240240
void pci_msi_unmask_irq(struct irq_data *data);
241241

242+
const struct attribute_group **msi_populate_sysfs(struct device *dev);
243+
void msi_destroy_sysfs(struct device *dev,
244+
const struct attribute_group **msi_irq_groups);
245+
242246
/*
243247
* The arch hooks to setup up msi irqs. Default functions are implemented
244248
* as weak symbols so that they /can/ be overriden by architecture specific

kernel/irq/msi.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/irqdomain.h>
1515
#include <linux/msi.h>
1616
#include <linux/slab.h>
17+
#include <linux/pci.h>
1718

1819
#include "internals.h"
1920

@@ -71,6 +72,139 @@ void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
7172
}
7273
EXPORT_SYMBOL_GPL(get_cached_msi_msg);
7374

75+
static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
76+
char *buf)
77+
{
78+
struct msi_desc *entry;
79+
bool is_msix = false;
80+
unsigned long irq;
81+
int retval;
82+
83+
retval = kstrtoul(attr->attr.name, 10, &irq);
84+
if (retval)
85+
return retval;
86+
87+
entry = irq_get_msi_desc(irq);
88+
if (!entry)
89+
return -ENODEV;
90+
91+
if (dev_is_pci(dev))
92+
is_msix = entry->msi_attrib.is_msix;
93+
94+
return sysfs_emit(buf, "%s\n", is_msix ? "msix" : "msi");
95+
}
96+
97+
/**
98+
* msi_populate_sysfs - Populate msi_irqs sysfs entries for devices
99+
* @dev: The device(PCI, platform etc) who will get sysfs entries
100+
*
101+
* Return attribute_group ** so that specific bus MSI can save it to
102+
* somewhere during initilizing msi irqs. If devices has no MSI irq,
103+
* return NULL; if it fails to populate sysfs, return ERR_PTR
104+
*/
105+
const struct attribute_group **msi_populate_sysfs(struct device *dev)
106+
{
107+
const struct attribute_group **msi_irq_groups;
108+
struct attribute **msi_attrs, *msi_attr;
109+
struct device_attribute *msi_dev_attr;
110+
struct attribute_group *msi_irq_group;
111+
struct msi_desc *entry;
112+
int ret = -ENOMEM;
113+
int num_msi = 0;
114+
int count = 0;
115+
int i;
116+
117+
/* Determine how many msi entries we have */
118+
for_each_msi_entry(entry, dev)
119+
num_msi += entry->nvec_used;
120+
if (!num_msi)
121+
return NULL;
122+
123+
/* Dynamically create the MSI attributes for the device */
124+
msi_attrs = kcalloc(num_msi + 1, sizeof(void *), GFP_KERNEL);
125+
if (!msi_attrs)
126+
return ERR_PTR(-ENOMEM);
127+
128+
for_each_msi_entry(entry, dev) {
129+
for (i = 0; i < entry->nvec_used; i++) {
130+
msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
131+
if (!msi_dev_attr)
132+
goto error_attrs;
133+
msi_attrs[count] = &msi_dev_attr->attr;
134+
135+
sysfs_attr_init(&msi_dev_attr->attr);
136+
msi_dev_attr->attr.name = kasprintf(GFP_KERNEL, "%d",
137+
entry->irq + i);
138+
if (!msi_dev_attr->attr.name)
139+
goto error_attrs;
140+
msi_dev_attr->attr.mode = 0444;
141+
msi_dev_attr->show = msi_mode_show;
142+
++count;
143+
}
144+
}
145+
146+
msi_irq_group = kzalloc(sizeof(*msi_irq_group), GFP_KERNEL);
147+
if (!msi_irq_group)
148+
goto error_attrs;
149+
msi_irq_group->name = "msi_irqs";
150+
msi_irq_group->attrs = msi_attrs;
151+
152+
msi_irq_groups = kcalloc(2, sizeof(void *), GFP_KERNEL);
153+
if (!msi_irq_groups)
154+
goto error_irq_group;
155+
msi_irq_groups[0] = msi_irq_group;
156+
157+
ret = sysfs_create_groups(&dev->kobj, msi_irq_groups);
158+
if (ret)
159+
goto error_irq_groups;
160+
161+
return msi_irq_groups;
162+
163+
error_irq_groups:
164+
kfree(msi_irq_groups);
165+
error_irq_group:
166+
kfree(msi_irq_group);
167+
error_attrs:
168+
count = 0;
169+
msi_attr = msi_attrs[count];
170+
while (msi_attr) {
171+
msi_dev_attr = container_of(msi_attr, struct device_attribute, attr);
172+
kfree(msi_attr->name);
173+
kfree(msi_dev_attr);
174+
++count;
175+
msi_attr = msi_attrs[count];
176+
}
177+
kfree(msi_attrs);
178+
return ERR_PTR(ret);
179+
}
180+
181+
/**
182+
* msi_destroy_sysfs - Destroy msi_irqs sysfs entries for devices
183+
* @dev: The device(PCI, platform etc) who will remove sysfs entries
184+
* @msi_irq_groups: attribute_group for device msi_irqs entries
185+
*/
186+
void msi_destroy_sysfs(struct device *dev, const struct attribute_group **msi_irq_groups)
187+
{
188+
struct device_attribute *dev_attr;
189+
struct attribute **msi_attrs;
190+
int count = 0;
191+
192+
if (msi_irq_groups) {
193+
sysfs_remove_groups(&dev->kobj, msi_irq_groups);
194+
msi_attrs = msi_irq_groups[0]->attrs;
195+
while (msi_attrs[count]) {
196+
dev_attr = container_of(msi_attrs[count],
197+
struct device_attribute, attr);
198+
kfree(dev_attr->attr.name);
199+
kfree(dev_attr);
200+
++count;
201+
}
202+
kfree(msi_attrs);
203+
kfree(msi_irq_groups[0]);
204+
kfree(msi_irq_groups);
205+
}
206+
}
207+
74208
#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
75209
static inline void irq_chip_write_msi_msg(struct irq_data *data,
76210
struct msi_msg *msg)

0 commit comments

Comments
 (0)