summaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-14 06:01:27 +0200
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-14 06:01:27 +0200
commitf4ad2df2209acac66f3df47d847f1f714283feab (patch)
tree23da0368acbb6c15cdebd2a35808cd6bbe99b8ae /driver
parentb492b1aac3d12683ccbc973b08b023ba0466cbec (diff)
downloadipecamera-f4ad2df2209acac66f3df47d847f1f714283feab.tar.gz
ipecamera-f4ad2df2209acac66f3df47d847f1f714283feab.tar.bz2
ipecamera-f4ad2df2209acac66f3df47d847f1f714283feab.tar.xz
ipecamera-f4ad2df2209acac66f3df47d847f1f714283feab.zip
First iteration of work to preserve DMA state between executions
Diffstat (limited to 'driver')
-rw-r--r--driver/base.c2
-rw-r--r--driver/common.h5
-rw-r--r--driver/kmem.c56
-rw-r--r--driver/kmem.h1
-rw-r--r--driver/pciDriver.h2
-rw-r--r--driver/sysfs.c9
6 files changed, 70 insertions, 5 deletions
diff --git a/driver/base.c b/driver/base.c
index 2c3ff23..37102d8 100644
--- a/driver/base.c
+++ b/driver/base.c
@@ -352,6 +352,8 @@ static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_devi
INIT_LIST_HEAD(&(privdata->kmem_list));
spin_lock_init(&(privdata->kmemlist_lock));
atomic_set(&privdata->kmem_count, 0);
+
+ privdata->kmem_cur = NULL;
INIT_LIST_HEAD(&(privdata->umem_list));
spin_lock_init(&(privdata->umemlist_lock));
diff --git a/driver/common.h b/driver/common.h
index 3bc27d8..e45ae25 100644
--- a/driver/common.h
+++ b/driver/common.h
@@ -16,6 +16,7 @@ typedef struct {
unsigned long size;
unsigned long type;
unsigned long use;
+ unsigned long item;
struct class_device_attribute sysfs_attr; /* initialized when adding the entry */
} pcidriver_kmem_entry_t;
@@ -56,11 +57,13 @@ typedef struct {
struct list_head kmem_list; /* List of 'kmem_list_entry's associated with this device */
atomic_t kmem_count; /* id for next kmem entry */
+ pcidriver_kmem_entry_t *kmem_cur; /* Currently selected kmem buffer, for mmap */
+
spinlock_t umemlist_lock; /* Spinlock to lock umem list operations */
struct list_head umem_list; /* List of 'umem_list_entry's associated with this device */
atomic_t umem_count; /* id for next umem entry */
- int msi_mode;
+ int msi_mode; /* Flag specifying if interrupt have been initialized in MSI mode */
} pcidriver_privdata_t;
diff --git a/driver/kmem.c b/driver/kmem.c
index 95a5487..ed2a2af 100644
--- a/driver/kmem.c
+++ b/driver/kmem.c
@@ -35,6 +35,26 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
pcidriver_kmem_entry_t *kmem_entry;
void *retptr;
+ privdata->kmem_cur = NULL;
+
+ if (kmem_handle->reuse) {
+/* kmem_entry = pcidriver_kmem_find_entry_use(privdata, kmem_handle->use, kmem_handle->item);
+ if (kmem_entry) {
+ if (kmem_handle->type != kmem_entry->type) return EINVAL;
+
+ if (kmem_handle->type == PCILIB_KMEM_TYPE_PAGE) kmem_handle->size = kmem_entry->size;
+ else if (kmem_handle->size != kmem_entry->size) return EINVAL;
+
+ kmem_handle->handle_id = kmem_entry->id;
+ kmem_handle->pa = (unsigned long)(kmem_entry->dma_handle);
+
+ privdata->kmem_cur = kmem_entry;
+
+ return 0;
+ }*/
+ kmem_handle->reuse = 0;
+ }
+
/* First, allocate zeroed memory for the kmem_entry */
if ((kmem_entry = kcalloc(1, sizeof(pcidriver_kmem_entry_t), GFP_KERNEL)) == NULL)
goto kmem_alloc_entry_fail;
@@ -42,6 +62,7 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
/* Initialize the kmem_entry */
kmem_entry->id = atomic_inc_return(&privdata->kmem_count) - 1;
kmem_entry->use = kmem_handle->use;
+ kmem_entry->item = kmem_handle->item;
kmem_entry->type = kmem_handle->type;
kmem_handle->handle_id = kmem_entry->id;
@@ -102,6 +123,11 @@ int pcidriver_kmem_free( pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
{
pcidriver_kmem_entry_t *kmem_entry;
+ if (kmem_handle->reuse) {
+ // just mark free
+ return 0;
+ }
+
/* Find the associated kmem_entry for this buffer */
if ((kmem_entry = pcidriver_kmem_find_entry(privdata, kmem_handle)) == NULL)
return -EINVAL; /* kmem_handle is not valid */
@@ -193,6 +219,8 @@ int pcidriver_kmem_sync( pcidriver_privdata_t *privdata, kmem_sync_t *kmem_sync
*/
int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry)
{
+ privdata->kmem_cur = NULL;
+
pcidriver_sysfs_remove(privdata, &(kmem_entry->sysfs_attr));
/* Go over the pages of the kmem buffer, and mark them as not reserved */
@@ -299,6 +327,31 @@ pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_id(pcidriver_privdata_t *privd
/**
*
+ * find the corresponding kmem_entry for the given use and item.
+ *
+ */
+pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_use(pcidriver_privdata_t *privdata, unsigned long use, unsigned long item)
+{
+ struct list_head *ptr;
+ pcidriver_kmem_entry_t *entry, *result = NULL;
+
+ spin_lock(&(privdata->kmemlist_lock));
+ list_for_each(ptr, &(privdata->kmem_list)) {
+ entry = list_entry(ptr, pcidriver_kmem_entry_t, list);
+
+ if ((entry->use == use)&&(entry->item == item)) {
+ result = entry;
+ break;
+ }
+ }
+
+ spin_unlock(&(privdata->kmemlist_lock));
+ return result;
+}
+
+
+/**
+ *
* mmap() kernel memory to userspace.
*
*/
@@ -318,7 +371,8 @@ int pcidriver_mmap_kmem(pcidriver_privdata_t *privdata, struct vm_area_struct *v
mod_info("Trying to mmap a kernel memory buffer without creating it first!\n");
return -EFAULT;
}
- kmem_entry = list_entry(privdata->kmem_list.prev, pcidriver_kmem_entry_t, list);
+ if (privdata->kmem_cur) kmem_entry = privdata->kmem_cur;
+ else kmem_entry = list_entry(privdata->kmem_list.prev, pcidriver_kmem_entry_t, list);
spin_unlock(&(privdata->kmemlist_lock));
mod_info_dbg("Got kmem_entry with id: %d\n", kmem_entry->id);
diff --git a/driver/kmem.h b/driver/kmem.h
index c9e2fb9..ee12855 100644
--- a/driver/kmem.h
+++ b/driver/kmem.h
@@ -4,4 +4,5 @@ int pcidriver_kmem_sync( pcidriver_privdata_t *privdata, kmem_sync_t *kmem_sync
int pcidriver_kmem_free_all( pcidriver_privdata_t *privdata );
pcidriver_kmem_entry_t *pcidriver_kmem_find_entry( pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle );
pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_id( pcidriver_privdata_t *privdata, int id );
+pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_use(pcidriver_privdata_t *privdata, unsigned long use, unsigned long item);
int pcidriver_kmem_free_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry );
diff --git a/driver/pciDriver.h b/driver/pciDriver.h
index 74eacaf..3ff3357 100644
--- a/driver/pciDriver.h
+++ b/driver/pciDriver.h
@@ -106,6 +106,8 @@ typedef struct {
unsigned long size;
unsigned long align;
unsigned long use;
+ unsigned long item;
+ int reuse;
int handle_id;
} kmem_handle_t;
diff --git a/driver/sysfs.c b/driver/sysfs.c
index b082d3c..0653aef 100644
--- a/driver/sysfs.c
+++ b/driver/sysfs.c
@@ -90,14 +90,17 @@ void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct class_device_
static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
-// pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)cls->class_data;
+ 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);
-
- return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id);
+ pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id);
+ if (entry)
+ return snprintf(buf, PAGE_SIZE, "buffer: %d\ntype: %lu\nuse: 0x%lx\nitem: %lu\nsize: %lu\n", id, entry->type, entry->use, entry->item, entry->size);
+ else
+ return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id);
#else
return 0;
#endif