mirror of
https://github.com/KastnerRG/riffa.git
synced 2025-01-30 23:02:54 +08:00
Linux driver: Protect recv and send with atomic test and set instead of lock to enable clear at reset
This commit is contained in:
parent
3775133808
commit
9f791acfea
@ -53,7 +53,6 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/rwsem.h>
|
#include <linux/rwsem.h>
|
||||||
#include <linux/semaphore.h>
|
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
@ -76,6 +75,8 @@ MODULE_AUTHOR("Matt Jacobsen, Patrick Lai");
|
|||||||
#define BUILD_32 1
|
#define BUILD_32 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CHNL_FLAG_BUSY 0
|
||||||
|
|
||||||
struct sg_mapping {
|
struct sg_mapping {
|
||||||
struct page ** pages;
|
struct page ** pages;
|
||||||
struct scatterlist * sgl;
|
struct scatterlist * sgl;
|
||||||
@ -87,7 +88,7 @@ struct sg_mapping {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct chnl_dir {
|
struct chnl_dir {
|
||||||
struct semaphore sem;
|
volatile unsigned long flags;
|
||||||
wait_queue_head_t waitq;
|
wait_queue_head_t waitq;
|
||||||
struct circ_queue * msgs;
|
struct circ_queue * msgs;
|
||||||
void * buf_addr;
|
void * buf_addr;
|
||||||
@ -686,15 +687,15 @@ static inline unsigned int chnl_recv_wrapcheck(struct fpga_state * sc, int chnl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure no simultaneous operations from several threads
|
// Ensure no simultaneous operations from several threads
|
||||||
if (down_trylock(&sc->recv[chnl]->sem) != 0) {
|
if (test_and_set_bit(CHNL_FLAG_BUSY, &sc->recv[chnl]->flags) != 0) {
|
||||||
printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv conflict between threads!\n", sc->id, chnl);
|
printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv conflict between threads!\n", sc->id, chnl);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = chnl_recv(sc, chnl, bufp, len, timeout);
|
ret = chnl_recv(sc, chnl, bufp, len, timeout);
|
||||||
|
|
||||||
// Release the semaphore
|
// Clear the busy flag
|
||||||
up(&sc->recv[chnl]->sem);
|
clear_bit(CHNL_FLAG_BUSY, &sc->recv[chnl]->flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -856,15 +857,15 @@ static inline unsigned int chnl_send_wrapcheck(struct fpga_state * sc, int chnl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure no simultaneous operations from several threads
|
// Ensure no simultaneous operations from several threads
|
||||||
if (down_trylock(&sc->send[chnl]->sem) != 0) {
|
if (test_and_set_bit(CHNL_FLAG_BUSY, &sc->send[chnl]->flags) != 0) {
|
||||||
printk(KERN_ERR "riffa: fpga:%d chnl:%d, send conflict between threads!\n", sc->id, chnl);
|
printk(KERN_ERR "riffa: fpga:%d chnl:%d, send conflict between threads!\n", sc->id, chnl);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = chnl_send(sc, chnl, bufp, len, offset, last, timeout);
|
ret = chnl_send(sc, chnl, bufp, len, offset, last, timeout);
|
||||||
|
|
||||||
// Release the semaphore
|
// Clear the busy flag
|
||||||
up(&sc->send[chnl]->sem);
|
clear_bit(CHNL_FLAG_BUSY, &sc->send[chnl]->flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -927,6 +928,8 @@ static inline void reset(int id)
|
|||||||
while (!pop_circ_queue(sc->recv[i]->msgs, &dummy0, &dummy1));
|
while (!pop_circ_queue(sc->recv[i]->msgs, &dummy0, &dummy1));
|
||||||
wake_up(&sc->send[i]->waitq);
|
wake_up(&sc->send[i]->waitq);
|
||||||
wake_up(&sc->recv[i]->waitq);
|
wake_up(&sc->recv[i]->waitq);
|
||||||
|
clear_bit(CHNL_FLAG_BUSY, &sc->send[i]->flags);
|
||||||
|
clear_bit(CHNL_FLAG_BUSY, &sc->recv[i]->flags);
|
||||||
}
|
}
|
||||||
// Enable interrupts
|
// Enable interrupts
|
||||||
atomic_set(&sc->intr_disabled, 0);
|
atomic_set(&sc->intr_disabled, 0);
|
||||||
@ -996,7 +999,7 @@ static inline int __devinit allocate_chnls(struct pci_dev *dev, struct fpga_stat
|
|||||||
sc->recv[i] = (struct chnl_dir *) kzalloc(sizeof(struct chnl_dir), GFP_KERNEL);
|
sc->recv[i] = (struct chnl_dir *) kzalloc(sizeof(struct chnl_dir), GFP_KERNEL);
|
||||||
if (sc->recv[i] == NULL)
|
if (sc->recv[i] == NULL)
|
||||||
return i;
|
return i;
|
||||||
sema_init(&sc->recv[i]->sem, 1);
|
sc->recv[i]->flags = 0;
|
||||||
init_waitqueue_head(&sc->recv[i]->waitq);
|
init_waitqueue_head(&sc->recv[i]->waitq);
|
||||||
if ((sc->recv[i]->msgs = init_circ_queue(5)) == NULL) {
|
if ((sc->recv[i]->msgs = init_circ_queue(5)) == NULL) {
|
||||||
kfree(sc->recv[i]);
|
kfree(sc->recv[i]);
|
||||||
@ -1019,7 +1022,7 @@ static inline int __devinit allocate_chnls(struct pci_dev *dev, struct fpga_stat
|
|||||||
kfree(sc->recv[i]);
|
kfree(sc->recv[i]);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
sema_init(&sc->send[i]->sem, 1);
|
sc->send[i]->flags = 0;
|
||||||
init_waitqueue_head(&sc->send[i]->waitq);
|
init_waitqueue_head(&sc->send[i]->waitq);
|
||||||
if ((sc->send[i]->msgs = init_circ_queue(4)) == NULL) {
|
if ((sc->send[i]->msgs = init_circ_queue(4)) == NULL) {
|
||||||
kfree(sc->send[i]);
|
kfree(sc->send[i]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user