diff options
author | Suren A. Chilingaryan <csa@suren.me> | 2015-05-08 16:35:09 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@suren.me> | 2015-05-08 16:35:09 +0200 |
commit | a1889bc2f45b3d944652be6436569980f189922d (patch) | |
tree | e4fe4ad383fd190f1269aff4e51cf538642881ef | |
parent | 8f241478d649bfafb73f7fe0e4ae5e3d80b73bab (diff) | |
download | pcitool-a1889bc2f45b3d944652be6436569980f189922d.tar.gz pcitool-a1889bc2f45b3d944652be6436569980f189922d.tar.bz2 pcitool-a1889bc2f45b3d944652be6436569980f189922d.tar.xz pcitool-a1889bc2f45b3d944652be6436569980f189922d.zip |
Predict next accessed DMA block in the driver (to speed-up buffer syncing)
-rw-r--r-- | driver/common.h | 3 | ||||
-rw-r--r-- | driver/kmem.c | 36 |
2 files changed, 35 insertions, 4 deletions
diff --git a/driver/common.h b/driver/common.h index 75005e9..6bc1329 100644 --- a/driver/common.h +++ b/driver/common.h @@ -1,7 +1,7 @@ #ifndef _PCIDRIVER_COMMON_H #define _PCIDRIVER_COMMON_H -#include "../kmem.h" +#include "../pcilib/kmem.h" /*************************************************************************/ /* Private data types and structures */ @@ -64,6 +64,7 @@ typedef struct { spinlock_t kmemlist_lock; /* Spinlock to lock kmem list operations */ struct list_head kmem_list; /* List of 'kmem_list_entry's associated with this device */ + pcidriver_kmem_entry_t *kmem_last_sync; /* Last accessed kmem entry */ atomic_t kmem_count; /* id for next kmem entry */ int kmem_cur_id; /* Currently selected kmem buffer, for mmap */ diff --git a/driver/kmem.c b/driver/kmem.c index b323272..9b3ab14 100644 --- a/driver/kmem.c +++ b/driver/kmem.c @@ -396,11 +396,39 @@ int pcidriver_kmem_sync_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_en */ int pcidriver_kmem_sync( pcidriver_privdata_t *privdata, kmem_sync_t *kmem_sync ) { - pcidriver_kmem_entry_t *kmem_entry; + pcidriver_kmem_entry_t *kmem_entry = NULL; - /* Find the associated kmem_entry for this buffer */ - if ((kmem_entry = pcidriver_kmem_find_entry(privdata, &(kmem_sync->handle))) == NULL) + /* + * This is a shortcut to quickly find a next item in big multi-page kernel buffers + */ + spin_lock(&(privdata->kmemlist_lock)); + if (privdata->kmem_last_sync) { + if (privdata->kmem_last_sync->id == kmem_sync->handle.handle_id) + kmem_entry = privdata->kmem_last_sync; + else { + privdata->kmem_last_sync = container_of(privdata->kmem_last_sync->list.next, pcidriver_kmem_entry_t, list); + + if (privdata->kmem_last_sync) { + if (privdata->kmem_last_sync->id == kmem_sync->handle.handle_id) + kmem_entry = privdata->kmem_last_sync; + else + privdata->kmem_last_sync = NULL; + } + } + } + spin_unlock(&(privdata->kmemlist_lock)); + + /* + * If not found go the standard way + */ + if (!kmem_entry) { + if ((kmem_entry = pcidriver_kmem_find_entry(privdata, &(kmem_sync->handle))) == NULL) return -EINVAL; /* kmem_handle is not valid */ + + spin_lock(&(privdata->kmemlist_lock)); + privdata->kmem_last_sync = kmem_entry; + spin_unlock(&(privdata->kmemlist_lock)); + } return pcidriver_kmem_sync_entry(privdata, kmem_entry, kmem_sync->dir); } @@ -466,6 +494,8 @@ int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_ent /* Remove the kmem list entry */ spin_lock( &(privdata->kmemlist_lock) ); + if (privdata->kmem_last_sync == kmem_entry) + privdata->kmem_last_sync = NULL; list_del( &(kmem_entry->list) ); spin_unlock( &(privdata->kmemlist_lock) ); |