Re: [RFC][PATCH] Add sysfs entry that displays MSI-X IRQs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Thanks Greg, I wasn't sure what to do there. I've updated it to no permissions.




-- Vinnie.
>From 39acc4f1643d308e3ded71b4a93cc302f71e4287 Mon Sep 17 00:00:00 2001
From: Vincent Rizza <vinnie@xxxxxxx>
Date: Thu, 13 Nov 2008 10:27:33 +1100
Subject: [RFC][PATCH] Add sysfs entry that displays MSI-X IRQs

Here's the new patch. It creates an "msix_irq" directory in
/sys/bus/pci/devices/.../ and populates it with a file for each MSI-X
vector used by the device. The filename is the vector number(ie. IRQ).

Exposing the vectors to userspace allows applications like
irqbalancer to intelligently spread device IRQs across many CPUs
since it will be able to work out which IRQ belongs to which device.

Signed-off-by: Vincent Rizza <vinnie@xxxxxxx>
Signed-off-by: Brett Grandbois <brettg@xxxxxxx>
Signed-off-by: Greg Banks <gnb@xxxxxxx>
---
 Documentation/ABI/testing/sysfs-bus-pci |   10 ++++++++
 drivers/pci/msi.c                       |   36 +++++++++++++++++++++++++++++++
 include/linux/msi.h                     |    5 ++++
 include/linux/pci.h                     |    1 +
 4 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index ceddcff..23101b9 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -9,3 +9,13 @@ Description:
 		that some devices may have malformatted data.  If the
 		underlying VPD has a writable section then the
 		corresponding section of this file will be writable.
+
+What:		/sys/bus/pci/devices/.../msix_irq/<IRQ vector number>
+Date:		November 2008
+Contact:	Vincent Rizza <vinnie@xxxxxxx>
+Description:
+		If a pci device uses any MSI-X IRQs a new directory
+		is created called "msix_irq". The directory contains a
+		file for each MSI-X IRQ used. The filename is the IRQ
+		number. There are no permissions on the files since all
+		the information needed is in the filename.
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 74801f7..cc0a00c 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -488,12 +488,31 @@ static int msix_capability_init(struct pci_dev *dev,
 		return avail;
 	}
 
+	/* create directory "msix_irq" */
+	dev->msix_dir = kobject_create_and_add("msix_irq", &dev->dev.kobj);
+	if (!dev->msix_dir)
+		return -ENOMEM;
+
 	i = 0;
 	list_for_each_entry(entry, &dev->msi_list, list) {
 		entries[i].vector = entry->irq;
 		set_irq_msi(entry->irq, entry);
+
+		snprintf(entry->msix_fname, sizeof(entry->msix_fname), "%d",
+			 entry->irq);
+		entry->sysfs_entry.attr.name = (const char *) entry->msix_fname;
+
+		ret = sysfs_create_file(dev->msix_dir,
+					&entry->sysfs_entry.attr);
+		if (ret) {
+			/* Using name as a flag during clean-up */
+			entry->sysfs_entry.attr.name = NULL;
+			msi_free_irqs(dev);
+			return ret;
+		}
 		i++;
 	}
+
 	/* Set MSI-X enabled bits */
 	pci_intx_for_msi(dev, 0);
 	msix_set_enable(dev, 1);
@@ -641,10 +660,27 @@ static int msi_free_irqs(struct pci_dev* dev)
 			if (list_is_last(&entry->list, &dev->msi_list))
 				iounmap(entry->mask_base);
 		}
+
+		/*
+		 *  Only remove if it's been created. If the attribute's name is
+		 *  set then this particular "entry" corresponds to a sysfs
+		 *  file.
+		 */
+		if (entry->sysfs_entry.attr.name)
+			sysfs_remove_file(&dev->dev.kobj,
+					  &entry->sysfs_entry.attr);
+
 		list_del(&entry->list);
 		kfree(entry);
 	}
 
+	/* Also doesn't exist in MSI mode */
+	if (dev->msix_dir) {
+		sysfs_remove_dir(dev->msix_dir);
+		kobject_put(dev->msix_dir);
+		dev->msix_dir = NULL;
+	}
+
 	return 0;
 }
 
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 8f29392..b0c92d3 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -2,6 +2,7 @@
 #define LINUX_MSI_H
 
 #include <linux/list.h>
+#include <linux/device.h>
 
 struct msi_msg {
 	u32	address_lo;	/* low 32 bits of msi message address */
@@ -33,6 +34,10 @@ struct msi_desc {
 	void __iomem *mask_base;
 	struct pci_dev *dev;
 
+	struct	device_attribute sysfs_entry;
+	/* filename = IRQ */
+	char	msix_fname[16];
+
 	/* Last set MSI message */
 	struct msi_msg msg;
 };
diff --git a/include/linux/pci.h b/include/linux/pci.h
index c75b82b..6b818f7 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -234,6 +234,7 @@ struct pci_dev {
 	struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
 #ifdef CONFIG_PCI_MSI
 	struct list_head msi_list;
+	struct kobject *msix_dir;
 #endif
 	struct pci_vpd *vpd;
 };


[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux