diff options
author | Andrew de Quincy <devnull@localhost> | 2005-07-23 22:24:31 +0000 |
---|---|---|
committer | Andrew de Quincy <devnull@localhost> | 2005-07-23 22:24:31 +0000 |
commit | dc3d59ccae0329939665505d585f92c2095591ca (patch) | |
tree | ca5c5ef102581b19cdc94630abea644b4be7921e /linux/drivers/media/dvb | |
parent | fc5fdeb9baf0a40a275635f2cc5280445e39c581 (diff) | |
download | mediapointer-dvb-s2-dc3d59ccae0329939665505d585f92c2095591ca.tar.gz mediapointer-dvb-s2-dc3d59ccae0329939665505d585f92c2095591ca.tar.bz2 |
Convert to using read/write spinlocks to fix kernel errors as reported by
Michael Ditum
Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c | 68 |
1 files changed, 38 insertions, 30 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 0eb9aa711..b9d596883 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -35,7 +35,7 @@ #include <linux/moduleparam.h> #include <linux/vmalloc.h> #include <linux/delay.h> -#include <linux/rwsem.h> +#include <linux/spinlock.h> #include "dvb_ca_en50221.h" #include "dvb_ringbuffer.h" @@ -110,8 +110,8 @@ struct dvb_ca_slot { /* size of the buffer to use when talking to the CAM */ int link_buf_size; - /* semaphore for syncing access to slot structure */ - struct rw_semaphore sem; + /* spinlock for syncing access to slot structure */ + rwlock_t lock; /* buffer for incoming packets */ struct dvb_ringbuffer rx_buffer; @@ -594,6 +594,7 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb int status; u8 buf[HOST_LINK_BUF_SIZE]; int i; + unsigned long irqsave; dprintk("%s\n", __FUNCTION__); @@ -601,14 +602,14 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb if (ebuf == NULL) { int buf_free; - down_read(&ca->slot_info[slot].sem); + read_lock_irqsave(&ca->slot_info[slot].lock, irqsave); if (ca->slot_info[slot].rx_buffer.data == NULL) { - up_read(&ca->slot_info[slot].sem); + read_unlock_irqrestore(&ca->slot_info[slot].lock, irqsave); status = -EIO; goto exit; } buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); - up_read(&ca->slot_info[slot].sem); + read_unlock_irqrestore(&ca->slot_info[slot].lock, irqsave); if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) { status = -EAGAIN; @@ -679,14 +680,14 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb /* OK, add it to the receive buffer, or copy into external buffer if supplied */ if (ebuf == NULL) { - down_read(&ca->slot_info[slot].sem); + read_lock_irqsave(&ca->slot_info[slot].lock, irqsave); if (ca->slot_info[slot].rx_buffer.data == NULL) { - up_read(&ca->slot_info[slot].sem); + read_unlock_irqrestore(&ca->slot_info[slot].lock, irqsave); status = -EIO; goto exit; } dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read); - up_read(&ca->slot_info[slot].sem); + read_unlock_irqrestore(&ca->slot_info[slot].lock, irqsave); } else { memcpy(ebuf, buf, bytes_read); } @@ -800,13 +801,14 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq); static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot) { dprintk("%s\n", __FUNCTION__); + unsigned long irqsave; - down_write(&ca->slot_info[slot].sem); + write_lock_irqsave(&ca->slot_info[slot].lock, irqsave); ca->pub->slot_shutdown(ca->pub, slot); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; vfree(ca->slot_info[slot].rx_buffer.data); ca->slot_info[slot].rx_buffer.data = NULL; - up_write(&ca->slot_info[slot].sem); + write_unlock_irqrestore(&ca->slot_info[slot].lock, irqsave); /* need to wake up all processes to check if they're now trying to write to a defunct CAM */ @@ -1000,6 +1002,7 @@ static int dvb_ca_en50221_thread(void *data) int status; int pktcount; void *rxbuf; + unsigned long irqsave; dprintk("%s\n", __FUNCTION__); @@ -1133,9 +1136,9 @@ static int dvb_ca_en50221_thread(void *data) dvb_ca_en50221_thread_update_delay(ca); break; } - down_write(&ca->slot_info[slot].sem); + write_lock_irqsave(&ca->slot_info[slot].lock, irqsave); dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE); - up_write(&ca->slot_info[slot].sem); + write_unlock_irqrestore(&ca->slot_info[slot].lock, irqsave); ca->pub->slot_ts_enable(ca->pub, slot); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; @@ -1366,7 +1369,9 @@ exit: /** * Condition for waking up in dvb_ca_en50221_io_read_condition */ -static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, int *result, int *_slot) +static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, + int *result, int *_slot, + unsigned long *irqsave) { int slot; int slot_count = 0; @@ -1381,10 +1386,10 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, int *resu if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) goto nextslot; - down_read(&ca->slot_info[slot].sem); + read_lock_irqsave(&ca->slot_info[slot].lock, *irqsave); if (ca->slot_info[slot].rx_buffer.data == NULL) { - up_read(&ca->slot_info[slot].sem); + read_unlock_irqrestore(&ca->slot_info[slot].lock, *irqsave); return 0; } @@ -1403,9 +1408,9 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, int *resu } if (!found) - up_read(&ca->slot_info[slot].sem); + read_unlock_irqrestore(&ca->slot_info[slot].lock, *irqsave); - nextslot: +nextslot: slot = (slot + 1) % ca->slot_count; slot_count++; } @@ -1440,6 +1445,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, size_t fraglen; int pktlen; int dispose = 0; + unsigned long irqsave; dprintk("%s\n", __FUNCTION__); @@ -1448,7 +1454,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, return -EINVAL; /* wait for some data */ - if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) { + if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot, &irqsave)) == 0) { /* if we're in nonblocking mode, exit immediately */ if (file->f_flags & O_NONBLOCK) @@ -1457,7 +1463,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, /* wait for some data */ status = wait_event_interruptible(ca->wait_queue, dvb_ca_en50221_io_read_condition - (ca, &result, &slot)); + (ca, &result, &slot, &irqsave)); } if ((status < 0) || (result < 0)) { if (result) @@ -1510,8 +1516,8 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, goto exit; status = pktlen; - exit: - up_read(&ca->slot_info[slot].sem); +exit: + read_unlock_irqrestore(&ca->slot_info[slot].lock, irqsave); return status; } @@ -1530,6 +1536,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) struct dvb_ca_private *ca = dvbdev->priv; int err; int i; + unsigned long irqsave; dprintk("%s\n", __FUNCTION__); @@ -1543,11 +1550,11 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) for (i = 0; i < ca->slot_count; i++) { if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { - down_write(&ca->slot_info[i].sem); + read_lock_irqsave(&ca->slot_info[i].lock, irqsave); if (ca->slot_info[i].rx_buffer.data != NULL) { dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer); } - up_write(&ca->slot_info[i].sem); + read_unlock_irqrestore(&ca->slot_info[i].lock, irqsave); } } @@ -1602,11 +1609,12 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait) unsigned int mask = 0; int slot; int result = 0; + unsigned long irqsave; dprintk("%s\n", __FUNCTION__); - if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { - up_read(&ca->slot_info[slot].sem); + if (dvb_ca_en50221_io_read_condition(ca, &result, &slot, &irqsave) == 1) { + read_unlock_irqrestore(&ca->slot_info[slot].lock, irqsave); mask |= POLLIN; } @@ -1617,8 +1625,8 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait) /* wait for something to happen */ poll_wait(file, &ca->wait_queue, wait); - if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { - up_read(&ca->slot_info[slot].sem); + if (dvb_ca_en50221_io_read_condition(ca, &result, &slot, &irqsave) == 1) { + read_unlock_irqrestore(&ca->slot_info[slot].lock, irqsave); mask |= POLLIN; } @@ -1708,7 +1716,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; atomic_set(&ca->slot_info[i].camchange_count, 0); ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; - init_rwsem(&ca->slot_info[i].sem); + ca->slot_info[i].lock = RW_LOCK_UNLOCKED; } if (signal_pending(current)) { @@ -1728,7 +1736,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, ca->thread_pid = ret; return 0; - error: +error: if (ca != NULL) { if (ca->dvbdev != NULL) dvb_unregister_device(ca->dvbdev); |