diff options
Diffstat (limited to 'linux')
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c | 52 |
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); } } |