diff options
| author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-14 06:01:27 +0200 | 
|---|---|---|
| committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-14 06:01:27 +0200 | 
| commit | f4ad2df2209acac66f3df47d847f1f714283feab (patch) | |
| tree | 23da0368acbb6c15cdebd2a35808cd6bbe99b8ae /driver | |
| parent | b492b1aac3d12683ccbc973b08b023ba0466cbec (diff) | |
| download | ipecamera-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.c | 2 | ||||
| -rw-r--r-- | driver/common.h | 5 | ||||
| -rw-r--r-- | driver/kmem.c | 56 | ||||
| -rw-r--r-- | driver/kmem.h | 1 | ||||
| -rw-r--r-- | driver/pciDriver.h | 2 | ||||
| -rw-r--r-- | driver/sysfs.c | 9 | 
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  | 
