public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] export PCI resources in sysfs
@ 2004-12-21 17:43 Jesse Barnes
  2004-12-21 18:43 ` Greg KH
  0 siblings, 1 reply; 5+ messages in thread
From: Jesse Barnes @ 2004-12-21 17:43 UTC (permalink / raw)
  To: Greg KH, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 503 bytes --]

This patch sits on top of the last one that added mmap support to
struct bin_attribute.  It exports PCI resources from each device as a
file in the device's sysfs directory as resourceN where N is the
resource number.  The file is mmapable so that userspace can do
register reads and writes.

 drivers/pci/pci-sysfs.c |   72 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci.h     |    1
 2 files changed, 73 insertions(+)

Signed-off-by: Jesse Barnes <jbarnes@sgi.com>

Thanks,
Jesse

[-- Attachment #2: sysfs-pci-resource.patch --]
[-- Type: text/plain, Size: 3843 bytes --]

===== drivers/pci/pci-sysfs.c 1.13 vs edited =====
--- 1.13/drivers/pci/pci-sysfs.c	2004-11-30 11:54:02 -08:00
+++ edited/drivers/pci/pci-sysfs.c	2004-12-21 09:38:49 -08:00
@@ -20,6 +20,7 @@
 #include <linux/pci.h>
 #include <linux/stat.h>
 #include <linux/topology.h>
+#include <linux/mm.h>
 
 #include "pci.h"
 
@@ -178,6 +179,32 @@
 	return count;
 }
 
+#ifdef HAVE_PCI_MMAP
+/**
+ * pci_mmap_resource - map a PCI resource into user memory space
+ * @kobj: kobject for mapping
+ * @attr: struct bin_attribute for the file being mapped
+ * @vma: struct vm_area_struct passed into the mmap
+ *
+ * Use the regular PCI mapping routines to map a PCI resource into userspace.
+ * FIXME: write combining?  maybe automatic for prefetchable regions?
+ */
+static int
+pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
+		  struct vm_area_struct *vma)
+{
+	struct pci_dev *pdev = to_pci_dev(container_of(kobj,
+						       struct device, kobj));
+	struct resource *res = (struct resource *)attr->private;
+	enum pci_mmap_state mmap_type;
+
+	vma->vm_pgoff += res->start >> PAGE_SHIFT;
+	mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
+
+	return pci_mmap_page_range(pdev, vma, mmap_type, 0);
+}
+#endif /* HAVE_PCI_MMAP */
+
 /**
  * pci_write_rom - used to enable access to the PCI ROM display
  * @kobj: kernel object handle
@@ -261,6 +288,10 @@
 
 int pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
+#ifdef HAVE_PCI_MMAP
+	int i;
+#endif
+
 	if (!sysfs_initialized)
 		return -EACCES;
 
@@ -269,6 +300,31 @@
 	else
 		sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
 
+#ifdef HAVE_PCI_MMAP
+	/* Expose the PCI resources from this device as files */
+	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+		struct bin_attribute *res_attr;
+
+		/* skip empty resources */
+		if (!pci_resource_len(pdev, i))
+			continue;
+
+		res_attr = kmalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
+		if (res_attr) {
+			pdev->res_attr[i] = res_attr;
+			/* Allocated above after the res_attr struct */
+			res_attr->attr.name = (char *)(res_attr + 1);
+			sprintf(res_attr->attr.name, "resource%d", i);
+			res_attr->size = pci_resource_len(pdev, i);
+			res_attr->attr.mode = S_IRUSR | S_IWUSR;
+			res_attr->attr.owner = THIS_MODULE;
+			res_attr->mmap = pci_mmap_resource;
+			res_attr->private = &pdev->resource[i];
+			sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
+		}
+	}
+#endif /* HAVE_PCI_MMAP */
+
 	/* If the device has a ROM, try to expose it in sysfs. */
 	if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
 		struct bin_attribute *rom_attr;
@@ -299,10 +355,26 @@
  */
 void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 {
+#ifdef HAVE_PCI_MMAP
+	int i;
+#endif
+
 	if (pdev->cfg_size < 4096)
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
 	else
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+
+#ifdef HAVE_PCI_MMAP
+	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+		struct bin_attribute *res_attr;
+
+		res_attr = pdev->res_attr[i];
+		if (res_attr) {
+			sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
+			kfree(res_attr);
+		}
+	}
+#endif /* HAVE_PCI_MMAP */
 
 	if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
 		if (pdev->rom_attr) {
===== include/linux/pci.h 1.142 vs edited =====
--- 1.142/include/linux/pci.h	2004-10-31 14:10:04 -08:00
+++ edited/include/linux/pci.h	2004-12-21 09:08:37 -08:00
@@ -539,6 +539,7 @@
 	u32		saved_config_space[16]; /* config space saved at suspend time */
 	struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
 	int rom_attr_enabled;		/* has display of the rom attribute been enabled? */
+	struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
 #ifdef CONFIG_PCI_NAMES
 #define PCI_NAME_SIZE	96
 #define PCI_NAME_HALF	__stringify(43)	/* less than half to handle slop */

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] export PCI resources in sysfs
  2004-12-21 17:43 [PATCH] export PCI resources in sysfs Jesse Barnes
@ 2004-12-21 18:43 ` Greg KH
  2004-12-21 19:09   ` Jesse Barnes
  0 siblings, 1 reply; 5+ messages in thread
From: Greg KH @ 2004-12-21 18:43 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: linux-kernel

On Tue, Dec 21, 2004 at 09:43:39AM -0800, Jesse Barnes wrote:
>  int pci_create_sysfs_dev_files (struct pci_dev *pdev)
>  {
> +#ifdef HAVE_PCI_MMAP
> +	int i;
> +#endif
> +
>  	if (!sysfs_initialized)
>  		return -EACCES;
>  
> @@ -269,6 +300,31 @@
>  	else
>  		sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
>  
> +#ifdef HAVE_PCI_MMAP
> +	/* Expose the PCI resources from this device as files */
> +	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
> +		struct bin_attribute *res_attr;
> +
> +		/* skip empty resources */
> +		if (!pci_resource_len(pdev, i))
> +			continue;
> +
> +		res_attr = kmalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
> +		if (res_attr) {
> +			pdev->res_attr[i] = res_attr;
> +			/* Allocated above after the res_attr struct */
> +			res_attr->attr.name = (char *)(res_attr + 1);
> +			sprintf(res_attr->attr.name, "resource%d", i);
> +			res_attr->size = pci_resource_len(pdev, i);
> +			res_attr->attr.mode = S_IRUSR | S_IWUSR;
> +			res_attr->attr.owner = THIS_MODULE;
> +			res_attr->mmap = pci_mmap_resource;
> +			res_attr->private = &pdev->resource[i];
> +			sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
> +		}
> +	}
> +#endif /* HAVE_PCI_MMAP */

How about wrapping these two #ifdef blocks into one function, and moving
it up in the file under the other #ifdef.  Do that for the other cleanup
function, and it will drop a bunch of #ifdefs.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] export PCI resources in sysfs
  2004-12-21 18:43 ` Greg KH
@ 2004-12-21 19:09   ` Jesse Barnes
  2004-12-21 19:56     ` Jesse Barnes
  0 siblings, 1 reply; 5+ messages in thread
From: Jesse Barnes @ 2004-12-21 19:09 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel

On Tuesday, December 21, 2004 10:43 am, Greg KH wrote:
> On Tue, Dec 21, 2004 at 09:43:39AM -0800, Jesse Barnes wrote:
> >  int pci_create_sysfs_dev_files (struct pci_dev *pdev)
> >  {
> > +#ifdef HAVE_PCI_MMAP
> > + int i;
> > +#endif
> > +
> >   if (!sysfs_initialized)
> >    return -EACCES;
> >
> > @@ -269,6 +300,31 @@
> >   else
> >    sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
> >
> > +#ifdef HAVE_PCI_MMAP
> > + /* Expose the PCI resources from this device as files */
> > + for (i = 0; i < PCI_ROM_RESOURCE; i++) {
> > +  struct bin_attribute *res_attr;
> > +
> > +  /* skip empty resources */
> > +  if (!pci_resource_len(pdev, i))
> > +   continue;
> > +
> > +  res_attr = kmalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
> > +  if (res_attr) {
> > +   pdev->res_attr[i] = res_attr;
> > +   /* Allocated above after the res_attr struct */
> > +   res_attr->attr.name = (char *)(res_attr + 1);
> > +   sprintf(res_attr->attr.name, "resource%d", i);
> > +   res_attr->size = pci_resource_len(pdev, i);
> > +   res_attr->attr.mode = S_IRUSR | S_IWUSR;
> > +   res_attr->attr.owner = THIS_MODULE;
> > +   res_attr->mmap = pci_mmap_resource;
> > +   res_attr->private = &pdev->resource[i];
> > +   sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
> > +  }
> > + }
> > +#endif /* HAVE_PCI_MMAP */
>
> How about wrapping these two #ifdef blocks into one function, and moving
> it up in the file under the other #ifdef.  Do that for the other cleanup
> function, and it will drop a bunch of #ifdefs.

Yeah, that sounds good.  I really don't like adding these ifdefs, and limiting 
their scope to a function somewhere up above would be nicer.  I'll do that 
and respin.

Thanks,
Jesse

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] export PCI resources in sysfs
  2004-12-21 19:09   ` Jesse Barnes
@ 2004-12-21 19:56     ` Jesse Barnes
  2004-12-21 20:18       ` Greg KH
  0 siblings, 1 reply; 5+ messages in thread
From: Jesse Barnes @ 2004-12-21 19:56 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 767 bytes --]

On Tuesday, December 21, 2004 11:09 am, Jesse Barnes wrote:
> > How about wrapping these two #ifdef blocks into one function, and moving
> > it up in the file under the other #ifdef.  Do that for the other cleanup
> > function, and it will drop a bunch of #ifdefs.
>
> Yeah, that sounds good.  I really don't like adding these ifdefs, and
> limiting their scope to a function somewhere up above would be nicer.  I'll
> do that and respin.

Ok, here you go.

This patch exports PCI resources to userspace in the corresponding sysfs 
device directory.  It depends on the platform HAVE_PCI_MMAP code, and is 
#ifdef'd accordingly.  I've also added documentation describing the sysfs PCI 
device file layout.

Signed-off-by: Jesse Barnes <jbarnes@sgi.com>

Thanks,
Jesse

[-- Attachment #2: sysfs-pci-resource-2.patch --]
[-- Type: text/plain, Size: 6969 bytes --]

===== drivers/pci/pci-sysfs.c 1.13 vs edited =====
--- 1.13/drivers/pci/pci-sysfs.c	2004-11-30 11:54:02 -08:00
+++ edited/drivers/pci/pci-sysfs.c	2004-12-21 11:28:57 -08:00
@@ -20,6 +20,7 @@
 #include <linux/pci.h>
 #include <linux/stat.h>
 #include <linux/topology.h>
+#include <linux/mm.h>
 
 #include "pci.h"
 
@@ -178,6 +179,93 @@
 	return count;
 }
 
+#ifdef HAVE_PCI_MMAP
+/**
+ * pci_mmap_resource - map a PCI resource into user memory space
+ * @kobj: kobject for mapping
+ * @attr: struct bin_attribute for the file being mapped
+ * @vma: struct vm_area_struct passed into the mmap
+ *
+ * Use the regular PCI mapping routines to map a PCI resource into userspace.
+ * FIXME: write combining?  maybe automatic for prefetchable regions?
+ */
+static int
+pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
+		  struct vm_area_struct *vma)
+{
+	struct pci_dev *pdev = to_pci_dev(container_of(kobj,
+						       struct device, kobj));
+	struct resource *res = (struct resource *)attr->private;
+	enum pci_mmap_state mmap_type;
+
+	vma->vm_pgoff += res->start >> PAGE_SHIFT;
+	mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
+
+	return pci_mmap_page_range(pdev, vma, mmap_type, 0);
+}
+
+/**
+ * pci_create_resource_files - create resource files in sysfs for @dev
+ * @dev: dev in question
+ *
+ * Walk the resources in @dev creating files for each resource available.
+ */
+static void
+pci_create_resource_files(struct pci_dev *pdev)
+{
+	int i;
+
+	/* Expose the PCI resources from this device as files */
+	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+		struct bin_attribute *res_attr;
+
+		/* skip empty resources */
+		if (!pci_resource_len(pdev, i))
+			continue;
+
+		res_attr = kmalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
+		if (res_attr) {
+			pdev->res_attr[i] = res_attr;
+			/* Allocated above after the res_attr struct */
+			res_attr->attr.name = (char *)(res_attr + 1);
+			sprintf(res_attr->attr.name, "resource%d", i);
+			res_attr->size = pci_resource_len(pdev, i);
+			res_attr->attr.mode = S_IRUSR | S_IWUSR;
+			res_attr->attr.owner = THIS_MODULE;
+			res_attr->mmap = pci_mmap_resource;
+			res_attr->private = &pdev->resource[i];
+			sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
+		}
+	}
+}
+
+/**
+ * pci_remove_resource_files - cleanup resource files
+ * @dev: dev to cleanup
+ *
+ * If we created resource files for @dev, remove them from sysfs and
+ * free their resources.
+ */
+static void
+pci_remove_resource_files(struct pci_dev *pdev)
+{
+	int i;
+
+	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+		struct bin_attribute *res_attr;
+
+		res_attr = pdev->res_attr[i];
+		if (res_attr) {
+			sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
+			kfree(res_attr);
+		}
+	}
+}
+#else /* !HAVE_PCI_MMAP */
+static void pci_create_resource_files(struct pci_dev *dev) { return; }
+static void pci_remove_resource_files(struct pci_dev *dev) { return; }
+#endif /* HAVE_PCI_MMAP */
+
 /**
  * pci_write_rom - used to enable access to the PCI ROM display
  * @kobj: kernel object handle
@@ -269,6 +357,8 @@
 	else
 		sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
 
+	pci_create_resource_files(pdev);
+
 	/* If the device has a ROM, try to expose it in sysfs. */
 	if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
 		struct bin_attribute *rom_attr;
@@ -303,6 +393,8 @@
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
 	else
 		sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+
+	pci_remove_resource_files(pdev);
 
 	if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
 		if (pdev->rom_attr) {
===== include/linux/pci.h 1.142 vs edited =====
--- 1.142/include/linux/pci.h	2004-10-31 14:10:04 -08:00
+++ edited/include/linux/pci.h	2004-12-21 11:21:50 -08:00
@@ -539,6 +539,7 @@
 	u32		saved_config_space[16]; /* config space saved at suspend time */
 	struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
 	int rom_attr_enabled;		/* has display of the rom attribute been enabled? */
+	struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
 #ifdef CONFIG_PCI_NAMES
 #define PCI_NAME_SIZE	96
 #define PCI_NAME_HALF	__stringify(43)	/* less than half to handle slop */
--- /dev/null	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5-pcires/Documentation/filesystems/sysfs-pci.txt	2004-12-21 11:50:26.000000000 -0800
@@ -0,0 +1,64 @@
+Accessing PCI device resources through sysfs
+
+sysfs, usually mounted at /sys, provides access to PCI resources on platforms
+that support it.  For example, a given bus might look like this:
+
+     pci0000:17
+     |-- 0000:17:00.0
+     |   |-- class
+     |   |-- config
+     |   |-- detach_state
+     |   |-- device
+     |   |-- irq
+     |   |-- local_cpus
+     |   |-- resource
+     |   |-- resource0
+     |   |-- resource1
+     |   |-- resource2
+     |   |-- rom
+     |   |-- subsystem_device
+     |   |-- subsystem_vendor
+     |   `-- vendor
+     `-- detach_state
+
+The topmost element describes the PCI domain and bus number.  In this case,
+the domain number is 0000 and the bus number is 17 (both values are in hex).
+This bus contains a single function device in slot 0.  The domain and bus
+numbers are reproduced for convenience.  Under the device directory are several
+files, each with their own function.
+
+       file		   function
+       ----		   --------
+       class		   PCI class (ascii, ro)
+       config		   PCI config space (binary, rw)
+       detach_state	   connection status (bool, rw)
+       device		   PCI device (ascii, ro)
+       irq		   IRQ number (ascii, ro)
+       local_cpus	   nearby CPU mask (cpumask, ro)
+       resource		   PCI resource host addresses (ascii, ro)
+       resource0..N	   PCI resource N, if present (binary, mmap)
+       rom		   PCI ROM resource, if present (binary, ro)
+       subsystem_device	   PCI subsystem device (ascii, ro)
+       subsystem_vendor	   PCI subsystem vendor (ascii, ro)
+       vendor		   PCI vendor (ascii, ro)
+
+  ro - read only file
+  rw - file is readable and writable
+  mmap - file is mmapable
+  ascii - file contains ascii text
+  binary - file contains binary data
+  cpumask - file contains a cpumask type
+
+The read only files are informational, writes to them will be ignored.
+Writable files can be used to perform actions on the device (e.g. changing
+config space, detaching a device).  mmapable files are available via an
+mmap of the file at offset 0 and can be used to do actual device programming
+from userspace.  Note that some platforms don't support mmapping of certain
+resources, so be sure to check the return value from any attempted mmap.
+
+Supporting PCI access on new platforms
+
+In order to support PCI resource mapping as described above, Linux platform
+code must define HAVE_PCI_MMAP and provide a pci_mmap_page_range function.
+Platforms are free to only support subsets of the mmap functionality, but
+useful return codes should be provided.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] export PCI resources in sysfs
  2004-12-21 19:56     ` Jesse Barnes
@ 2004-12-21 20:18       ` Greg KH
  0 siblings, 0 replies; 5+ messages in thread
From: Greg KH @ 2004-12-21 20:18 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: linux-kernel

On Tue, Dec 21, 2004 at 11:56:39AM -0800, Jesse Barnes wrote:
> On Tuesday, December 21, 2004 11:09 am, Jesse Barnes wrote:
> > > How about wrapping these two #ifdef blocks into one function, and moving
> > > it up in the file under the other #ifdef.  Do that for the other cleanup
> > > function, and it will drop a bunch of #ifdefs.
> >
> > Yeah, that sounds good.  I really don't like adding these ifdefs, and
> > limiting their scope to a function somewhere up above would be nicer.  I'll
> > do that and respin.
> 
> Ok, here you go.
> 
> This patch exports PCI resources to userspace in the corresponding sysfs 
> device directory.  It depends on the platform HAVE_PCI_MMAP code, and is 
> #ifdef'd accordingly.  I've also added documentation describing the sysfs PCI 
> device file layout.
> 
> Signed-off-by: Jesse Barnes <jbarnes@sgi.com>

Looks good, I made one tiny change:

> +#else /* !HAVE_PCI_MMAP */
> +static void pci_create_resource_files(struct pci_dev *dev) { return; }
> +static void pci_remove_resource_files(struct pci_dev *dev) { return; }
> +#endif /* HAVE_PCI_MMAP */

I made these inline to have the compiler just "make them go away" for
when that define isn't enabled.

Applied to my trees,

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2004-12-21 20:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-21 17:43 [PATCH] export PCI resources in sysfs Jesse Barnes
2004-12-21 18:43 ` Greg KH
2004-12-21 19:09   ` Jesse Barnes
2004-12-21 19:56     ` Jesse Barnes
2004-12-21 20:18       ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox