aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Walls <awalls@md.metrocast.net>2011-02-17 18:50:38 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-22 18:24:00 -0400
commitd6dbd939b97d271766a58a66d69b27023bc90993 (patch)
treec5b529b78794bcb823a34bc33489bbb0afecd175
parent5bd6b0464b68d429bc8a3fe6595d19c39dfc4d95 (diff)
[media] lirc_zilog: Add locking of the i2c_clients when in use
Lock the i2c_client pointers and prevent i2c_client removal when lirc_zilog is perfoming a series of operations that require valid i2c_client pointers. Signed-off-by: Andy Walls <awalls@md.metrocast.net> Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/staging/lirc/lirc_zilog.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c
index 5df90dbba1c6..5946a9541c43 100644
--- a/drivers/staging/lirc/lirc_zilog.c
+++ b/drivers/staging/lirc/lirc_zilog.c
@@ -70,7 +70,7 @@ struct IR_rx {
70 struct IR *ir; 70 struct IR *ir;
71 71
72 /* RX device */ 72 /* RX device */
73 /* FIXME mutex lock access to this pointer */ 73 struct mutex client_lock;
74 struct i2c_client *c; 74 struct i2c_client *c;
75 75
76 /* RX polling thread data */ 76 /* RX polling thread data */
@@ -86,7 +86,7 @@ struct IR_tx {
86 struct IR *ir; 86 struct IR *ir;
87 87
88 /* TX device */ 88 /* TX device */
89 /* FIXME mutex lock access to this pointer */ 89 struct mutex client_lock;
90 struct i2c_client *c; 90 struct i2c_client *c;
91 91
92 /* TX additional actions needed */ 92 /* TX additional actions needed */
@@ -341,6 +341,14 @@ static int add_to_buf(struct IR *ir)
341 if (rx == NULL) 341 if (rx == NULL)
342 return -ENXIO; 342 return -ENXIO;
343 343
344 /* Ensure our rx->c i2c_client remains valid for the duration */
345 mutex_lock(&rx->client_lock);
346 if (rx->c == NULL) {
347 mutex_unlock(&rx->client_lock);
348 put_ir_rx(rx, false);
349 return -ENXIO;
350 }
351
344 tx = get_ir_tx(ir); 352 tx = get_ir_tx(ir);
345 353
346 /* 354 /*
@@ -442,6 +450,7 @@ static int add_to_buf(struct IR *ir)
442 ret = 0; 450 ret = 0;
443 } while (!lirc_buffer_full(rbuf)); 451 } while (!lirc_buffer_full(rbuf));
444 452
453 mutex_unlock(&rx->client_lock);
445 if (tx != NULL) 454 if (tx != NULL)
446 put_ir_tx(tx, false); 455 put_ir_tx(tx, false);
447 put_ir_rx(rx, false); 456 put_ir_rx(rx, false);
@@ -1089,6 +1098,14 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
1089 if (tx == NULL) 1098 if (tx == NULL)
1090 return -ENXIO; 1099 return -ENXIO;
1091 1100
1101 /* Ensure our tx->c i2c_client remains valid for the duration */
1102 mutex_lock(&tx->client_lock);
1103 if (tx->c == NULL) {
1104 mutex_unlock(&tx->client_lock);
1105 put_ir_tx(tx, false);
1106 return -ENXIO;
1107 }
1108
1092 /* Lock i2c bus for the duration */ 1109 /* Lock i2c bus for the duration */
1093 mutex_lock(&ir->ir_lock); 1110 mutex_lock(&ir->ir_lock);
1094 1111
@@ -1099,6 +1116,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
1099 1116
1100 if (copy_from_user(&command, buf + i, sizeof(command))) { 1117 if (copy_from_user(&command, buf + i, sizeof(command))) {
1101 mutex_unlock(&ir->ir_lock); 1118 mutex_unlock(&ir->ir_lock);
1119 mutex_unlock(&tx->client_lock);
1102 put_ir_tx(tx, false); 1120 put_ir_tx(tx, false);
1103 return -EFAULT; 1121 return -EFAULT;
1104 } 1122 }
@@ -1109,6 +1127,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
1109 ret = fw_load(tx); 1127 ret = fw_load(tx);
1110 if (ret != 0) { 1128 if (ret != 0) {
1111 mutex_unlock(&ir->ir_lock); 1129 mutex_unlock(&ir->ir_lock);
1130 mutex_unlock(&tx->client_lock);
1112 put_ir_tx(tx, false); 1131 put_ir_tx(tx, false);
1113 if (ret != -ENOMEM) 1132 if (ret != -ENOMEM)
1114 ret = -EIO; 1133 ret = -EIO;
@@ -1126,6 +1145,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
1126 (unsigned)command & 0xFFFF); 1145 (unsigned)command & 0xFFFF);
1127 if (ret == -EPROTO) { 1146 if (ret == -EPROTO) {
1128 mutex_unlock(&ir->ir_lock); 1147 mutex_unlock(&ir->ir_lock);
1148 mutex_unlock(&tx->client_lock);
1129 put_ir_tx(tx, false); 1149 put_ir_tx(tx, false);
1130 return ret; 1150 return ret;
1131 } 1151 }
@@ -1144,6 +1164,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
1144 zilog_error("unable to send to the IR chip " 1164 zilog_error("unable to send to the IR chip "
1145 "after 3 resets, giving up\n"); 1165 "after 3 resets, giving up\n");
1146 mutex_unlock(&ir->ir_lock); 1166 mutex_unlock(&ir->ir_lock);
1167 mutex_unlock(&tx->client_lock);
1147 put_ir_tx(tx, false); 1168 put_ir_tx(tx, false);
1148 return ret; 1169 return ret;
1149 } 1170 }
@@ -1158,6 +1179,8 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
1158 /* Release i2c bus */ 1179 /* Release i2c bus */
1159 mutex_unlock(&ir->ir_lock); 1180 mutex_unlock(&ir->ir_lock);
1160 1181
1182 mutex_unlock(&tx->client_lock);
1183
1161 /* Give back our struct IR_tx reference */ 1184 /* Give back our struct IR_tx reference */
1162 put_ir_tx(tx, false); 1185 put_ir_tx(tx, false);
1163 1186
@@ -1365,12 +1388,20 @@ static int ir_remove(struct i2c_client *client)
1365{ 1388{
1366 if (strncmp("ir_tx_z8", client->name, 8) == 0) { 1389 if (strncmp("ir_tx_z8", client->name, 8) == 0) {
1367 struct IR_tx *tx = i2c_get_clientdata(client); 1390 struct IR_tx *tx = i2c_get_clientdata(client);
1368 if (tx != NULL) 1391 if (tx != NULL) {
1392 mutex_lock(&tx->client_lock);
1393 tx->c = NULL;
1394 mutex_unlock(&tx->client_lock);
1369 put_ir_tx(tx, false); 1395 put_ir_tx(tx, false);
1396 }
1370 } else if (strncmp("ir_rx_z8", client->name, 8) == 0) { 1397 } else if (strncmp("ir_rx_z8", client->name, 8) == 0) {
1371 struct IR_rx *rx = i2c_get_clientdata(client); 1398 struct IR_rx *rx = i2c_get_clientdata(client);
1372 if (rx != NULL) 1399 if (rx != NULL) {
1400 mutex_lock(&rx->client_lock);
1401 rx->c = NULL;
1402 mutex_unlock(&rx->client_lock);
1373 put_ir_rx(rx, false); 1403 put_ir_rx(rx, false);
1404 }
1374 } 1405 }
1375 return 0; 1406 return 0;
1376} 1407}
@@ -1472,6 +1503,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
1472 ir->tx = tx; 1503 ir->tx = tx;
1473 1504
1474 ir->l.features |= LIRC_CAN_SEND_PULSE; 1505 ir->l.features |= LIRC_CAN_SEND_PULSE;
1506 mutex_init(&tx->client_lock);
1475 tx->c = client; 1507 tx->c = client;
1476 tx->need_boot = 1; 1508 tx->need_boot = 1;
1477 tx->post_tx_ready_poll = 1509 tx->post_tx_ready_poll =
@@ -1514,6 +1546,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
1514 ir->rx = rx; 1546 ir->rx = rx;
1515 1547
1516 ir->l.features |= LIRC_CAN_REC_LIRCCODE; 1548 ir->l.features |= LIRC_CAN_REC_LIRCCODE;
1549 mutex_init(&rx->client_lock);
1517 rx->c = client; 1550 rx->c = client;
1518 rx->hdpvr_data_fmt = 1551 rx->hdpvr_data_fmt =
1519 (id->driver_data & ID_FLAG_HDPVR) ? true : false; 1552 (id->driver_data & ID_FLAG_HDPVR) ? true : false;