aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c24
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.h6
2 files changed, 25 insertions, 5 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 98ee16773ff2..7e3aeaa7370f 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -93,6 +93,9 @@ struct dvb_ca_slot {
93 /* current state of the CAM */ 93 /* current state of the CAM */
94 int slot_state; 94 int slot_state;
95 95
96 /* mutex used for serializing access to one CI slot */
97 struct mutex slot_lock;
98
96 /* Number of CAMCHANGES that have occurred since last processing */ 99 /* Number of CAMCHANGES that have occurred since last processing */
97 atomic_t camchange_count; 100 atomic_t camchange_count;
98 101
@@ -711,14 +714,20 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
711 dprintk("%s\n", __func__); 714 dprintk("%s\n", __func__);
712 715
713 716
714 // sanity check 717 /* sanity check */
715 if (bytes_write > ca->slot_info[slot].link_buf_size) 718 if (bytes_write > ca->slot_info[slot].link_buf_size)
716 return -EINVAL; 719 return -EINVAL;
717 720
718 /* check if interface is actually waiting for us to read from it, or if a read is in progress */ 721 /* it is possible we are dealing with a single buffer implementation,
722 thus if there is data available for read or if there is even a read
723 already in progress, we do nothing but awake the kernel thread to
724 process the data if necessary. */
719 if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) 725 if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
720 goto exitnowrite; 726 goto exitnowrite;
721 if (status & (STATUSREG_DA | STATUSREG_RE)) { 727 if (status & (STATUSREG_DA | STATUSREG_RE)) {
728 if (status & STATUSREG_DA)
729 dvb_ca_en50221_thread_wakeup(ca);
730
722 status = -EAGAIN; 731 status = -EAGAIN;
723 goto exitnowrite; 732 goto exitnowrite;
724 } 733 }
@@ -987,6 +996,8 @@ static int dvb_ca_en50221_thread(void *data)
987 /* go through all the slots processing them */ 996 /* go through all the slots processing them */
988 for (slot = 0; slot < ca->slot_count; slot++) { 997 for (slot = 0; slot < ca->slot_count; slot++) {
989 998
999 mutex_lock(&ca->slot_info[slot].slot_lock);
1000
990 // check the cam status + deal with CAMCHANGEs 1001 // check the cam status + deal with CAMCHANGEs
991 while (dvb_ca_en50221_check_camstatus(ca, slot)) { 1002 while (dvb_ca_en50221_check_camstatus(ca, slot)) {
992 /* clear down an old CI slot if necessary */ 1003 /* clear down an old CI slot if necessary */
@@ -1122,7 +1133,7 @@ static int dvb_ca_en50221_thread(void *data)
1122 1133
1123 case DVB_CA_SLOTSTATE_RUNNING: 1134 case DVB_CA_SLOTSTATE_RUNNING:
1124 if (!ca->open) 1135 if (!ca->open)
1125 continue; 1136 break;
1126 1137
1127 // poll slots for data 1138 // poll slots for data
1128 pktcount = 0; 1139 pktcount = 0;
@@ -1146,6 +1157,8 @@ static int dvb_ca_en50221_thread(void *data)
1146 } 1157 }
1147 break; 1158 break;
1148 } 1159 }
1160
1161 mutex_unlock(&ca->slot_info[slot].slot_lock);
1149 } 1162 }
1150 } 1163 }
1151 1164
@@ -1181,6 +1194,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
1181 switch (cmd) { 1194 switch (cmd) {
1182 case CA_RESET: 1195 case CA_RESET:
1183 for (slot = 0; slot < ca->slot_count; slot++) { 1196 for (slot = 0; slot < ca->slot_count; slot++) {
1197 mutex_lock(&ca->slot_info[slot].slot_lock);
1184 if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { 1198 if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) {
1185 dvb_ca_en50221_slot_shutdown(ca, slot); 1199 dvb_ca_en50221_slot_shutdown(ca, slot);
1186 if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) 1200 if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)
@@ -1188,6 +1202,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
1188 slot, 1202 slot,
1189 DVB_CA_EN50221_CAMCHANGE_INSERTED); 1203 DVB_CA_EN50221_CAMCHANGE_INSERTED);
1190 } 1204 }
1205 mutex_unlock(&ca->slot_info[slot].slot_lock);
1191 } 1206 }
1192 ca->next_read_slot = 0; 1207 ca->next_read_slot = 0;
1193 dvb_ca_en50221_thread_wakeup(ca); 1208 dvb_ca_en50221_thread_wakeup(ca);
@@ -1308,7 +1323,9 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
1308 goto exit; 1323 goto exit;
1309 } 1324 }
1310 1325
1326 mutex_lock(&ca->slot_info[slot].slot_lock);
1311 status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2); 1327 status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2);
1328 mutex_unlock(&ca->slot_info[slot].slot_lock);
1312 if (status == (fraglen + 2)) { 1329 if (status == (fraglen + 2)) {
1313 written = 1; 1330 written = 1;
1314 break; 1331 break;
@@ -1664,6 +1681,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
1664 ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; 1681 ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE;
1665 atomic_set(&ca->slot_info[i].camchange_count, 0); 1682 atomic_set(&ca->slot_info[i].camchange_count, 0);
1666 ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; 1683 ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
1684 mutex_init(&ca->slot_info[i].slot_lock);
1667 } 1685 }
1668 1686
1669 if (signal_pending(current)) { 1687 if (signal_pending(current)) {
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h
index 8467e63ddc0d..7df2e141187a 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h
@@ -45,8 +45,10 @@ struct dvb_ca_en50221 {
45 /* the module owning this structure */ 45 /* the module owning this structure */
46 struct module* owner; 46 struct module* owner;
47 47
48 /* NOTE: the read_*, write_* and poll_slot_status functions must use locks as 48 /* NOTE: the read_*, write_* and poll_slot_status functions will be
49 * they may be called from several threads at once */ 49 * called for different slots concurrently and need to use locks where
50 * and if appropriate. There will be no concurrent access to one slot.
51 */
50 52
51 /* functions for accessing attribute memory on the CAM */ 53 /* functions for accessing attribute memory on the CAM */
52 int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); 54 int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);