diff options
Diffstat (limited to 'drivers/media/rc/imon.c')
| -rw-r--r-- | drivers/media/rc/imon.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index ebd68edf5b24..8fc0f081b470 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | #define MOD_AUTHOR "Jarod Wilson <jarod@wilsonet.com>" | 46 | #define MOD_AUTHOR "Jarod Wilson <jarod@wilsonet.com>" |
| 47 | #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" | 47 | #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" |
| 48 | #define MOD_NAME "imon" | 48 | #define MOD_NAME "imon" |
| 49 | #define MOD_VERSION "0.9.2" | 49 | #define MOD_VERSION "0.9.3" |
| 50 | 50 | ||
| 51 | #define DISPLAY_MINOR_BASE 144 | 51 | #define DISPLAY_MINOR_BASE 144 |
| 52 | #define DEVICE_NAME "lcd%d" | 52 | #define DEVICE_NAME "lcd%d" |
| @@ -460,8 +460,9 @@ static int display_close(struct inode *inode, struct file *file) | |||
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | /** | 462 | /** |
| 463 | * Sends a packet to the device -- this function must be called | 463 | * Sends a packet to the device -- this function must be called with |
| 464 | * with ictx->lock held. | 464 | * ictx->lock held, or its unlock/lock sequence while waiting for tx |
| 465 | * to complete can/will lead to a deadlock. | ||
| 465 | */ | 466 | */ |
| 466 | static int send_packet(struct imon_context *ictx) | 467 | static int send_packet(struct imon_context *ictx) |
| 467 | { | 468 | { |
| @@ -991,12 +992,21 @@ static void imon_touch_display_timeout(unsigned long data) | |||
| 991 | * the iMON remotes, and those used by the Windows MCE remotes (which is | 992 | * the iMON remotes, and those used by the Windows MCE remotes (which is |
| 992 | * really just RC-6), but only one or the other at a time, as the signals | 993 | * really just RC-6), but only one or the other at a time, as the signals |
| 993 | * are decoded onboard the receiver. | 994 | * are decoded onboard the receiver. |
| 995 | * | ||
| 996 | * This function gets called two different ways, one way is from | ||
| 997 | * rc_register_device, for initial protocol selection/setup, and the other is | ||
| 998 | * via a userspace-initiated protocol change request, either by direct sysfs | ||
| 999 | * prodding or by something like ir-keytable. In the rc_register_device case, | ||
| 1000 | * the imon context lock is already held, but when initiated from userspace, | ||
| 1001 | * it is not, so we must acquire it prior to calling send_packet, which | ||
| 1002 | * requires that the lock is held. | ||
| 994 | */ | 1003 | */ |
| 995 | static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type) | 1004 | static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type) |
| 996 | { | 1005 | { |
| 997 | int retval; | 1006 | int retval; |
| 998 | struct imon_context *ictx = rc->priv; | 1007 | struct imon_context *ictx = rc->priv; |
| 999 | struct device *dev = ictx->dev; | 1008 | struct device *dev = ictx->dev; |
| 1009 | bool unlock = false; | ||
| 1000 | unsigned char ir_proto_packet[] = { | 1010 | unsigned char ir_proto_packet[] = { |
| 1001 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; | 1011 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; |
| 1002 | 1012 | ||
| @@ -1029,6 +1039,11 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type) | |||
| 1029 | 1039 | ||
| 1030 | memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); | 1040 | memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); |
| 1031 | 1041 | ||
| 1042 | if (!mutex_is_locked(&ictx->lock)) { | ||
| 1043 | unlock = true; | ||
| 1044 | mutex_lock(&ictx->lock); | ||
| 1045 | } | ||
| 1046 | |||
| 1032 | retval = send_packet(ictx); | 1047 | retval = send_packet(ictx); |
| 1033 | if (retval) | 1048 | if (retval) |
| 1034 | goto out; | 1049 | goto out; |
| @@ -1037,6 +1052,9 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type) | |||
| 1037 | ictx->pad_mouse = false; | 1052 | ictx->pad_mouse = false; |
| 1038 | 1053 | ||
| 1039 | out: | 1054 | out: |
| 1055 | if (unlock) | ||
| 1056 | mutex_unlock(&ictx->lock); | ||
| 1057 | |||
| 1040 | return retval; | 1058 | return retval; |
| 1041 | } | 1059 | } |
| 1042 | 1060 | ||
| @@ -2134,6 +2152,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) | |||
| 2134 | goto rdev_setup_failed; | 2152 | goto rdev_setup_failed; |
| 2135 | } | 2153 | } |
| 2136 | 2154 | ||
| 2155 | mutex_unlock(&ictx->lock); | ||
| 2137 | return ictx; | 2156 | return ictx; |
| 2138 | 2157 | ||
| 2139 | rdev_setup_failed: | 2158 | rdev_setup_failed: |
| @@ -2205,6 +2224,7 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf, | |||
| 2205 | goto urb_submit_failed; | 2224 | goto urb_submit_failed; |
| 2206 | } | 2225 | } |
| 2207 | 2226 | ||
| 2227 | mutex_unlock(&ictx->lock); | ||
| 2208 | return ictx; | 2228 | return ictx; |
| 2209 | 2229 | ||
| 2210 | urb_submit_failed: | 2230 | urb_submit_failed: |
| @@ -2299,6 +2319,8 @@ static int __devinit imon_probe(struct usb_interface *interface, | |||
| 2299 | usb_set_intfdata(interface, ictx); | 2319 | usb_set_intfdata(interface, ictx); |
| 2300 | 2320 | ||
| 2301 | if (ifnum == 0) { | 2321 | if (ifnum == 0) { |
| 2322 | mutex_lock(&ictx->lock); | ||
| 2323 | |||
| 2302 | if (product == 0xffdc && ictx->rf_device) { | 2324 | if (product == 0xffdc && ictx->rf_device) { |
| 2303 | sysfs_err = sysfs_create_group(&interface->dev.kobj, | 2325 | sysfs_err = sysfs_create_group(&interface->dev.kobj, |
| 2304 | &imon_rf_attr_group); | 2326 | &imon_rf_attr_group); |
| @@ -2309,13 +2331,14 @@ static int __devinit imon_probe(struct usb_interface *interface, | |||
| 2309 | 2331 | ||
| 2310 | if (ictx->display_supported) | 2332 | if (ictx->display_supported) |
| 2311 | imon_init_display(ictx, interface); | 2333 | imon_init_display(ictx, interface); |
| 2334 | |||
| 2335 | mutex_unlock(&ictx->lock); | ||
| 2312 | } | 2336 | } |
| 2313 | 2337 | ||
| 2314 | dev_info(dev, "iMON device (%04x:%04x, intf%d) on " | 2338 | dev_info(dev, "iMON device (%04x:%04x, intf%d) on " |
| 2315 | "usb<%d:%d> initialized\n", vendor, product, ifnum, | 2339 | "usb<%d:%d> initialized\n", vendor, product, ifnum, |
| 2316 | usbdev->bus->busnum, usbdev->devnum); | 2340 | usbdev->bus->busnum, usbdev->devnum); |
| 2317 | 2341 | ||
| 2318 | mutex_unlock(&ictx->lock); | ||
| 2319 | mutex_unlock(&driver_lock); | 2342 | mutex_unlock(&driver_lock); |
| 2320 | 2343 | ||
| 2321 | return 0; | 2344 | return 0; |
