summaryrefslogtreecommitdiffstats
path: root/driver/sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/sysfs.c')
-rw-r--r--driver/sysfs.c440
1 files changed, 235 insertions, 205 deletions
diff --git a/driver/sysfs.c b/driver/sysfs.c
index abc1c8a..d0fd870 100644
--- a/driver/sysfs.c
+++ b/driver/sysfs.c
@@ -18,291 +18,321 @@
#include <linux/pagemap.h>
#include <linux/kernel.h>
-#include "compat.h"
-#include "config.h"
-#include "pciDriver.h"
-#include "common.h"
-#include "umem.h"
-#include "kmem.h"
-#include "sysfs.h"
+#include "base.h"
-static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry);
-static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry);
+#define SYSFS_GET_PRIVDATA dev_get_drvdata(dev)
+#define SYSFS_GET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, char *buf)
+#define SYSFS_SET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-/**
- *
- * Initializes the sysfs attributes for an kmem/umem-entry
- *
- */
-static int _pcidriver_sysfs_initialize(pcidriver_privdata_t *privdata,
- int id,
- struct class_device_attribute *sysfs_attr,
- const char *fmtstring,
- SYSFS_GET_FUNCTION((*callback)))
-{
- /* sysfs attributes for kmem buffers don’t make sense before 2.6.13, as
- we have no mmap support before */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
- char namebuffer[16];
+#define SYSFS_ATTR_NAME(name) (dev_attr_##name)
- /* allocate space for the name of the attribute */
- snprintf(namebuffer, sizeof(namebuffer), fmtstring, id);
+#define SYSFS_ATTR_CREATE(name) do { \
+ int err = device_create_file(privdata->class_dev, &SYSFS_ATTR_NAME(name)); \
+ if (err != 0) return err; \
+ } while (0)
- if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL)
- return -ENOMEM;
+#define SYSFS_ATTR_REMOVE(name) do { \
+ device_remove_file(privdata->class_dev, &SYSFS_ATTR_NAME(name)); \
+ } while (0)
- sysfs_attr->attr.mode = S_IRUGO;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
- // DS: Shall we lock now while accessing driver data structures???
- sysfs_attr->attr.owner = THIS_MODULE;
-#endif
- sysfs_attr->show = callback;
- sysfs_attr->store = NULL;
-
- /* name and add attribute */
- if (class_device_create_file(privdata->class_dev, sysfs_attr) != 0)
- return -ENXIO; /* Device not configured. Not the really best choice, but hm. */
-#endif
+#ifdef ENABLE_IRQ
+static SYSFS_GET_FUNCTION(pcidriver_show_irq_count)
+{
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- return 0;
+ return snprintf(buf, PAGE_SIZE, "%d\n", privdata->irq_count);
}
-int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr)
+static SYSFS_GET_FUNCTION(pcidriver_show_irq_queues)
{
- return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry);
-}
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ int i, offset;
-int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr)
-{
- return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "umem%d", pcidriver_show_umem_entry);
-}
+ /* output will be truncated to PAGE_SIZE */
+ offset = snprintf(buf, PAGE_SIZE, "Queue\tOutstanding IRQs\n");
+ for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++)
+ offset += snprintf(buf+offset, PAGE_SIZE-offset, "%d\t%d\n", i, atomic_read(&(privdata->irq_outstanding[i])) );
-/**
- *
- * Removes the file from sysfs and frees the allocated (kstrdup()) memory.
- *
- */
-void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct class_device_attribute *sysfs_attr)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
- class_device_remove_file(privdata->class_dev, sysfs_attr);
- kfree(sysfs_attr->attr.name);
-#endif
+ return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
}
+#endif
-static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry)
+static SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
-
- /* As we can be sure that attr.name contains a filename which we
- * created (see _pcidriver_sysfs_initialize), we do not need to have
- * sanity checks but can directly call simple_strtol() */
- int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10);
- pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id);
- if (entry) {
- unsigned long addr = entry->cpua;
- unsigned long dma_addr = entry->dma_handle;
-
- if (entry->size >= 16) {
- pcidriver_kmem_sync_entry(privdata, entry, PCILIB_KMEM_SYNC_FROMDEVICE);
- return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\ndata: %8x %8x %8x %8x\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode, *(u32*)(entry->cpua), *(u32*)(entry->cpua + 4), *(u32*)(entry->cpua + 8), *(u32*)(entry->cpua + 12));
- } else
- return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode);
- } else
- return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id);
-#else
- return 0;
-#endif
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_mode);
}
-static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry)
+static SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
-#if 0
- pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)cls->class_data;
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ int mode = -1;
- return snprintf(buf, PAGE_SIZE, "I am in the umem_entry show function, class_device_kobj_name: %s\n", cls->kobj.name);
-#endif
- return 0;
-#else
- return 0;
-#endif
+ /* Set the mmap-mode if it is either PCIDRIVER_MMAP_PCI or PCIDRIVER_MMAP_KMEM */
+ if (sscanf(buf, "%d", &mode) == 1 &&
+ (mode == PCIDRIVER_MMAP_PCI || mode == PCIDRIVER_MMAP_KMEM))
+ privdata->mmap_mode = mode;
+
+ return strlen(buf);
}
-#ifdef ENABLE_IRQ
-SYSFS_GET_FUNCTION(pcidriver_show_irq_count)
+static SYSFS_GET_FUNCTION(pcidriver_show_mmap_area)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- return snprintf(buf, PAGE_SIZE, "%d\n", privdata->irq_count);
+ return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_area);
}
-SYSFS_GET_FUNCTION(pcidriver_show_irq_queues)
+static SYSFS_SET_FUNCTION(pcidriver_store_mmap_area)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- int i, offset;
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ int temp = -1;
+
+ sscanf(buf, "%d", &temp);
- /* output will be truncated to PAGE_SIZE */
- offset = snprintf(buf, PAGE_SIZE, "Queue\tOutstanding IRQs\n");
- for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++)
- offset += snprintf(buf+offset, PAGE_SIZE-offset, "%d\t%d\n", i, atomic_read(&(privdata->irq_outstanding[i])) );
+ if ((temp >= PCIDRIVER_BAR0) && (temp <= PCIDRIVER_BAR5))
+ privdata->mmap_area = temp;
- return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
+ return strlen(buf);
}
-#endif
-SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode)
+static SYSFS_GET_FUNCTION(pcidriver_show_kmem_count)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_mode);
+ return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&(privdata->kmem_count)));
}
-SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode)
+static SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- int mode = -1;
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ kmem_handle_t kmem_handle;
- /* Set the mmap-mode if it is either PCIDRIVER_MMAP_PCI or PCIDRIVER_MMAP_KMEM */
- if (sscanf(buf, "%d", &mode) == 1 &&
- (mode == PCIDRIVER_MMAP_PCI || mode == PCIDRIVER_MMAP_KMEM))
- privdata->mmap_mode = mode;
+ /* FIXME: guillermo: is validation of parsing an unsigned int enough? */
+ if (sscanf(buf, "%lu", &kmem_handle.size) == 1)
+ pcidriver_kmem_alloc(privdata, &kmem_handle);
- return strlen(buf);
+ return strlen(buf);
}
-SYSFS_GET_FUNCTION(pcidriver_show_mmap_area)
+static SYSFS_SET_FUNCTION(pcidriver_store_kmem_free)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ unsigned int id;
+ pcidriver_kmem_entry_t *kmem_entry;
+
+ /* Parse the ID of the kernel memory to be freed, check bounds */
+ if (sscanf(buf, "%u", &id) != 1 ||
+ (id >= atomic_read(&(privdata->kmem_count))))
+ goto err;
+
+ if ((kmem_entry = pcidriver_kmem_find_entry_id(privdata,id)) == NULL)
+ goto err;
- return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_area);
+ pcidriver_kmem_free_entry(privdata, kmem_entry );
+err:
+ return strlen(buf);
}
-SYSFS_SET_FUNCTION(pcidriver_store_mmap_area)
+static SYSFS_GET_FUNCTION(pcidriver_show_kbuffers)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- int temp = -1;
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ int offset = 0;
+ struct list_head *ptr;
+ pcidriver_kmem_entry_t *entry;
- sscanf(buf, "%d", &temp);
+ /* print the header */
+ offset += snprintf(buf, PAGE_SIZE, "kbuf#\tcpu addr\tsize\n");
- if ((temp >= PCIDRIVER_BAR0) && (temp <= PCIDRIVER_BAR5))
- privdata->mmap_area = temp;
+ spin_lock(&(privdata->kmemlist_lock));
+ list_for_each(ptr, &(privdata->kmem_list)) {
+ entry = list_entry(ptr, pcidriver_kmem_entry_t, list);
- return strlen(buf);
-}
+ /* print entry info */
+ if (offset > PAGE_SIZE) {
+ spin_unlock( &(privdata->kmemlist_lock) );
+ return PAGE_SIZE;
+ }
-SYSFS_GET_FUNCTION(pcidriver_show_kmem_count)
-{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%08lx\t%lu\n", entry->id, (unsigned long)(entry->dma_handle), entry->size );
+ }
+
+ spin_unlock(&(privdata->kmemlist_lock));
- return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&(privdata->kmem_count)));
+ /* output will be truncated to PAGE_SIZE */
+ return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
}
-SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc)
+static SYSFS_GET_FUNCTION(pcidriver_show_umappings)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- kmem_handle_t kmem_handle;
+ int offset = 0;
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ struct list_head *ptr;
+ pcidriver_umem_entry_t *entry;
- /* FIXME: guillermo: is validation of parsing an unsigned int enough? */
- if (sscanf(buf, "%lu", &kmem_handle.size) == 1)
- pcidriver_kmem_alloc(privdata, &kmem_handle);
+ /* print the header */
+ offset += snprintf(buf, PAGE_SIZE, "umap#\tn_pages\tsg_ents\n");
- return strlen(buf);
+ spin_lock( &(privdata->umemlist_lock) );
+ list_for_each( ptr, &(privdata->umem_list) ) {
+ entry = list_entry(ptr, pcidriver_umem_entry_t, list );
+
+ /* print entry info */
+ if (offset > PAGE_SIZE) {
+ spin_unlock( &(privdata->umemlist_lock) );
+ return PAGE_SIZE;
+ }
+
+ offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%lu\t%lu\n", entry->id,
+ (unsigned long)(entry->nr_pages), (unsigned long)(entry->nents));
+ }
+
+ spin_unlock( &(privdata->umemlist_lock) );
+
+ /* output will be truncated to PAGE_SIZE */
+ return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
}
-SYSFS_SET_FUNCTION(pcidriver_store_kmem_free)
+static SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- unsigned int id;
- pcidriver_kmem_entry_t *kmem_entry;
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+ pcidriver_umem_entry_t *umem_entry;
+ unsigned int id;
- /* Parse the ID of the kernel memory to be freed, check bounds */
- if (sscanf(buf, "%u", &id) != 1 ||
- (id >= atomic_read(&(privdata->kmem_count))))
- goto err;
+ if (sscanf(buf, "%u", &id) != 1 ||
+ (id >= atomic_read(&(privdata->umem_count))))
+ goto err;
- if ((kmem_entry = pcidriver_kmem_find_entry_id(privdata,id)) == NULL)
- goto err;
+ if ((umem_entry = pcidriver_umem_find_entry_id(privdata, id)) == NULL)
+ goto err;
- pcidriver_kmem_free_entry(privdata, kmem_entry );
+ pcidriver_umem_sgunmap(privdata, umem_entry);
err:
- return strlen(buf);
+ return strlen(buf);
}
-SYSFS_GET_FUNCTION(pcidriver_show_kbuffers)
+static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry)
+{
+ pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
+
+ /* As we can be sure that attr.name contains a filename which we
+ * created (see _pcidriver_sysfs_initialize), we do not need to have
+ * sanity checks but can directly call simple_strtol() */
+ int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10);
+ pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id);
+ if (entry) {
+ unsigned long addr = entry->cpua;
+ unsigned long dma_addr = entry->dma_handle;
+
+ if (entry->size >= 16) {
+ pcidriver_kmem_sync_entry(privdata, entry, PCILIB_KMEM_SYNC_FROMDEVICE);
+ return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\ndata: %8x %8x %8x %8x\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode, *(u32*)(entry->cpua), *(u32*)(entry->cpua + 4), *(u32*)(entry->cpua + 8), *(u32*)(entry->cpua + 12));
+ } else
+ return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode);
+ } else
+ return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id);
+}
+
+static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- int offset = 0;
- struct list_head *ptr;
- pcidriver_kmem_entry_t *entry;
+ return 0;
+}
- /* print the header */
- offset += snprintf(buf, PAGE_SIZE, "kbuf#\tcpu addr\tsize\n");
- spin_lock(&(privdata->kmemlist_lock));
- list_for_each(ptr, &(privdata->kmem_list)) {
- entry = list_entry(ptr, pcidriver_kmem_entry_t, list);
+#ifdef ENABLE_IRQ
+static DEVICE_ATTR(irq_count, S_IRUGO, pcidriver_show_irq_count, NULL);
+static DEVICE_ATTR(irq_queues, S_IRUGO, pcidriver_show_irq_queues, NULL);
+#endif
- /* print entry info */
- if (offset > PAGE_SIZE) {
- spin_unlock( &(privdata->kmemlist_lock) );
- return PAGE_SIZE;
- }
+static DEVICE_ATTR(mmap_mode, 0664, pcidriver_show_mmap_mode, pcidriver_store_mmap_mode);
+static DEVICE_ATTR(mmap_area, 0664, pcidriver_show_mmap_area, pcidriver_store_mmap_area);
+static DEVICE_ATTR(kmem_count, 0444, pcidriver_show_kmem_count, NULL);
+static DEVICE_ATTR(kbuffers, 0444, pcidriver_show_kbuffers, NULL);
+static DEVICE_ATTR(kmem_alloc, 0220, NULL, pcidriver_store_kmem_alloc);
+static DEVICE_ATTR(kmem_free, 0220, NULL, pcidriver_store_kmem_free);
+static DEVICE_ATTR(umappings, 0444, pcidriver_show_umappings, NULL);
+static DEVICE_ATTR(umem_unmap, 0220, NULL, pcidriver_store_umem_unmap);
- offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%08lx\t%lu\n", entry->id, (unsigned long)(entry->dma_handle), entry->size );
- }
+int pcidriver_create_sysfs_attributes(pcidriver_privdata_t *privdata) {
+#ifdef ENABLE_IRQ
+ SYSFS_ATTR_CREATE(irq_count);
+ SYSFS_ATTR_CREATE(irq_queues);
+#endif
- spin_unlock(&(privdata->kmemlist_lock));
+ SYSFS_ATTR_CREATE(mmap_mode);
+ SYSFS_ATTR_CREATE(mmap_area);
+ SYSFS_ATTR_CREATE(kmem_count);
+ SYSFS_ATTR_CREATE(kmem_alloc);
+ SYSFS_ATTR_CREATE(kmem_free);
+ SYSFS_ATTR_CREATE(kbuffers);
+ SYSFS_ATTR_CREATE(umappings);
+ SYSFS_ATTR_CREATE(umem_unmap);
+
+ return 0;
+}
+
+void pcidriver_remove_sysfs_attributes(pcidriver_privdata_t *privdata) {
+#ifdef ENABLE_IRQ
+ SYSFS_ATTR_REMOVE(irq_count);
+ SYSFS_ATTR_REMOVE(irq_queues);
+#endif
- /* output will be truncated to PAGE_SIZE */
- return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
+ SYSFS_ATTR_REMOVE(mmap_mode);
+ SYSFS_ATTR_REMOVE(mmap_area);
+ SYSFS_ATTR_REMOVE(kmem_count);
+ SYSFS_ATTR_REMOVE(kmem_alloc);
+ SYSFS_ATTR_REMOVE(kmem_free);
+ SYSFS_ATTR_REMOVE(kbuffers);
+ SYSFS_ATTR_REMOVE(umappings);
+ SYSFS_ATTR_REMOVE(umem_unmap);
}
-SYSFS_GET_FUNCTION(pcidriver_show_umappings)
+/**
+ *
+ * Removes the file from sysfs and frees the allocated (kstrdup()) memory.
+ *
+ */
+void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct device_attribute *sysfs_attr)
{
- int offset = 0;
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- struct list_head *ptr;
- pcidriver_umem_entry_t *entry;
+ device_remove_file(privdata->class_dev, sysfs_attr);
+ kfree(sysfs_attr->attr.name);
+}
- /* print the header */
- offset += snprintf(buf, PAGE_SIZE, "umap#\tn_pages\tsg_ents\n");
+/**
+ *
+ * Initializes the sysfs attributes for an kmem/umem-entry
+ *
+ */
+static int _pcidriver_sysfs_initialize(pcidriver_privdata_t *privdata, int id, struct device_attribute *sysfs_attr, const char *fmtstring, SYSFS_GET_FUNCTION((*callback)))
+{
+ /* sysfs attributes for kmem buffers don’t make sense before 2.6.13, as
+ we have no mmap support before */
+ char namebuffer[16];
- spin_lock( &(privdata->umemlist_lock) );
- list_for_each( ptr, &(privdata->umem_list) ) {
- entry = list_entry(ptr, pcidriver_umem_entry_t, list );
+ /* allocate space for the name of the attribute */
+ snprintf(namebuffer, sizeof(namebuffer), fmtstring, id);
- /* print entry info */
- if (offset > PAGE_SIZE) {
- spin_unlock( &(privdata->umemlist_lock) );
- return PAGE_SIZE;
- }
+ if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL)
+ return -ENOMEM;
- offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%lu\t%lu\n", entry->id,
- (unsigned long)(entry->nr_pages), (unsigned long)(entry->nents));
- }
+ sysfs_attr->attr.mode = S_IRUGO;
+ sysfs_attr->show = callback;
+ sysfs_attr->store = NULL;
- spin_unlock( &(privdata->umemlist_lock) );
+ /* name and add attribute */
+ if (device_create_file(privdata->class_dev, sysfs_attr) != 0)
+ return -ENXIO; /* Device not configured. Not the really best choice, but hm. */
- /* output will be truncated to PAGE_SIZE */
- return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
+ return 0;
}
-SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap)
+int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct device_attribute *sysfs_attr)
{
- pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
- pcidriver_umem_entry_t *umem_entry;
- unsigned int id;
-
- if (sscanf(buf, "%u", &id) != 1 ||
- (id >= atomic_read(&(privdata->umem_count))))
- goto err;
-
- if ((umem_entry = pcidriver_umem_find_entry_id(privdata, id)) == NULL)
- goto err;
+ return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry);
+}
- pcidriver_umem_sgunmap(privdata, umem_entry);
-err:
- return strlen(buf);
+int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct device_attribute *sysfs_attr)
+{
+ return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "umem%d", pcidriver_show_umem_entry);
}