diff options
-rw-r--r-- | drivers/staging/lirc/lirc_zilog.c | 344 |
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 */ |
103 | static struct mutex ir_devices_lock; | ||
102 | static struct IR *ir_devices[MAX_IRCTL_DEVICES]; | 104 | static 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 */ |
136 | static int debug; /* debug output */ | 139 | static int debug; /* debug output */ |
137 | static int disable_rx; /* disable RX device */ | 140 | static int tx_only; /* only handle the IR Tx function */ |
138 | static int minor = -1; /* minor number */ | 141 | static 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 */ | ||
1063 | static 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 | ||
1162 | static int ir_remove(struct i2c_client *client) | 1172 | /* FIXME - investigate if this is the proper way to shutdown a kthread */ |
1173 | static 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); | 1195 | static 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; | 1209 | static 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 | |||
1220 | static 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 | ||
1210 | static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | 1256 | |
1257 | /* ir_devices_lock must be held */ | ||
1258 | static 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 | |||
1273 | static 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 | ||
1407 | out_ok: | ||
1408 | mutex_unlock(&ir_devices_lock); | ||
1342 | return 0; | 1409 | return 0; |
1343 | 1410 | ||
1344 | err: | 1411 | out_unregister: |
1345 | /* FIXME - memory deallocation for all error cases needs work */ | 1412 | lirc_unregister_driver(ir->l.minor); |
1346 | /* undo everything, hopefully... */ | 1413 | out_free_thread: |
1347 | if (ir->rx != NULL) | 1414 | destroy_rx_kthread(ir->rx); |
1348 | ir_remove(ir->rx->c); | 1415 | out_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) | |
1353 | out_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 | } | ||
1428 | out_free_ir: | ||
1429 | del_ir_device(ir); | ||
1356 | kfree(ir); | 1430 | kfree(ir); |
1357 | return -ENOMEM; | 1431 | out_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 | ||
1360 | static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg) | 1439 | static 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"); | |||
1406 | module_param(debug, bool, 0644); | 1486 | module_param(debug, bool, 0644); |
1407 | MODULE_PARM_DESC(debug, "Enable debugging messages"); | 1487 | MODULE_PARM_DESC(debug, "Enable debugging messages"); |
1408 | 1488 | ||
1409 | module_param(disable_rx, bool, 0644); | 1489 | module_param(tx_only, bool, 0644); |
1410 | MODULE_PARM_DESC(disable_rx, "Disable the IR receiver device"); | 1490 | MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function"); |