summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c52
1 files changed, 35 insertions, 17 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 35e265963..7fe4c100d 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -602,6 +602,11 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb
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);
@@ -631,8 +636,8 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb
/* check it will fit */
if (ebuf == NULL) {
if (bytes_read > ca->slot_info[slot].link_buf_size) {
- printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size!\n",
- ca->dvbdev->adapter->num);
+ printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n",
+ ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
status = -EIO;
goto exit;
@@ -675,6 +680,11 @@ 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);
+ 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 {
@@ -690,7 +700,7 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb
}
status = bytes_read;
- exit:
+exit:
return status;
}
@@ -1075,9 +1085,8 @@ static int dvb_ca_en50221_thread(void *data)
dvb_ca_en50221_thread_update_delay(ca);
break;
}
- if (ca->pub->
- write_cam_control(ca->pub, slot,
- CTRLIF_COMMAND, CMDREG_RS) != 0) {
+ if (ca->pub->write_cam_control(ca->pub, slot,
+ CTRLIF_COMMAND, CMDREG_RS) != 0) {
printk("dvb_ca adapter %d: Unable to reset CAM IF\n",
ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
@@ -1122,7 +1131,9 @@ static int dvb_ca_en50221_thread(void *data)
dvb_ca_en50221_thread_update_delay(ca);
break;
}
+ 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;
@@ -1205,8 +1216,6 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
dvb_ca_en50221_camchange_irq(ca->pub,
slot,
DVB_CA_EN50221_CAMCHANGE_INSERTED);
- else
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
}
}
ca->next_read_slot = 0;
@@ -1322,6 +1331,12 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
timeout = jiffies + HZ / 2;
written = 0;
while (!time_after(jiffies, timeout)) {
+ /* check the CAM hasn't been removed/reset in the meantime */
+ if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) {
+ status = -EIO;
+ goto exit;
+ }
+
status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2);
if (status == (fraglen + 2)) {
written = 1;
@@ -1341,7 +1356,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
}
status = count + 2;
- exit:
+exit:
return status;
}
@@ -1366,6 +1381,11 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, int *resu
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, -1, &fraglen);
while (idx != -1) {
dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
@@ -1377,8 +1397,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, int *resu
break;
}
- idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].
- rx_buffer, idx, &fraglen);
+ idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
}
if (!found)
@@ -1464,11 +1483,8 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
fraglen -= 2;
}
- if ((status =
- dvb_ringbuffer_pkt_read(&ca->
- slot_info[slot].
- rx_buffer, idx, 2,
- buf + pktlen, fraglen, 1)) < 0) {
+ if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2,
+ buf + pktlen, fraglen, 1)) < 0) {
goto exit;
}
pktlen += fraglen;
@@ -1523,7 +1539,9 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
down_write(&ca->slot_info[i].sem);
- dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer);
+ 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);
}
}