aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Walls <awalls@md.metrocast.net>2011-01-14 23:04:06 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-01-19 08:46:06 -0500
commita68a9b73fbb05144a71b573f262fbc8ed8f71179 (patch)
treea1fffd97eecbc39244bd21ee47dca6063e8ad5c8
parente9b351f64f5c02acf6552d2109bc213bfa133388 (diff)
[media] lirc_zilog: Extensive rework of ir_probe()/ir_remove()
This patch is an extensive rework of the ir_probe() and ir_remove() functions. It removes all the double binding and allocation problems on module load. It removes almost all the memory leaks on module exit and on device instantiation failure. Proper destruction of the Rx polling kthread still needs investigation and more work, but it is no worse than it already was. This rework also had side effects that include: - encapsulation of the ir_devices[] array - serialization of access to the ir_devices[] array - semantic change of the module parameter "disable_rx" to "tx_only" If tx_only is true, the module does not claim the i2c_client for the IR Rx function, and only claims and handles the i2c_client for the IR Tx function. This is a first step in providing the option of letting ir-kbd-i2c.c handle IR Rx function, while lirc_zilog handles the IR Tx function. Signed-off-by: Andy Walls <awalls@md.metrocast.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/staging/lirc/lirc_zilog.c344
1 files changed, 212 insertions, 132 deletions
diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c
index 00f2e7d3b3e5..f2e8c63fa5bd 100644
--- a/drivers/staging/lirc/lirc_zilog.c
+++ b/drivers/staging/lirc/lirc_zilog.c
@@ -94,11 +94,13 @@ struct IR {
94 struct mutex ir_lock; 94 struct mutex ir_lock;
95 int open; 95 int open;
96 96
97 struct i2c_adapter *adapter;
97 struct IR_rx *rx; 98 struct IR_rx *rx;
98 struct IR_tx *tx; 99 struct IR_tx *tx;
99}; 100};
100 101
101/* Minor -> data mapping */ 102/* Minor -> data mapping */
103static struct mutex ir_devices_lock;
102static struct IR *ir_devices[MAX_IRCTL_DEVICES]; 104static struct IR *ir_devices[MAX_IRCTL_DEVICES];
103 105
104/* Block size for IR transmitter */ 106/* Block size for IR transmitter */
@@ -131,10 +133,11 @@ static struct mutex tx_data_lock;
131#define zilog_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, \ 133#define zilog_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, \
132 ## args) 134 ## args)
133#define zilog_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) 135#define zilog_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
136#define zilog_info(s, args...) printk(KERN_INFO KBUILD_MODNAME ": " s, ## args)
134 137
135/* module parameters */ 138/* module parameters */
136static int debug; /* debug output */ 139static int debug; /* debug output */
137static int disable_rx; /* disable RX device */ 140static int tx_only; /* only handle the IR Tx function */
138static int minor = -1; /* minor number */ 141static int minor = -1; /* minor number */
139 142
140#define dprintk(fmt, args...) \ 143#define dprintk(fmt, args...) \
@@ -252,9 +255,6 @@ static int lirc_thread(void *arg)
252 struct IR *ir = arg; 255 struct IR *ir = arg;
253 struct IR_rx *rx = ir->rx; 256 struct IR_rx *rx = ir->rx;
254 257
255 if (rx == NULL)
256 return -ENXIO;
257
258 if (rx->t_notify != NULL) 258 if (rx->t_notify != NULL)
259 complete(rx->t_notify); 259 complete(rx->t_notify);
260 260
@@ -296,6 +296,7 @@ static int lirc_thread(void *arg)
296 complete(rx->t_notify); 296 complete(rx->t_notify);
297 297
298 dprintk("poll thread ended\n"); 298 dprintk("poll thread ended\n");
299 /* FIXME - investigate if this is the proper way to shutdown a kthread*/
299 return 0; 300 return 0;
300} 301}
301 302
@@ -1058,6 +1059,15 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
1058 return result; 1059 return result;
1059} 1060}
1060 1061
1062/* ir_devices_lock must be held */
1063static struct IR *find_ir_device_by_minor(unsigned int minor)
1064{
1065 if (minor >= MAX_IRCTL_DEVICES)
1066 return NULL;
1067
1068 return ir_devices[minor];
1069}
1070
1061/* 1071/*
1062 * Open the IR device. Get hold of our IR structure and 1072 * Open the IR device. Get hold of our IR structure and
1063 * stash it in private_data for the file 1073 * stash it in private_data for the file
@@ -1066,15 +1076,15 @@ static int open(struct inode *node, struct file *filep)
1066{ 1076{
1067 struct IR *ir; 1077 struct IR *ir;
1068 int ret; 1078 int ret;
1079 unsigned int minor = MINOR(node->i_rdev);
1069 1080
1070 /* find our IR struct */ 1081 /* find our IR struct */
1071 unsigned minor = MINOR(node->i_rdev); 1082 mutex_lock(&ir_devices_lock);
1072 if (minor >= MAX_IRCTL_DEVICES) { 1083 ir = find_ir_device_by_minor(minor);
1073 dprintk("minor %d: open result = -ENODEV\n", 1084 mutex_unlock(&ir_devices_lock);
1074 minor); 1085
1086 if (ir == NULL)
1075 return -ENODEV; 1087 return -ENODEV;
1076 }
1077 ir = ir_devices[minor];
1078 1088
1079 /* increment in use count */ 1089 /* increment in use count */
1080 mutex_lock(&ir->ir_lock); 1090 mutex_lock(&ir->ir_lock);
@@ -1159,136 +1169,203 @@ static const struct file_operations lirc_fops = {
1159 .release = close 1169 .release = close
1160}; 1170};
1161 1171
1162static int ir_remove(struct i2c_client *client) 1172/* FIXME - investigate if this is the proper way to shutdown a kthread */
1173static void destroy_rx_kthread(struct IR_rx *rx)
1163{ 1174{
1164 struct IR *ir = i2c_get_clientdata(client); 1175 DECLARE_COMPLETION(tn);
1165 struct IR_rx *rx = ir->rx; 1176 DECLARE_COMPLETION(tn2);
1166 struct IR_tx *tx = ir->tx;
1167 1177
1168 /* FIXME make tx, rx senitive */ 1178 if (rx == NULL)
1169 mutex_lock(&ir->ir_lock); 1179 return;
1180
1181 /* end up polling thread */
1182 if (rx->task && !IS_ERR(rx->task)) {
1183 rx->t_notify = &tn;
1184 rx->t_notify2 = &tn2;
1185 rx->shutdown = 1;
1186 wake_up_process(rx->task);
1187 complete(&tn2);
1188 wait_for_completion(&tn);
1189 rx->t_notify = NULL;
1190 rx->t_notify2 = NULL;
1191 }
1192}
1170 1193
1171 if (rx != NULL || tx != NULL) { 1194/* ir_devices_lock must be held */
1172 DECLARE_COMPLETION(tn); 1195static int add_ir_device(struct IR *ir)
1173 DECLARE_COMPLETION(tn2); 1196{
1174 1197 int i;
1175 /* end up polling thread */ 1198
1176 if (rx->task && !IS_ERR(rx->task)) { 1199 for (i = 0; i < MAX_IRCTL_DEVICES; i++)
1177 rx->t_notify = &tn; 1200 if (ir_devices[i] == NULL) {
1178 rx->t_notify2 = &tn2; 1201 ir_devices[i] = ir;
1179 rx->shutdown = 1; 1202 break;
1180 wake_up_process(rx->task);
1181 complete(&tn2);
1182 wait_for_completion(&tn);
1183 rx->t_notify = NULL;
1184 rx->t_notify2 = NULL;
1185 } 1203 }
1186 1204
1187 } else { 1205 return i == MAX_IRCTL_DEVICES ? -ENOMEM : i;
1188 mutex_unlock(&ir->ir_lock); 1206}
1189 zilog_error("%s: detached from something we didn't " 1207
1190 "attach to\n", __func__); 1208/* ir_devices_lock must be held */
1191 return -ENODEV; 1209static void del_ir_device(struct IR *ir)
1210{
1211 int i;
1212
1213 for (i = 0; i < MAX_IRCTL_DEVICES; i++)
1214 if (ir_devices[i] == ir) {
1215 ir_devices[i] = NULL;
1216 break;
1217 }
1218}
1219
1220static int ir_remove(struct i2c_client *client)
1221{
1222 struct IR *ir = i2c_get_clientdata(client);
1223
1224 mutex_lock(&ir_devices_lock);
1225
1226 if (ir == NULL) {
1227 /* We destroyed everything when the first client came through */
1228 mutex_unlock(&ir_devices_lock);
1229 return 0;
1192 } 1230 }
1193 1231
1194 /* unregister lirc driver */ 1232 /* Good-bye LIRC */
1195 /* FIXME make tx, rx senitive */ 1233 lirc_unregister_driver(ir->l.minor);
1196 if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) { 1234
1197 lirc_unregister_driver(ir->l.minor); 1235 /* Good-bye Rx */
1198 ir_devices[ir->l.minor] = NULL; 1236 destroy_rx_kthread(ir->rx);
1237 if (ir->rx != NULL) {
1238 if (ir->rx->buf.fifo_initialized)
1239 lirc_buffer_free(&ir->rx->buf);
1240 i2c_set_clientdata(ir->rx->c, NULL);
1241 kfree(ir->rx);
1199 } 1242 }
1200 1243
1201 /* free memory */ 1244 /* Good-bye Tx */
1202 /* FIXME make tx, rx senitive */ 1245 i2c_set_clientdata(ir->tx->c, NULL);
1203 lirc_buffer_free(&rx->buf); 1246 kfree(ir->tx);
1204 mutex_unlock(&ir->ir_lock); 1247
1248 /* Good-bye IR */
1249 del_ir_device(ir);
1205 kfree(ir); 1250 kfree(ir);
1206 1251
1252 mutex_unlock(&ir_devices_lock);
1207 return 0; 1253 return 0;
1208} 1254}
1209 1255
1210static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) 1256
1257/* ir_devices_lock must be held */
1258static struct IR *find_ir_device_by_adapter(struct i2c_adapter *adapter)
1211{ 1259{
1260 int i;
1212 struct IR *ir = NULL; 1261 struct IR *ir = NULL;
1262
1263 for (i = 0; i < MAX_IRCTL_DEVICES; i++)
1264 if (ir_devices[i] != NULL &&
1265 ir_devices[i]->adapter == adapter) {
1266 ir = ir_devices[i];
1267 break;
1268 }
1269
1270 return ir;
1271}
1272
1273static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
1274{
1275 struct IR *ir;
1213 struct i2c_adapter *adap = client->adapter; 1276 struct i2c_adapter *adap = client->adapter;
1214 int ret; 1277 int ret;
1215 int have_rx = 0, have_tx = 0; 1278 bool tx_probe = false;
1216 1279
1217 dprintk("%s: %s on i2c-%d (%s), client addr=0x%02x\n", 1280 dprintk("%s: %s on i2c-%d (%s), client addr=0x%02x\n",
1218 __func__, id->name, adap->nr, adap->name, client->addr); 1281 __func__, id->name, adap->nr, adap->name, client->addr);
1219 1282
1220 /* 1283 /*
1221 * FIXME - This probe function probes both the Tx and Rx 1284 * The IR receiver is at i2c address 0x71.
1222 * addresses of the IR microcontroller. 1285 * The IR transmitter is at i2c address 0x70.
1223 *
1224 * However, the I2C subsystem is passing along one I2C client at a
1225 * time, based on matches to the ir_transceiver_id[] table above.
1226 * The expectation is that each i2c_client address will be probed
1227 * individually by drivers so the I2C subsystem can mark all client
1228 * addresses as claimed or not.
1229 *
1230 * This probe routine causes only one of the client addresses, TX or RX,
1231 * to be claimed. This will cause a problem if the I2C subsystem is
1232 * subsequently triggered to probe unclaimed clients again.
1233 */
1234 /*
1235 * The external IR receiver is at i2c address 0x71.
1236 * The IR transmitter is at 0x70.
1237 */ 1286 */
1238 1287
1239 if (id->driver_data & ID_FLAG_TX) { 1288 if (id->driver_data & ID_FLAG_TX)
1240 have_tx = 1; 1289 tx_probe = true;
1241 } else if (!disable_rx) { 1290 else if (tx_only) /* module option */
1242 have_rx = 1;
1243 } else {
1244 return -ENXIO; 1291 return -ENXIO;
1245 }
1246 1292
1247 printk(KERN_INFO "lirc_zilog: chip found with %s\n", 1293 zilog_info("%s: probing IR %s on %s (i2c-%d)\n",
1248 have_rx && have_tx ? "RX and TX" : 1294 __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
1249 have_rx ? "RX only" : "TX only");
1250 1295
1251 ir = kzalloc(sizeof(struct IR), GFP_KERNEL); 1296 mutex_lock(&ir_devices_lock);
1252 if (!ir)
1253 goto out_nomem;
1254 1297
1255 if (have_tx) { 1298 /* Use a single struct IR instance for both the Rx and Tx functions */
1256 ir->tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL); 1299 ir = find_ir_device_by_adapter(adap);
1257 if (ir->tx != NULL) { 1300 if (ir == NULL) {
1258 ir->tx->c = client; 1301 ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
1259 ir->tx->need_boot = 1; 1302 if (ir == NULL) {
1260 ir->tx->post_tx_ready_poll = 1303 ret = -ENOMEM;
1261 (id->driver_data & ID_FLAG_HDPVR) ? false : true; 1304 goto out_no_ir;
1262 } 1305 }
1306 /* store for use in ir_probe() again, and open() later on */
1307 ret = add_ir_device(ir);
1308 if (ret)
1309 goto out_free_ir;
1310
1311 ir->adapter = adap;
1312 mutex_init(&ir->ir_lock);
1313
1314 /* set lirc_dev stuff */
1315 memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver));
1316 ir->l.minor = minor; /* module option */
1317 ir->l.code_length = 13;
1318 ir->l.rbuf = NULL;
1319 ir->l.fops = &lirc_fops;
1320 ir->l.data = ir;
1321 ir->l.dev = &adap->dev;
1322 ir->l.sample_rate = 0;
1263 } 1323 }
1264 1324
1265 if (have_rx) { 1325 if (tx_probe) {
1266 ir->rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL); 1326 /* Set up a struct IR_tx instance */
1327 ir->tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL);
1328 if (ir->tx == NULL) {
1329 ret = -ENOMEM;
1330 goto out_free_xx;
1331 }
1267 1332
1333 ir->tx->c = client;
1334 ir->tx->need_boot = 1;
1335 ir->tx->post_tx_ready_poll =
1336 (id->driver_data & ID_FLAG_HDPVR) ? false : true;
1337 } else {
1338 /* Set up a struct IR_rx instance */
1339 ir->rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL);
1268 if (ir->rx == NULL) { 1340 if (ir->rx == NULL) {
1269 ret = -ENOMEM; 1341 ret = -ENOMEM;
1270 } else { 1342 goto out_free_xx;
1271 ir->rx->c = client;
1272 ir->rx->hdpvr_data_fmt =
1273 (id->driver_data & ID_FLAG_HDPVR) ? true : false;
1274 mutex_init(&ir->rx->buf_lock);
1275 ret = lirc_buffer_init(&ir->rx->buf, 2, BUFLEN / 2);
1276 } 1343 }
1277 1344
1278 if (ret && (ir->rx != NULL)) { 1345 ret = lirc_buffer_init(&ir->rx->buf, 2, BUFLEN / 2);
1279 kfree(ir->rx); 1346 if (ret)
1280 ir->rx = NULL; 1347 goto out_free_xx;
1281 }
1282 }
1283 1348
1284 mutex_init(&ir->ir_lock); 1349 mutex_init(&ir->rx->buf_lock);
1350 ir->rx->c = client;
1351 ir->rx->hdpvr_data_fmt =
1352 (id->driver_data & ID_FLAG_HDPVR) ? true : false;
1285 1353
1286 memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); 1354 /* set lirc_dev stuff */
1287 ir->l.minor = -1; 1355 ir->l.rbuf = &ir->rx->buf;
1356 }
1288 1357
1289 /* I2C attach to device */
1290 i2c_set_clientdata(client, ir); 1358 i2c_set_clientdata(client, ir);
1291 1359
1360 /* Proceed only if we have the required Tx and Rx clients ready to go */
1361 if (ir->tx == NULL ||
1362 (ir->rx == NULL && !tx_only)) {
1363 zilog_info("%s: probe of IR %s on %s (i2c-%d) done, waiting on "
1364 "IR %s\n", __func__, tx_probe ? "Tx" : "Rx",
1365 adap->name, adap->nr, tx_probe ? "Rx" : "Tx");
1366 goto out_ok;
1367 }
1368
1292 /* initialise RX device */ 1369 /* initialise RX device */
1293 if (ir->rx != NULL) { 1370 if (ir->rx != NULL) {
1294 DECLARE_COMPLETION(tn); 1371 DECLARE_COMPLETION(tn);
@@ -1298,35 +1375,23 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
1298 ir->rx->task = kthread_run(lirc_thread, ir, "lirc_zilog"); 1375 ir->rx->task = kthread_run(lirc_thread, ir, "lirc_zilog");
1299 if (IS_ERR(ir->rx->task)) { 1376 if (IS_ERR(ir->rx->task)) {
1300 ret = PTR_ERR(ir->rx->task); 1377 ret = PTR_ERR(ir->rx->task);
1301 zilog_error("lirc_register_driver: cannot run " 1378 zilog_error("%s: could not start IR Rx polling thread"
1302 "poll thread %d\n", ret); 1379 "\n", __func__);
1303 goto err; 1380 goto out_free_xx;
1304 } 1381 }
1305 wait_for_completion(&tn); 1382 wait_for_completion(&tn);
1306 ir->rx->t_notify = NULL; 1383 ir->rx->t_notify = NULL;
1307 } 1384 }
1308 1385
1309 /* set lirc_dev stuff */
1310 ir->l.code_length = 13;
1311 ir->l.rbuf = (ir->rx == NULL) ? NULL : &ir->rx->buf;
1312 ir->l.fops = &lirc_fops;
1313 ir->l.data = ir;
1314 ir->l.minor = minor;
1315 ir->l.dev = &adap->dev;
1316 ir->l.sample_rate = 0;
1317
1318 /* register with lirc */ 1386 /* register with lirc */
1319 ir->l.minor = lirc_register_driver(&ir->l); 1387 ir->l.minor = lirc_register_driver(&ir->l);
1320 if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) { 1388 if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) {
1321 zilog_error("ir_attach: \"minor\" must be between 0 and %d " 1389 zilog_error("%s: \"minor\" must be between 0 and %d (%d)!\n",
1322 "(%d)!\n", MAX_IRCTL_DEVICES-1, ir->l.minor); 1390 __func__, MAX_IRCTL_DEVICES-1, ir->l.minor);
1323 ret = -EBADRQC; 1391 ret = -EBADRQC;
1324 goto err; 1392 goto out_free_thread;
1325 } 1393 }
1326 1394
1327 /* store this for getting back in open() later on */
1328 ir_devices[ir->l.minor] = ir;
1329
1330 /* 1395 /*
1331 * if we have the tx device, load the 'firmware'. We do this 1396 * if we have the tx device, load the 'firmware'. We do this
1332 * after registering with lirc as otherwise hotplug seems to take 1397 * after registering with lirc as otherwise hotplug seems to take
@@ -1336,25 +1401,39 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
1336 /* Special TX init */ 1401 /* Special TX init */
1337 ret = tx_init(ir->tx); 1402 ret = tx_init(ir->tx);
1338 if (ret != 0) 1403 if (ret != 0)
1339 goto err; 1404 goto out_unregister;
1340 } 1405 }
1341 1406
1407out_ok:
1408 mutex_unlock(&ir_devices_lock);
1342 return 0; 1409 return 0;
1343 1410
1344err: 1411out_unregister:
1345 /* FIXME - memory deallocation for all error cases needs work */ 1412 lirc_unregister_driver(ir->l.minor);
1346 /* undo everything, hopefully... */ 1413out_free_thread:
1347 if (ir->rx != NULL) 1414 destroy_rx_kthread(ir->rx);
1348 ir_remove(ir->rx->c); 1415out_free_xx:
1349 if (ir->tx != NULL) 1416 if (ir->rx != NULL) {
1350 ir_remove(ir->tx->c); 1417 if (ir->rx->buf.fifo_initialized)
1351 return ret; 1418 lirc_buffer_free(&ir->rx->buf);
1352 1419 if (ir->rx->c != NULL)
1353out_nomem: 1420 i2c_set_clientdata(ir->rx->c, NULL);
1354 /* FIXME - memory deallocation for all error cases needs work */ 1421 kfree(ir->rx);
1355 zilog_error("memory allocation failure\n"); 1422 }
1423 if (ir->tx != NULL) {
1424 if (ir->tx->c != NULL)
1425 i2c_set_clientdata(ir->tx->c, NULL);
1426 kfree(ir->tx);
1427 }
1428out_free_ir:
1429 del_ir_device(ir);
1356 kfree(ir); 1430 kfree(ir);
1357 return -ENOMEM; 1431out_no_ir:
1432 zilog_error("%s: probing IR %s on %s (i2c-%d) failed with %d\n",
1433 __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr,
1434 ret);
1435 mutex_unlock(&ir_devices_lock);
1436 return ret;
1358} 1437}
1359 1438
1360static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg) 1439static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg)
@@ -1370,6 +1449,7 @@ static int __init zilog_init(void)
1370 zilog_notify("Zilog/Hauppauge IR driver initializing\n"); 1449 zilog_notify("Zilog/Hauppauge IR driver initializing\n");
1371 1450
1372 mutex_init(&tx_data_lock); 1451 mutex_init(&tx_data_lock);
1452 mutex_init(&ir_devices_lock);
1373 1453
1374 request_module("firmware_class"); 1454 request_module("firmware_class");
1375 1455
@@ -1406,5 +1486,5 @@ MODULE_PARM_DESC(minor, "Preferred minor device number");
1406module_param(debug, bool, 0644); 1486module_param(debug, bool, 0644);
1407MODULE_PARM_DESC(debug, "Enable debugging messages"); 1487MODULE_PARM_DESC(debug, "Enable debugging messages");
1408 1488
1409module_param(disable_rx, bool, 0644); 1489module_param(tx_only, bool, 0644);
1410MODULE_PARM_DESC(disable_rx, "Disable the IR receiver device"); 1490MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function");