#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
-#include <linux/rwsem.h>
+#include <linux/spinlock.h>
#include <linux/sched.h>
#include "dvb_ca_en50221.h"
/* 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;
-
/* buffer for incoming packets */
struct dvb_ringbuffer rx_buffer;
if (ebuf == NULL) {
int buf_free;
- down_read(&ca->slot_info[slot].sem);
if (ca->slot_info[slot].rx_buffer.data == NULL) {
- up_read(&ca->slot_info[slot].sem);
status = -EIO;
goto exit;
}
buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer);
- up_read(&ca->slot_info[slot].sem);
if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) {
status = -EAGAIN;
/* OK, add it to the receive buffer, or copy into external buffer if supplied */
if (ebuf == NULL) {
- down_read(&ca->slot_info[slot].sem);
if (ca->slot_info[slot].rx_buffer.data == NULL) {
- up_read(&ca->slot_info[slot].sem);
status = -EIO;
goto exit;
}
dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read);
- up_read(&ca->slot_info[slot].sem);
} else {
memcpy(ebuf, buf, bytes_read);
}
{
dprintk("%s\n", __FUNCTION__);
- down_write(&ca->slot_info[slot].sem);
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);
/* need to wake up all processes to check if they're now
trying to write to a defunct CAM */
case DVB_CA_SLOTSTATE_RUNNING:
if (ca->open)
- dvb_ca_en50221_read_data(ca, slot, NULL, 0);
+ dvb_ca_en50221_thread_wakeup(ca);
break;
}
}
break;
}
- rxbuf = vmalloc(RX_BUFFER_SIZE);
- if (rxbuf == NULL) {
- printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
- dvb_ca_en50221_thread_update_delay(ca);
- break;
+ if (ca->slot_info[slot].rx_buffer.data == NULL) {
+ rxbuf = vmalloc(RX_BUFFER_SIZE);
+ if (rxbuf == NULL) {
+ printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num);
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
+ dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE);
}
- down_write(&ca->slot_info[slot].sem);
- dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE);
- up_write(&ca->slot_info[slot].sem);
ca->pub->slot_ts_enable(ca->pub, slot);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING;
if (!ca->open)
continue;
- // no need to poll if the CAM supports IRQs
- if (ca->slot_info[slot].da_irq_supported)
- break;
-
- // poll mode
+ // poll slots for data
pktcount = 0;
while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) {
if (!ca->open)
/**
* 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)
{
int slot;
int slot_count = 0;
int idx;
- int fraglen;
+ size_t fraglen;
int connection_id = -1;
int found = 0;
u8 hdr[2];
if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING)
goto nextslot;
- down_read(&ca->slot_info[slot].sem);
-
if (ca->slot_info[slot].rx_buffer.data == NULL) {
- up_read(&ca->slot_info[slot].sem);
return 0;
}
idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
}
- if (!found)
- up_read(&ca->slot_info[slot].sem);
-
- nextslot:
+nextslot:
slot = (slot + 1) % ca->slot_count;
slot_count++;
}
goto exit;
status = pktlen;
- exit:
- up_read(&ca->slot_info[slot].sem);
+exit:
return status;
}
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);
if (ca->slot_info[i].rx_buffer.data != NULL) {
+ /* it is safe to call this here without locks because
+ * ca->open == 0. Data is not read in this case */
dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer);
}
- up_write(&ca->slot_info[i].sem);
}
}
dprintk("%s\n", __FUNCTION__);
if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
- up_read(&ca->slot_info[slot].sem);
mask |= POLLIN;
}
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);
mask |= POLLIN;
}
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);
}
if (signal_pending(current)) {
ca->thread_pid = ret;
return 0;
- error:
+error:
if (ca != NULL) {
if (ca->dvbdev != NULL)
dvb_unregister_device(ca->dvbdev);
for (i = 0; i < ca->slot_count; i++) {
dvb_ca_en50221_slot_shutdown(ca, i);
+ if (ca->slot_info[i].rx_buffer.data != NULL) {
+ vfree(ca->slot_info[i].rx_buffer.data);
+ }
}
kfree(ca->slot_info);
dvb_unregister_device(ca->dvbdev);