From f923add0a9b6bd17d43f72c21eec4e01e19240cf Mon Sep 17 00:00:00 2001 From: zilio nicolas Date: Tue, 7 Jul 2015 11:12:52 +0200 Subject: clean version for locks --- pcilib/CMakeLists.txt | 4 +- pcilib/kmem.h | 1 + pcilib/lock.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ pcilib/lock.h | 55 ++++++++++++++++++++++++ pcilib/locking.c | 74 ++++++++++++++++++++++++++++++++ pcilib/locking.h | 44 +++++++++++++++++++ pcilib/pci.c | 8 ++++ pcilib/pci.h | 2 +- 8 files changed, 301 insertions(+), 3 deletions(-) create mode 100644 pcilib/lock.c create mode 100644 pcilib/lock.h create mode 100644 pcilib/locking.c create mode 100644 pcilib/locking.h (limited to 'pcilib') diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index c9bf0fb..ebb5cec 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -3,8 +3,8 @@ include_directories( ${CMAKE_SOURCE_DIR}/pcilib ) -set(HEADERS pcilib.h pci.h export.h bar.h fifo.h model.h bank.h register.h kmem.h irq.h dma.h event.h plugin.h tools.h error.h debug.h env.h version.h config.h) -add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c register.c kmem.c irq.c dma.c event.c plugin.c tools.c error.c debug.c env.c) +set(HEADERS pcilib.h pci.h export.h bar.h fifo.h model.h bank.h register.h kmem.h irq.h dma.h event.h plugin.h tools.h error.h debug.h env.h version.h config.h locking.h lock.h) +add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c register.c kmem.c irq.c dma.c event.c plugin.c tools.c error.c debug.c env.c locking.c lock.c) target_link_libraries(pcilib dma protocols ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS}) add_dependencies(pcilib dma protocols) diff --git a/pcilib/kmem.h b/pcilib/kmem.h index 8299379..65bdf04 100644 --- a/pcilib/kmem.h +++ b/pcilib/kmem.h @@ -31,6 +31,7 @@ typedef enum { PCILIB_KMEM_USE_DMA_RING = 1, PCILIB_KMEM_USE_DMA_PAGES = 2, PCILIB_KMEM_USE_SOFTWARE_REGISTERS = 3, + PCILIB_KMEM_USE_MUTEXES = 4, PCILIB_KMEM_USE_USER = 0x10 } pcilib_kmem_use_t; diff --git a/pcilib/lock.c b/pcilib/lock.c new file mode 100644 index 0000000..8715d21 --- /dev/null +++ b/pcilib/lock.c @@ -0,0 +1,116 @@ +#define _GNU_SOURCE +#define _XOPEN_SOURCE 600 + +#include +#include +#include "error.h" +#include "lock.h" +#include "pci.h" + +/* + * this function will take the lock for the semaphore pointed by semId + */ +void pcilib_lock(pcilib_lock_t *lock_ctx, pcilib_lock_flags_t flags, ...){ + int err; + struct timespec *time; + va_list pa; + va_start(pa,flags); + + if(flags & MUTEX_LOCK){ + err=pthread_mutex_lock(lock_ctx);/**< we try to lock here*/ + if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + /** if the lock haven't been acquired and errno==EOWNERDEAD, it means the previous application that got the lock crashed, we have to remake the lock "consistent" so*/ + else if(errno==EOWNERDEAD){ + pthread_mutex_consistent(lock_ctx); + pthread_mutex_lock(lock_ctx); + if(err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + } + } + else if(flags & MUTEX_TRYLOCK){ + err=pthread_mutex_trylock(lock_ctx);/**< we try to lock here*/ + if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + else if(errno==EOWNERDEAD){ + pthread_mutex_consistent(lock_ctx); + pthread_mutex_lock(lock_ctx); + if(err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + } + } + else if(flags & MUTEX_TIMEDLOCK){ + time=va_arg(pa,struct timespec*); + va_end(pa); + err=pthread_mutex_timedlock(lock_ctx, time);/**< we try to lock here*/ + if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + else if(errno==EOWNERDEAD){ + pthread_mutex_consistent(lock_ctx); + pthread_mutex_timedlock(lock_ctx, time); + if(err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)), errno); + } + } + else pcilib_error("wrong flag for pcilib_lock"); +} + +/** + * this function will unlock the semaphore pointed by lock_ctx. + */ +void pcilib_unlock(pcilib_lock_t* lock_ctx){ + int err; + if((err=pthread_mutex_unlock(lock_ctx))!=0) pcilib_error("can't unlock semaphore\n"); +} + +/** + * pcilib_init_lock + * this function initialize a new semaphore in the kernel if it's not already initialized given the key that permits to differentiate semaphores, and then return the integer that points to the semaphore that have been initialized or to a previously already initialized semaphore + * @param[out] lock_ctx the pointer that will points to the semaphore for other functions + * @param[in] keysem the integer that permits to define to what the semaphore is attached + */ +pcilib_lock_t* pcilib_init_lock(pcilib_t *ctx, char* lock_id, ...){ + int err; + pthread_mutexattr_t attr; + int i,j; + void* addr,*locks_addr; + va_list pa; + va_start(pa,lock_id); + + pcilib_lock_init_flags_t flag; + flag=va_arg(pa,pcilib_lock_init_flags_t); + va_end(pa); + + if(strlen(lock_id)>PCILIB_LOCK_SIZE-sizeof(pcilib_lock_t)) pcilib_error("the entered protocol name is too long"); + if(((PCILIB_MAX_NUMBER_LOCKS*PCILIB_LOCK_SIZE)%PCILIB_KMEM_PAGE_SIZE)!=0) pcilib_error("PCILIB_MAX_NUMBER_LOCKS*PCILIB_LOCK_SIZE should be a multiple of kmem page size"); + + addr=pcilib_kmem_get_block_ua(ctx,ctx->locks_handle,0); + if(flag & LOCK_INIT) pcilib_lock((pcilib_lock_t*)addr,MUTEX_LOCK); + /* we search for the given lock if it was already initialized*/ + for(j=0;jlocks_handle,j); + while((*(char*)(locks_addr+i*PCILIB_LOCK_SIZE+sizeof(pcilib_lock_t))!=0) && (i +#include +#include "lock.h" + +/* + * this function clean all locks created by the pcitool program + */ +void pcilib_clean_all_locks(pcilib_t* ctx){ +int i,j; +void* addr; + i=0; + while(ilocks_handle,i); +for(j=0;jlocks_handle,PCILIB_KMEM_FLAG_REUSE); +} + +/* + * this function allocates the kernel memory for the locks for software registers + */ +int pcilib_init_locking(pcilib_t* ctx, ...){ +/*for future possible more args + va_list pa; + va_start(pa,ctx);*/ + pcilib_kmem_handle_t *handle; + int err; + pcilib_kmem_reuse_state_t reused; + + + if((err=flock(ctx->handle,LOCK_EX))==-1) pcilib_warning("can't get flock on /dev/fpga0"); + handle=pcilib_alloc_kernel_memory(ctx,PCILIB_KMEM_TYPE_PAGE,PCILIB_NUMBER_OF_LOCK_PAGES,PCILIB_KMEM_PAGE_SIZE,0,PCILIB_KMEM_USE(PCILIB_KMEM_USE_MUTEXES,0),PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_PERSISTENT); + + if (!handle) { + pcilib_error("Allocation of kernel memory for mutexes has failed"); + return 1; + } + + ctx->locks_handle=handle; + reused = pcilib_kmem_is_reused(ctx, handle); +//#define DEBUG_REUSE +#ifdef DEBUG_REUSE +reused=0; +#endif + if ((reused & PCILIB_KMEM_REUSE_REUSED) == 0) { + pcilib_register_t i; + + if (reused & PCILIB_KMEM_REUSE_PARTIAL) { + pcilib_error("Inconsistent software registers are found (only part of required buffers is available)"); + pcilib_clean_all_locks(ctx); + return 1; + } + for(i=0;ihandle,LOCK_UN))==-1) pcilib_warning("could not remove lock correctly on /dev/fpga0"); + + return 0; +} diff --git a/pcilib/locking.h b/pcilib/locking.h new file mode 100644 index 0000000..f7570f6 --- /dev/null +++ b/pcilib/locking.h @@ -0,0 +1,44 @@ +/** + * @file lock_global.h + * @brief this file is the header file for functions that touch all locks allocated for software registers. + * @details for more details about implementation choice, please read the file lock.h + */ +#define _XOPEN_SOURCE 700 + +#ifndef _LOCKING_ +#define _LOCKING_ + +#include + +/** number of maximum locks*/ +#define PCILIB_MAX_NUMBER_LOCKS 64 + +/**size of one lock, determine so the size of the protocol_name in the way locks are registered. 40 bytes are necessary for the mutex structure, so we have a protocol name of length LOCK_SIZE-40*/ +#define PCILIB_LOCK_SIZE 128 + +#define PCILIB_LOCKS_PER_PAGE PCILIB_KMEM_PAGE_SIZE/PCILIB_LOCK_SIZE + +#define PCILIB_NUMBER_OF_LOCK_PAGES (PCILIB_MAX_NUMBER_LOCKS*PCILIB_LOCK_SIZE)/PCILIB_KMEM_PAGE_SIZE + + +/** +* new type to define a semaphore. It was made to differentiate from the library type. +*/ +typedef pthread_mutex_t pcilib_lock_t; + +/** + * this function destroy all locks created + *@param[in] ctx, the pcilib_t running + */ +void pcilib_clean_all_locks(pcilib_t* ctx); + +/** +* this function initialize the kmem pages containing locks +*@param[in] ctx the pcilib_t running +*/ +int pcilib_init_locking(pcilib_t* ctx, ...); + + +void pcilib_free_all_locks(pcilib_t* ctx); + +#endif /* _LOCK_GLOBAL_ */ diff --git a/pcilib/pci.c b/pcilib/pci.c index 3a18ccd..c7b86e8 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -1,4 +1,5 @@ //#define PCILIB_FILE_IO +#define _XOPEN_SOURCE 700 #define _BSD_SOURCE #define _POSIX_C_SOURCE 200809L @@ -24,6 +25,7 @@ #include "model.h" #include "plugin.h" #include "bar.h" +#include "locking.h" static int pcilib_detect_model(pcilib_t *ctx, const char *model) { int i, j; @@ -159,6 +161,12 @@ pcilib_t *pcilib_open(const char *device, const char *model) { ctx->model_info.protocols = ctx->protocols; ctx->model_info.ranges = ctx->ranges; + err=pcilib_init_locking(ctx); + if (err) { + pcilib_error("Error (%i) initializing locking\n", err); + pcilib_close(ctx); + return NULL; + } err = pcilib_init_register_banks(ctx); if (err) { diff --git a/pcilib/pci.h b/pcilib/pci.h index d176caf..a7b3d50 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -69,7 +69,7 @@ struct pcilib_s { pcilib_register_bank_context_t *bank_ctx[PCILIB_MAX_REGISTER_BANKS]; /**< Contexts for registers banks if required by register protocol */ pcilib_dma_context_t *dma_ctx; /**< DMA context */ pcilib_context_t *event_ctx; /**< Implmentation context */ - + void* locks_handle; /**< adress of the kernel memory use for locks from user space*/ #ifdef PCILIB_FILE_IO int file_io_handle; #endif /* PCILIB_FILE_IO */ -- cgit v1.2.3 From fe821c4f1b85d2a2d358da098f85327d41212dc3 Mon Sep 17 00:00:00 2001 From: zilio nicolas Date: Tue, 7 Jul 2015 15:38:14 +0200 Subject: modified for last remarks --- pcilib/lock.c | 40 ++++++++++++++++++++++------------------ pcilib/locking.c | 4 ++-- 2 files changed, 24 insertions(+), 20 deletions(-) (limited to 'pcilib') diff --git a/pcilib/lock.c b/pcilib/lock.c index 8715d21..b99ecfc 100644 --- a/pcilib/lock.c +++ b/pcilib/lock.c @@ -6,7 +6,7 @@ #include "error.h" #include "lock.h" #include "pci.h" - +#include /* * this function will take the lock for the semaphore pointed by semId */ @@ -18,32 +18,32 @@ void pcilib_lock(pcilib_lock_t *lock_ctx, pcilib_lock_flags_t flags, ...){ if(flags & MUTEX_LOCK){ err=pthread_mutex_lock(lock_ctx);/**< we try to lock here*/ - if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, errno %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); /** if the lock haven't been acquired and errno==EOWNERDEAD, it means the previous application that got the lock crashed, we have to remake the lock "consistent" so*/ else if(errno==EOWNERDEAD){ pthread_mutex_consistent(lock_ctx); pthread_mutex_lock(lock_ctx); - if(err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + if(err!=0) pcilib_error("can't acquire lock %s, errno %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); } } else if(flags & MUTEX_TRYLOCK){ err=pthread_mutex_trylock(lock_ctx);/**< we try to lock here*/ - if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, errno %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); else if(errno==EOWNERDEAD){ pthread_mutex_consistent(lock_ctx); pthread_mutex_lock(lock_ctx); - if(err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + if(err!=0) pcilib_error("can't acquire lock %s, errno %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); } } else if(flags & MUTEX_TIMEDLOCK){ time=va_arg(pa,struct timespec*); va_end(pa); err=pthread_mutex_timedlock(lock_ctx, time);/**< we try to lock here*/ - if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); + if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, errni %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); else if(errno==EOWNERDEAD){ pthread_mutex_consistent(lock_ctx); pthread_mutex_timedlock(lock_ctx, time); - if(err!=0) pcilib_error("can't acquire lock %s, error %i\n",(char*)(lock_ctx+sizeof(pcilib_lock_t)), errno); + if(err!=0) pcilib_error("can't acquire lock %s, errno %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)), errno); } } else pcilib_error("wrong flag for pcilib_lock"); @@ -54,7 +54,7 @@ void pcilib_lock(pcilib_lock_t *lock_ctx, pcilib_lock_flags_t flags, ...){ */ void pcilib_unlock(pcilib_lock_t* lock_ctx){ int err; - if((err=pthread_mutex_unlock(lock_ctx))!=0) pcilib_error("can't unlock semaphore\n"); + if((err=pthread_mutex_unlock(lock_ctx))!=0) pcilib_error("can't unlock mutex: errno %i",errno); } /** @@ -71,21 +71,25 @@ pcilib_lock_t* pcilib_init_lock(pcilib_t *ctx, char* lock_id, ...){ va_list pa; va_start(pa,lock_id); + char* temp; + temp=malloc((strlen(lock_id)+strlen("bank_register_"))*sizeof(char)); + sprintf(temp,"bank_register_%s",lock_id); + pcilib_lock_init_flags_t flag; flag=va_arg(pa,pcilib_lock_init_flags_t); va_end(pa); - if(strlen(lock_id)>PCILIB_LOCK_SIZE-sizeof(pcilib_lock_t)) pcilib_error("the entered protocol name is too long"); + if(strlen(temp)>PCILIB_LOCK_SIZE-sizeof(pcilib_lock_t)) pcilib_error("the entered protocol name is too long"); if(((PCILIB_MAX_NUMBER_LOCKS*PCILIB_LOCK_SIZE)%PCILIB_KMEM_PAGE_SIZE)!=0) pcilib_error("PCILIB_MAX_NUMBER_LOCKS*PCILIB_LOCK_SIZE should be a multiple of kmem page size"); addr=pcilib_kmem_get_block_ua(ctx,ctx->locks_handle,0); - if(flag & LOCK_INIT) pcilib_lock((pcilib_lock_t*)addr,MUTEX_LOCK); + if((flag & LOCK_INIT)==0) pcilib_lock((pcilib_lock_t*)addr,MUTEX_LOCK); /* we search for the given lock if it was already initialized*/ for(j=0;jlocks_handle,j); while((*(char*)(locks_addr+i*PCILIB_LOCK_SIZE+sizeof(pcilib_lock_t))!=0) && (ilocks_handle=handle; reused = pcilib_kmem_is_reused(ctx, handle); -//#define DEBUG_REUSE + #define DEBUG_REUSE #ifdef DEBUG_REUSE reused=0; #endif @@ -57,7 +57,7 @@ reused=0; pcilib_register_t i; if (reused & PCILIB_KMEM_REUSE_PARTIAL) { - pcilib_error("Inconsistent software registers are found (only part of required buffers is available)"); + pcilib_error("Inconsistent memory for locks was found (only part of required buffers is available)"); pcilib_clean_all_locks(ctx); return 1; } -- cgit v1.2.3 From edd5ccf24c146915ee475bd223e2ad695520a241 Mon Sep 17 00:00:00 2001 From: zilio nicolas Date: Fri, 10 Jul 2015 10:52:06 +0200 Subject: last modification+comments update --- pcilib/lock.c | 32 ++++++++++++++------------------ pcilib/lock.h | 25 +++++++++++++++++-------- pcilib/locking.c | 15 +++++++++++---- pcilib/locking.h | 7 ++++++- 4 files changed, 48 insertions(+), 31 deletions(-) (limited to 'pcilib') diff --git a/pcilib/lock.c b/pcilib/lock.c index b99ecfc..b92b11d 100644 --- a/pcilib/lock.c +++ b/pcilib/lock.c @@ -7,6 +7,7 @@ #include "lock.h" #include "pci.h" #include + /* * this function will take the lock for the semaphore pointed by semId */ @@ -21,6 +22,7 @@ void pcilib_lock(pcilib_lock_t *lock_ctx, pcilib_lock_flags_t flags, ...){ if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, errno %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); /** if the lock haven't been acquired and errno==EOWNERDEAD, it means the previous application that got the lock crashed, we have to remake the lock "consistent" so*/ else if(errno==EOWNERDEAD){ + /* one question is "is pthread_mutex_consistent protected in case we call twice it?", it seems to not make any importance in fact regarding man pages, but we have to survey it in future applications*/ pthread_mutex_consistent(lock_ctx); pthread_mutex_lock(lock_ctx); if(err!=0) pcilib_error("can't acquire lock %s, errno %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); @@ -31,7 +33,7 @@ void pcilib_lock(pcilib_lock_t *lock_ctx, pcilib_lock_flags_t flags, ...){ if(errno!=EOWNERDEAD && err!=0) pcilib_error("can't acquire lock %s, errno %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); else if(errno==EOWNERDEAD){ pthread_mutex_consistent(lock_ctx); - pthread_mutex_lock(lock_ctx); + pthread_mutex_trylock(lock_ctx); if(err!=0) pcilib_error("can't acquire lock %s, errno %i",(char*)(lock_ctx+sizeof(pcilib_lock_t)),errno); } } @@ -58,43 +60,37 @@ void pcilib_unlock(pcilib_lock_t* lock_ctx){ } /** - * pcilib_init_lock * this function initialize a new semaphore in the kernel if it's not already initialized given the key that permits to differentiate semaphores, and then return the integer that points to the semaphore that have been initialized or to a previously already initialized semaphore - * @param[out] lock_ctx the pointer that will points to the semaphore for other functions - * @param[in] keysem the integer that permits to define to what the semaphore is attached */ -pcilib_lock_t* pcilib_init_lock(pcilib_t *ctx, char* lock_id, ...){ +pcilib_lock_t* pcilib_init_lock(pcilib_t *ctx, pcilib_lock_init_flags_t flag, char* lock_id, ...){ int err; pthread_mutexattr_t attr; int i,j; void* addr,*locks_addr; + char buffer[PCILIB_LOCK_SIZE-sizeof(pcilib_lock_t)]; + /* here lock_id is the format string for vsprintf, the lock name will so be put in adding arguments*/ va_list pa; va_start(pa,lock_id); - - char* temp; - temp=malloc((strlen(lock_id)+strlen("bank_register_"))*sizeof(char)); - sprintf(temp,"bank_register_%s",lock_id); - - pcilib_lock_init_flags_t flag; - flag=va_arg(pa,pcilib_lock_init_flags_t); + err=vsprintf(buffer,lock_id,pa); va_end(pa); - if(strlen(temp)>PCILIB_LOCK_SIZE-sizeof(pcilib_lock_t)) pcilib_error("the entered protocol name is too long"); + if(err<0) pcilib_error("error in obtaining the lock name"); if(((PCILIB_MAX_NUMBER_LOCKS*PCILIB_LOCK_SIZE)%PCILIB_KMEM_PAGE_SIZE)!=0) pcilib_error("PCILIB_MAX_NUMBER_LOCKS*PCILIB_LOCK_SIZE should be a multiple of kmem page size"); addr=pcilib_kmem_get_block_ua(ctx,ctx->locks_handle,0); - if((flag & LOCK_INIT)==0) pcilib_lock((pcilib_lock_t*)addr,MUTEX_LOCK); + if((flag & PCILIB_NO_LOCK)==0) pcilib_lock((pcilib_lock_t*)addr,MUTEX_LOCK); /* we search for the given lock if it was already initialized*/ for(j=0;jlocks_handle,j); while((*(char*)(locks_addr+i*PCILIB_LOCK_SIZE+sizeof(pcilib_lock_t))!=0) && (ilocks_handle,i); for(j=0;jlocks_handle,PCILIB_KMEM_FLAG_REUSE); @@ -38,8 +42,9 @@ int pcilib_init_locking(pcilib_t* ctx, ...){ int err; pcilib_kmem_reuse_state_t reused; - + /* we flock() to make sure to not have two initialization in the same time (possible long time to init)*/ if((err=flock(ctx->handle,LOCK_EX))==-1) pcilib_warning("can't get flock on /dev/fpga0"); + handle=pcilib_alloc_kernel_memory(ctx,PCILIB_KMEM_TYPE_PAGE,PCILIB_NUMBER_OF_LOCK_PAGES,PCILIB_KMEM_PAGE_SIZE,0,PCILIB_KMEM_USE(PCILIB_KMEM_USE_MUTEXES,0),PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_PERSISTENT); if (!handle) { @@ -49,10 +54,11 @@ int pcilib_init_locking(pcilib_t* ctx, ...){ ctx->locks_handle=handle; reused = pcilib_kmem_is_reused(ctx, handle); - #define DEBUG_REUSE +//#define DEBUG_REUSE #ifdef DEBUG_REUSE reused=0; #endif +/* verification about the handling memory got, first use or not, and integrity*/ if ((reused & PCILIB_KMEM_REUSE_REUSED) == 0) { pcilib_register_t i; @@ -61,10 +67,11 @@ reused=0; pcilib_clean_all_locks(ctx); return 1; } + /* if we get here so this is the first initialization (after some free or new), we so set kernel pages to 0 and initialize then the first lock that will be used when we create other locks*/ for(i=0;i Date: Fri, 24 Jul 2015 13:09:59 +0200 Subject: Make pcilib_streaming_action_t public --- pcilib/event.h | 11 ----------- pcilib/pcilib.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'pcilib') diff --git a/pcilib/event.h b/pcilib/event.h index d2b9793..f14abeb 100644 --- a/pcilib/event.h +++ b/pcilib/event.h @@ -45,17 +45,6 @@ typedef struct { const char *description; } pcilib_event_data_type_description_t; -typedef enum { - PCILIB_STREAMING_STOP = 0, /**< stop streaming */ - PCILIB_STREAMING_CONTINUE = 1, /**< wait the default DMA timeout for a new data */ - PCILIB_STREAMING_WAIT = 2, /**< wait the specified timeout for a new data */ - PCILIB_STREAMING_CHECK = 3, /**< do not wait for the data, bail out imideatly if no data ready */ - PCILIB_STREAMING_FAIL = 4, /**< fail if data is not available on timeout */ - PCILIB_STREAMING_REQ_FRAGMENT = 5, /**< only fragment of a packet is read, wait for next fragment and fail if no data during DMA timeout */ - PCILIB_STREAMING_REQ_PACKET = 6, /**< wait for next packet and fail if no data during the specified timeout */ - PCILIB_STREAMING_TIMEOUT_MASK = 3 /**< mask specifying all timeout modes */ -} pcilib_streaming_action_t; - /* * get_data: This call is used by get_data and copy_data functions of public * interface. When copy_data is the caller, the data parameter will be passed. diff --git a/pcilib/pcilib.h b/pcilib/pcilib.h index 8a43bfb..01f3324 100644 --- a/pcilib/pcilib.h +++ b/pcilib/pcilib.h @@ -62,6 +62,17 @@ typedef enum { PCILIB_DMA_FLAG_IGNORE_ERRORS = 16 /**< do not crash on errors, but return appropriate error codes */ } pcilib_dma_flags_t; +typedef enum { + PCILIB_STREAMING_STOP = 0, /**< stop streaming */ + PCILIB_STREAMING_CONTINUE = 1, /**< wait the default DMA timeout for a new data */ + PCILIB_STREAMING_WAIT = 2, /**< wait the specified timeout for a new data */ + PCILIB_STREAMING_CHECK = 3, /**< do not wait for the data, bail out imideatly if no data ready */ + PCILIB_STREAMING_FAIL = 4, /**< fail if data is not available on timeout */ + PCILIB_STREAMING_REQ_FRAGMENT = 5, /**< only fragment of a packet is read, wait for next fragment and fail if no data during DMA timeout */ + PCILIB_STREAMING_REQ_PACKET = 6, /**< wait for next packet and fail if no data during the specified timeout */ + PCILIB_STREAMING_TIMEOUT_MASK = 3 /**< mask specifying all timeout modes */ +} pcilib_streaming_action_t; + typedef enum { PCILIB_EVENT_FLAGS_DEFAULT = 0, PCILIB_EVENT_FLAG_RAW_DATA_ONLY = 1, /**< Do not parse data, just read raw and pass it to rawdata callback. If passed to rawdata callback, idicates the data is not identified as event (most probably just padding) */ -- cgit v1.2.3 From 39417c2c0386a971a6973a6aaf779e82c9298020 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 5 Aug 2015 15:14:41 +0200 Subject: Fix error-checking typo in kmem --- pcilib/kmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pcilib') diff --git a/pcilib/kmem.c b/pcilib/kmem.c index 2ff674f..469c63a 100644 --- a/pcilib/kmem.c +++ b/pcilib/kmem.c @@ -81,8 +81,8 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type memset(kbuf, 0, sizeof(pcilib_kmem_list_t) + nmemb * sizeof(pcilib_kmem_addr_t)); err = pcilib_lock(ctx->locks.mmap); - if (!err) { - pcilib_error("Error acquiring mmap lock"); + if (err) { + pcilib_error("Error (%i) acquiring mmap lock", err); return NULL; } -- cgit v1.2.3 From f2e47ba725cc7ba477d3a788addc974f2b18d36f Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 5 Aug 2015 15:30:41 +0200 Subject: Protect mmaping BARs as well --- pcilib/bar.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'pcilib') diff --git a/pcilib/bar.c b/pcilib/bar.c index ce04f6d..17828a8 100644 --- a/pcilib/bar.c +++ b/pcilib/bar.c @@ -73,21 +73,29 @@ int pcilib_detect_address(pcilib_t *ctx, pcilib_bar_t *bar, uintptr_t *addr, siz void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) { void *res; - int ret; + int err, ret; const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); if (!board_info) return NULL; - + if (ctx->bar_space[bar]) return ctx->bar_space[bar]; - + + err = pcilib_lock(ctx->locks.mmap); + if (err) { + pcilib_error("Error (%i) acquiring mmap lock", err); + return NULL; + } + ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_PCI ); if (ret) { + pcilib_unlock(ctx->locks.mmap); pcilib_error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed", bar); return NULL; } ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_AREA, PCIDRIVER_BAR0 + bar ); if (ret) { + pcilib_unlock(ctx->locks.mmap); pcilib_error("PCIDRIVER_IOC_MMAP_AREA ioctl have failed for bank %i", bar); return NULL; } @@ -98,12 +106,13 @@ void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) { #else res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 ); #endif + pcilib_unlock(ctx->locks.mmap); + if ((!res)||(res == MAP_FAILED)) { pcilib_error("Failed to mmap data bank %i", bar); return NULL; } - return res; } -- cgit v1.2.3 From 7c5897933f4f64594602b2e38264af705c061754 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 5 Aug 2015 18:11:59 +0200 Subject: Use global locks to protect kmem allocation to prevent race while allocating simmultaneously locking kmem pages and any other type of kmem --- pcilib/bar.c | 9 +++++---- pcilib/kmem.c | 6 +++--- pcilib/lock.c | 5 ++++- pcilib/locking.c | 6 +----- pcilib/locking.h | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) (limited to 'pcilib') diff --git a/pcilib/bar.c b/pcilib/bar.c index 17828a8..418f864 100644 --- a/pcilib/bar.c +++ b/pcilib/bar.c @@ -80,7 +80,7 @@ void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) { if (ctx->bar_space[bar]) return ctx->bar_space[bar]; - err = pcilib_lock(ctx->locks.mmap); + err = pcilib_lock_global(ctx); if (err) { pcilib_error("Error (%i) acquiring mmap lock", err); return NULL; @@ -88,14 +88,14 @@ void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) { ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_PCI ); if (ret) { - pcilib_unlock(ctx->locks.mmap); + pcilib_unlock_global(ctx); pcilib_error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed", bar); return NULL; } ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_AREA, PCIDRIVER_BAR0 + bar ); if (ret) { - pcilib_unlock(ctx->locks.mmap); + pcilib_unlock_global(ctx); pcilib_error("PCIDRIVER_IOC_MMAP_AREA ioctl have failed for bank %i", bar); return NULL; } @@ -106,7 +106,8 @@ void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) { #else res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 ); #endif - pcilib_unlock(ctx->locks.mmap); + + pcilib_unlock_global(ctx); if ((!res)||(res == MAP_FAILED)) { pcilib_error("Failed to mmap data bank %i", bar); diff --git a/pcilib/kmem.c b/pcilib/kmem.c index 469c63a..b1d2c5c 100644 --- a/pcilib/kmem.c +++ b/pcilib/kmem.c @@ -80,7 +80,7 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type memset(kbuf, 0, sizeof(pcilib_kmem_list_t) + nmemb * sizeof(pcilib_kmem_addr_t)); - err = pcilib_lock(ctx->locks.mmap); + err = pcilib_lock_global(ctx); if (err) { pcilib_error("Error (%i) acquiring mmap lock", err); return NULL; @@ -88,7 +88,7 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_KMEM ); if (ret) { - pcilib_unlock(ctx->locks.mmap); + pcilib_unlock_global(ctx); pcilib_error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed"); return NULL; } @@ -176,7 +176,7 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type kbuf->buf.blocks[i].mmap_offset = kh.pa & ctx->page_mask; } - pcilib_unlock(ctx->locks.mmap); + pcilib_unlock_global(ctx); //This is possible in the case of error (nothing is allocated yet) or if buffers are not reused diff --git a/pcilib/lock.c b/pcilib/lock.c index f1cbc56..13e363a 100644 --- a/pcilib/lock.c +++ b/pcilib/lock.c @@ -140,7 +140,10 @@ const char *pcilib_lock_get_name(pcilib_lock_t *lock) { int pcilib_lock_custom(pcilib_lock_t *lock, pcilib_lock_flags_t flags, pcilib_timeout_t timeout) { int err; - if (!lock) return 0; + if (!lock) { + pcilib_error("The null lock pointer is passed to lock function"); + return PCILIB_ERROR_INVALID_ARGUMENT; + } struct timespec tm; diff --git a/pcilib/locking.c b/pcilib/locking.c index ffd05ce..7a32605 100644 --- a/pcilib/locking.c +++ b/pcilib/locking.c @@ -46,11 +46,10 @@ int pcilib_init_locking(pcilib_t* ctx) { } ctx->locks.locking = pcilib_get_lock(ctx, PCILIB_LOCK_FLAG_UNLOCKED, "locking"); - ctx->locks.mmap = pcilib_get_lock(ctx, PCILIB_LOCK_FLAG_UNLOCKED, "mmap"); pcilib_unlock_global(ctx); - if ((!ctx->locks.locking)||(!ctx->locks.mmap)) { + if ((!ctx->locks.locking)) { pcilib_error("Locking subsystem has failed to initialized mandatory global locks"); return PCILIB_ERROR_FAILED; } @@ -62,9 +61,6 @@ int pcilib_init_locking(pcilib_t* ctx) { * this functions destroy all locks and then free the kernel memory allocated for them */ void pcilib_free_locking(pcilib_t *ctx) { - if (ctx->locks.mmap) - pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, ctx->locks.mmap); - if (ctx->locks.locking) pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, ctx->locks.locking); diff --git a/pcilib/locking.h b/pcilib/locking.h index ae2f368..ccacd63 100644 --- a/pcilib/locking.h +++ b/pcilib/locking.h @@ -20,7 +20,7 @@ typedef struct pcilib_locking_s pcilib_locking_t; struct pcilib_locking_s { pcilib_kmem_handle_t *kmem; /**< kmem used to store mutexes */ pcilib_lock_t *locking; /**< lock used while intializing other locks */ - pcilib_lock_t *mmap; /**< lock used to protect mmap operation */ +// pcilib_lock_t *mmap; /**< lock used to protect mmap operation */ }; #ifdef __cplusplus -- cgit v1.2.3 From 6ac0cf129270aef989785e3fbc84abc238a29e92 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 5 Aug 2015 19:13:07 +0200 Subject: Read model from environmental variable if defined --- pcilib/pci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'pcilib') diff --git a/pcilib/pci.c b/pcilib/pci.c index 512e891..6078a6e 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -108,6 +108,9 @@ pcilib_t *pcilib_open(const char *device, const char *model) { size_t i; pcilib_t *ctx = malloc(sizeof(pcilib_t)); + if (!model) + model = getenv("PCILIB_MODEL"); + if (ctx) { memset(ctx, 0, sizeof(pcilib_t)); ctx->pci_cfg_space_fd = -1; -- cgit v1.2.3 From 98fa817f608756b39223ed785b85dd5cace9b096 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 5 Aug 2015 19:19:57 +0200 Subject: Install locking-related headers --- pcilib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pcilib') diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index 0bf0e66..79b15c2 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -16,6 +16,6 @@ install(FILES pcilib.h DESTINATION include ) -install(FILES bar.h kmem.h bank.h register.h dma.h event.h model.h error.h debug.h env.h tools.h export.h version.h +install(FILES bar.h kmem.h locking.h lock.h bank.h register.h dma.h event.h model.h error.h debug.h env.h tools.h export.h version.h DESTINATION include/pcilib ) -- cgit v1.2.3 From 63bc897c9444b364b0364bfd04a0c87d9fe29307 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Thu, 6 Aug 2015 01:13:17 +0200 Subject: Provide pcilib_try_lock call --- pcilib/lock.c | 4 ++++ pcilib/lock.h | 7 +++++++ 2 files changed, 11 insertions(+) (limited to 'pcilib') diff --git a/pcilib/lock.c b/pcilib/lock.c index 13e363a..9045ffa 100644 --- a/pcilib/lock.c +++ b/pcilib/lock.c @@ -190,6 +190,10 @@ int pcilib_lock(pcilib_lock_t* lock) { return pcilib_lock_custom(lock, PCILIB_LOCK_FLAGS_DEFAULT, PCILIB_TIMEOUT_INFINITE); } +int pcilib_try_lock(pcilib_lock_t* lock) { + return pcilib_lock_custom(lock, PCILIB_LOCK_FLAGS_DEFAULT, PCILIB_TIMEOUT_IMMEDIATE); +} + /** * this function will unlock the semaphore pointed by lock_ctx. */ diff --git a/pcilib/lock.h b/pcilib/lock.h index 8e1017a..9ffe4cf 100644 --- a/pcilib/lock.h +++ b/pcilib/lock.h @@ -86,6 +86,13 @@ int pcilib_lock_custom(pcilib_lock_t* lock, pcilib_lock_flags_t flags, pcilib_ti */ int pcilib_lock(pcilib_lock_t* lock); +/** + * this function will try to take a lock for the mutex pointed by lock + * @param[in] lock the pointer to the mutex + */ +int pcilib_try_lock(pcilib_lock_t* lock); + + /** * this function will unlock the lock pointed by lock * @param[in] lock the integer that points to the semaphore -- cgit v1.2.3 From 8b8a2bee0bce0bc9cc78d43f236c6a3d8a0bd2e4 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Thu, 6 Aug 2015 02:27:54 +0200 Subject: Fix handling of inconsistent mutexes --- pcilib/lock.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'pcilib') diff --git a/pcilib/lock.c b/pcilib/lock.c index 9045ffa..03a2377 100644 --- a/pcilib/lock.c +++ b/pcilib/lock.c @@ -174,8 +174,9 @@ int pcilib_lock_custom(pcilib_lock_t *lock, pcilib_lock_flags_t flags, pcilib_ti err = pthread_mutex_consistent(&lock->mutex); if (err) { pcilib_error("Failed to mark mutex as consistent, errno %i", err); + break; } - break; + return 0; case ETIMEDOUT: case EBUSY: return PCILIB_ERROR_TIMEOUT; @@ -203,6 +204,13 @@ void pcilib_unlock(pcilib_lock_t *lock) { if (!lock) return; - if ((err = pthread_mutex_unlock(&lock->mutex)) != 0) - pcilib_error("Can't unlock mutex, errno %i", err); + if ((err = pthread_mutex_unlock(&lock->mutex)) != 0) { + switch (err) { + case EPERM: + pcilib_error("Trying to unlock not locked mutex (%s) or the mutex which was locked by a different thread", lock->name); + break; + default: + pcilib_error("Can't unlock mutex, errno %i", err); + } + } } -- cgit v1.2.3 From d60dd48eec0ef5d7bf2feca9b3f06374a2f444aa Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Thu, 6 Aug 2015 04:24:58 +0200 Subject: Protect access to the DMA engine with locks --- pcilib/dma.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- pcilib/pci.c | 8 ++++++++ pcilib/pci.h | 3 +++ 3 files changed, 68 insertions(+), 5 deletions(-) (limited to 'pcilib') diff --git a/pcilib/dma.c b/pcilib/dma.c index f6b8053..be02c21 100644 --- a/pcilib/dma.c +++ b/pcilib/dma.c @@ -61,8 +61,11 @@ pcilib_dma_engine_t pcilib_add_dma_engine(pcilib_t *ctx, pcilib_dma_engine_descr int pcilib_init_dma(pcilib_t *ctx) { int err; pcilib_dma_context_t *dma_ctx = NULL; + const pcilib_dma_description_t *info = &ctx->dma; const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_dma_engine_t dma; + if (ctx->dma_ctx) return 0; @@ -86,6 +89,24 @@ int pcilib_init_dma(pcilib_t *ctx) { } if (dma_ctx) { + for (dma = 0; info->engines[dma].addr_bits; dma++) { + if (info->engines[dma].direction&PCILIB_DMA_FROM_DEVICE) { + ctx->dma_rlock[dma] = pcilib_get_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, "dma%ir/%s", info->engines[dma].addr, info->name); + if (!ctx->dma_rlock[dma]) break; + } + if (info->engines[dma].direction&PCILIB_DMA_TO_DEVICE) { + ctx->dma_wlock[dma] = pcilib_get_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, "dma%iw/%s", info->engines[dma].addr, info->name); + if (!ctx->dma_wlock[dma]) break; + } + } + + if (info->engines[dma].addr_bits) { + if (ctx->dma.api->free) + ctx->dma.api->free(dma_ctx); + pcilib_error("Failed to intialize DMA locks"); + return PCILIB_ERROR_FAILED; + } + dma_ctx->pcilib = ctx; // DS: parameters? ctx->dma_ctx = dma_ctx; @@ -105,11 +126,11 @@ int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t pcilib_error("DMA Engine is not configured in the current model"); return PCILIB_ERROR_NOTAVAILABLE; } - + if (!info->api->start_dma) { return 0; } - + return info->api->start_dma(ctx->dma_ctx, dma, flags); } @@ -201,6 +222,7 @@ static int pcilib_dma_skip_callback(void *arg, pcilib_dma_flags_t flags, size_t } int pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr) { + int err; const pcilib_dma_description_t *info = pcilib_get_dma_description(ctx); if (!info) { pcilib_error("DMA is not supported by the device"); @@ -228,7 +250,21 @@ int pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, si return PCILIB_ERROR_NOTSUPPORTED; } - return info->api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr); + err = pcilib_try_lock(ctx->dma_rlock[dma]); + if (err) { + if ((err == PCILIB_ERROR_BUSY)||(err == PCILIB_ERROR_TIMEOUT)) + pcilib_error("DMA engine (%i) is busy", dma); + else + pcilib_error("Error (%i) locking DMA engine (%i)", err, dma); + + return err; + } + + err = info->api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr); + + pcilib_unlock(ctx->dma_rlock[dma]); + + return err; } int pcilib_read_dma_custom(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *read_bytes) { @@ -278,6 +314,8 @@ int pcilib_skip_dma(pcilib_t *ctx, pcilib_dma_engine_t dma) { int pcilib_push_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *buf, size_t *written) { + int err; + const pcilib_dma_description_t *info = pcilib_get_dma_description(ctx); if (!info) { pcilib_error("DMA is not supported by the device"); @@ -304,8 +342,22 @@ int pcilib_push_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size pcilib_error("The selected engine (%i) is C2S-only and does not support writes", dma); return PCILIB_ERROR_NOTSUPPORTED; } - - return info->api->push(ctx->dma_ctx, dma, addr, size, flags, timeout, buf, written); + + err = pcilib_try_lock(ctx->dma_wlock[dma]); + if (err) { + if (err == PCILIB_ERROR_BUSY) + pcilib_error("DMA engine (%i) is busy", dma); + else + pcilib_error("Error (%i) locking DMA engine (%i)", err, dma); + + return err; + } + + err = info->api->push(ctx->dma_ctx, dma, addr, size, flags, timeout, buf, written); + + pcilib_unlock(ctx->dma_wlock[dma]); + + return err; } diff --git a/pcilib/pci.c b/pcilib/pci.c index 6078a6e..4351c1e 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -337,6 +337,7 @@ void pcilib_close(pcilib_t *ctx) { pcilib_bar_t i; if (ctx) { + pcilib_dma_engine_t dma; const pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); const pcilib_event_api_description_t *eapi = model_info->api; const pcilib_dma_api_description_t *dapi = ctx->dma.api; @@ -344,6 +345,13 @@ void pcilib_close(pcilib_t *ctx) { if ((eapi)&&(eapi->free)) eapi->free(ctx->event_ctx); if ((dapi)&&(dapi->free)) dapi->free(ctx->dma_ctx); + for (dma = 0; dma < PCILIB_MAX_DMA_ENGINES; dma++) { + if (ctx->dma_rlock[dma]) + pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, ctx->dma_rlock[dma]); + if (ctx->dma_wlock[dma]) + pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, ctx->dma_wlock[dma]); + } + pcilib_free_register_banks(ctx); if (ctx->register_ctx) diff --git a/pcilib/pci.h b/pcilib/pci.h index c97f753..51bb352 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -71,6 +71,9 @@ struct pcilib_s { pcilib_dma_context_t *dma_ctx; /**< DMA context */ pcilib_context_t *event_ctx; /**< Implmentation context */ + pcilib_lock_t *dma_rlock[PCILIB_MAX_DMA_ENGINES]; /**< Per-engine locks to serialize streaming and read operations */ + pcilib_lock_t *dma_wlock[PCILIB_MAX_DMA_ENGINES]; /**< Per-engine locks to serialize write operations */ + struct pcilib_locking_s locks; /**< Context of locking subsystem */ #ifdef PCILIB_FILE_IO -- cgit v1.2.3 From 81de1a078b5c54c81b869564d33ed3e025bb695e Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Thu, 6 Aug 2015 16:46:05 +0200 Subject: Fix compilation of the driver --- pcilib/kmem.h | 2 -- pcilib/locking.c | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'pcilib') diff --git a/pcilib/kmem.h b/pcilib/kmem.h index 9cd1971..3dff625 100644 --- a/pcilib/kmem.h +++ b/pcilib/kmem.h @@ -1,8 +1,6 @@ #ifndef _PCILIB_KMEM_H #define _PCILIB_KMEM_H -#include - typedef struct pcilib_s pcilib_t; typedef struct pcilib_kmem_list_s pcilib_kmem_list_t; diff --git a/pcilib/locking.c b/pcilib/locking.c index 7a32605..f384ca4 100644 --- a/pcilib/locking.c +++ b/pcilib/locking.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "locking.h" -- cgit v1.2.3 From 55783eb24e983786056f4ba7925aa23fca13c79e Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 12 Aug 2015 20:25:35 +0200 Subject: Fix support of older systems: Remove C11 derective and add rt library to the link list --- pcilib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pcilib') diff --git a/pcilib/CMakeLists.txt b/pcilib/CMakeLists.txt index 79b15c2..be59cb7 100644 --- a/pcilib/CMakeLists.txt +++ b/pcilib/CMakeLists.txt @@ -5,7 +5,7 @@ include_directories( set(HEADERS pcilib.h pci.h export.h bar.h fifo.h model.h bank.h register.h kmem.h irq.h locking.h lock.h dma.h event.h plugin.h tools.h error.h debug.h env.h version.h config.h) add_library(pcilib SHARED pci.c export.c bar.c fifo.c model.c bank.c register.c kmem.c irq.c locking.c lock.c dma.c event.c plugin.c tools.c error.c debug.c env.c ) -target_link_libraries(pcilib dma protocols ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS}) +target_link_libraries(pcilib dma protocols ${CMAKE_THREAD_LIBS_INIT} ${UFODECODE_LIBRARIES} ${CMAKE_DL_LIBS} ${EXTRA_SYSTEM_LIBS}) add_dependencies(pcilib dma protocols) install(TARGETS pcilib -- cgit v1.2.3 From 5001621745651443d3825a30a92897cac7f1ec53 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 12 Aug 2015 20:57:37 +0200 Subject: Do not fail if PCI configuration is not fully available to unprivileged user --- pcilib/pci.c | 11 ++++++++--- pcilib/pci.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'pcilib') diff --git a/pcilib/pci.c b/pcilib/pci.c index 4351c1e..62ac92d 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -425,11 +425,16 @@ static int pcilib_update_pci_configuration_space(pcilib_t *ctx) { } size = read(ctx->pci_cfg_space_fd, ctx->pci_cfg_space_cache, 256); - if (size != 256) { - pcilib_error("Failed to read PCI configuration from sysfs"); + if (size < 64) { + if (size <= 0) + pcilib_error("Failed to read PCI configuration from sysfs, errno: %i", errno); + else + pcilib_error("Failed to read PCI configuration from sysfs, only %zu bytes read (expected at least 64)", size); return PCILIB_ERROR_FAILED; } + ctx->pci_cfg_space_size = size; + return 0; } @@ -452,7 +457,7 @@ static uint32_t *pcilib_get_pci_capabilities(pcilib_t *ctx, int cap_id) { cap = ctx->pci_cfg_space_cache[(0x34>>2)]; cap_offset = cap&0xFC; - while ((cap_offset)&&(cap_offset < 256)) { + while ((cap_offset)&&(cap_offset < ctx->pci_cfg_space_size)) { cap = ctx->pci_cfg_space_cache[cap_offset>>2]; if ((cap&0xFF) == cap_id) return &ctx->pci_cfg_space_cache[cap_offset>>2]; diff --git a/pcilib/pci.h b/pcilib/pci.h index 51bb352..340abd3 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -42,6 +42,7 @@ struct pcilib_s { int pci_cfg_space_fd; /**< File descriptor linking to PCI configuration space in sysfs */ uint32_t pci_cfg_space_cache[64]; /**< Cached PCI configuration space */ + size_t pci_cfg_space_size; /**< Size of the cached PCI configuration space, sometimes not fully is available for unpriveledged user */ const uint32_t *pcie_capabilities; /**< PCI Capbility structure (just a pointer at appropriate place in the pci_cfg_space) */ int reg_bar_mapped; /**< Indicates that all BARs used to access registers are mapped */ -- cgit v1.2.3