diff options
-rw-r--r-- | drivers/media/rc/rc-main.c | 47 | ||||
-rw-r--r-- | include/media/rc-core.h | 7 |
2 files changed, 46 insertions, 8 deletions
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index a2706648e365..0d4fcd911b8c 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c | |||
@@ -749,6 +749,9 @@ static struct { | |||
749 | * it is trigged by reading /sys/class/rc/rc?/protocols. | 749 | * it is trigged by reading /sys/class/rc/rc?/protocols. |
750 | * It returns the protocol names of supported protocols. | 750 | * It returns the protocol names of supported protocols. |
751 | * Enabled protocols are printed in brackets. | 751 | * Enabled protocols are printed in brackets. |
752 | * | ||
753 | * dev->lock is taken to guard against races between device | ||
754 | * registration, store_protocols and show_protocols. | ||
752 | */ | 755 | */ |
753 | static ssize_t show_protocols(struct device *device, | 756 | static ssize_t show_protocols(struct device *device, |
754 | struct device_attribute *mattr, char *buf) | 757 | struct device_attribute *mattr, char *buf) |
@@ -762,6 +765,8 @@ static ssize_t show_protocols(struct device *device, | |||
762 | if (!dev) | 765 | if (!dev) |
763 | return -EINVAL; | 766 | return -EINVAL; |
764 | 767 | ||
768 | mutex_lock(&dev->lock); | ||
769 | |||
765 | if (dev->driver_type == RC_DRIVER_SCANCODE) { | 770 | if (dev->driver_type == RC_DRIVER_SCANCODE) { |
766 | enabled = dev->rc_map.rc_type; | 771 | enabled = dev->rc_map.rc_type; |
767 | allowed = dev->allowed_protos; | 772 | allowed = dev->allowed_protos; |
@@ -784,6 +789,9 @@ static ssize_t show_protocols(struct device *device, | |||
784 | if (tmp != buf) | 789 | if (tmp != buf) |
785 | tmp--; | 790 | tmp--; |
786 | *tmp = '\n'; | 791 | *tmp = '\n'; |
792 | |||
793 | mutex_unlock(&dev->lock); | ||
794 | |||
787 | return tmp + 1 - buf; | 795 | return tmp + 1 - buf; |
788 | } | 796 | } |
789 | 797 | ||
@@ -802,6 +810,9 @@ static ssize_t show_protocols(struct device *device, | |||
802 | * Writing "none" will disable all protocols. | 810 | * Writing "none" will disable all protocols. |
803 | * Returns -EINVAL if an invalid protocol combination or unknown protocol name | 811 | * Returns -EINVAL if an invalid protocol combination or unknown protocol name |
804 | * is used, otherwise @len. | 812 | * is used, otherwise @len. |
813 | * | ||
814 | * dev->lock is taken to guard against races between device | ||
815 | * registration, store_protocols and show_protocols. | ||
805 | */ | 816 | */ |
806 | static ssize_t store_protocols(struct device *device, | 817 | static ssize_t store_protocols(struct device *device, |
807 | struct device_attribute *mattr, | 818 | struct device_attribute *mattr, |
@@ -815,18 +826,22 @@ static ssize_t store_protocols(struct device *device, | |||
815 | u64 mask; | 826 | u64 mask; |
816 | int rc, i, count = 0; | 827 | int rc, i, count = 0; |
817 | unsigned long flags; | 828 | unsigned long flags; |
829 | ssize_t ret; | ||
818 | 830 | ||
819 | /* Device is being removed */ | 831 | /* Device is being removed */ |
820 | if (!dev) | 832 | if (!dev) |
821 | return -EINVAL; | 833 | return -EINVAL; |
822 | 834 | ||
835 | mutex_lock(&dev->lock); | ||
836 | |||
823 | if (dev->driver_type == RC_DRIVER_SCANCODE) | 837 | if (dev->driver_type == RC_DRIVER_SCANCODE) |
824 | type = dev->rc_map.rc_type; | 838 | type = dev->rc_map.rc_type; |
825 | else if (dev->raw) | 839 | else if (dev->raw) |
826 | type = dev->raw->enabled_protocols; | 840 | type = dev->raw->enabled_protocols; |
827 | else { | 841 | else { |
828 | IR_dprintk(1, "Protocol switching not supported\n"); | 842 | IR_dprintk(1, "Protocol switching not supported\n"); |
829 | return -EINVAL; | 843 | ret = -EINVAL; |
844 | goto out; | ||
830 | } | 845 | } |
831 | 846 | ||
832 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { | 847 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { |
@@ -860,7 +875,8 @@ static ssize_t store_protocols(struct device *device, | |||
860 | } | 875 | } |
861 | if (i == ARRAY_SIZE(proto_names)) { | 876 | if (i == ARRAY_SIZE(proto_names)) { |
862 | IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); | 877 | IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); |
863 | return -EINVAL; | 878 | ret = -EINVAL; |
879 | goto out; | ||
864 | } | 880 | } |
865 | count++; | 881 | count++; |
866 | } | 882 | } |
@@ -875,7 +891,8 @@ static ssize_t store_protocols(struct device *device, | |||
875 | 891 | ||
876 | if (!count) { | 892 | if (!count) { |
877 | IR_dprintk(1, "Protocol not specified\n"); | 893 | IR_dprintk(1, "Protocol not specified\n"); |
878 | return -EINVAL; | 894 | ret = -EINVAL; |
895 | goto out; | ||
879 | } | 896 | } |
880 | 897 | ||
881 | if (dev->change_protocol) { | 898 | if (dev->change_protocol) { |
@@ -883,7 +900,8 @@ static ssize_t store_protocols(struct device *device, | |||
883 | if (rc < 0) { | 900 | if (rc < 0) { |
884 | IR_dprintk(1, "Error setting protocols to 0x%llx\n", | 901 | IR_dprintk(1, "Error setting protocols to 0x%llx\n", |
885 | (long long)type); | 902 | (long long)type); |
886 | return -EINVAL; | 903 | ret = -EINVAL; |
904 | goto out; | ||
887 | } | 905 | } |
888 | } | 906 | } |
889 | 907 | ||
@@ -898,7 +916,11 @@ static ssize_t store_protocols(struct device *device, | |||
898 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", | 916 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", |
899 | (long long)type); | 917 | (long long)type); |
900 | 918 | ||
901 | return len; | 919 | ret = len; |
920 | |||
921 | out: | ||
922 | mutex_unlock(&dev->lock); | ||
923 | return ret; | ||
902 | } | 924 | } |
903 | 925 | ||
904 | static void rc_dev_release(struct device *device) | 926 | static void rc_dev_release(struct device *device) |
@@ -974,6 +996,7 @@ struct rc_dev *rc_allocate_device(void) | |||
974 | 996 | ||
975 | spin_lock_init(&dev->rc_map.lock); | 997 | spin_lock_init(&dev->rc_map.lock); |
976 | spin_lock_init(&dev->keylock); | 998 | spin_lock_init(&dev->keylock); |
999 | mutex_init(&dev->lock); | ||
977 | setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); | 1000 | setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); |
978 | 1001 | ||
979 | dev->dev.type = &rc_dev_type; | 1002 | dev->dev.type = &rc_dev_type; |
@@ -1019,12 +1042,21 @@ int rc_register_device(struct rc_dev *dev) | |||
1019 | if (dev->close) | 1042 | if (dev->close) |
1020 | dev->input_dev->close = ir_close; | 1043 | dev->input_dev->close = ir_close; |
1021 | 1044 | ||
1045 | /* | ||
1046 | * Take the lock here, as the device sysfs node will appear | ||
1047 | * when device_add() is called, which may trigger an ir-keytable udev | ||
1048 | * rule, which will in turn call show_protocols and access either | ||
1049 | * dev->rc_map.rc_type or dev->raw->enabled_protocols before it has | ||
1050 | * been initialized. | ||
1051 | */ | ||
1052 | mutex_lock(&dev->lock); | ||
1053 | |||
1022 | dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); | 1054 | dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); |
1023 | dev_set_name(&dev->dev, "rc%ld", dev->devno); | 1055 | dev_set_name(&dev->dev, "rc%ld", dev->devno); |
1024 | dev_set_drvdata(&dev->dev, dev); | 1056 | dev_set_drvdata(&dev->dev, dev); |
1025 | rc = device_add(&dev->dev); | 1057 | rc = device_add(&dev->dev); |
1026 | if (rc) | 1058 | if (rc) |
1027 | return rc; | 1059 | goto out_unlock; |
1028 | 1060 | ||
1029 | rc = ir_setkeytable(dev, rc_map); | 1061 | rc = ir_setkeytable(dev, rc_map); |
1030 | if (rc) | 1062 | if (rc) |
@@ -1058,6 +1090,7 @@ int rc_register_device(struct rc_dev *dev) | |||
1058 | if (rc < 0) | 1090 | if (rc < 0) |
1059 | goto out_input; | 1091 | goto out_input; |
1060 | } | 1092 | } |
1093 | mutex_unlock(&dev->lock); | ||
1061 | 1094 | ||
1062 | if (dev->change_protocol) { | 1095 | if (dev->change_protocol) { |
1063 | rc = dev->change_protocol(dev, rc_map->rc_type); | 1096 | rc = dev->change_protocol(dev, rc_map->rc_type); |
@@ -1083,6 +1116,8 @@ out_table: | |||
1083 | ir_free_table(&dev->rc_map); | 1116 | ir_free_table(&dev->rc_map); |
1084 | out_dev: | 1117 | out_dev: |
1085 | device_del(&dev->dev); | 1118 | device_del(&dev->dev); |
1119 | out_unlock: | ||
1120 | mutex_unlock(&dev->lock); | ||
1086 | return rc; | 1121 | return rc; |
1087 | } | 1122 | } |
1088 | EXPORT_SYMBOL_GPL(rc_register_device); | 1123 | EXPORT_SYMBOL_GPL(rc_register_device); |
diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 2963263f31e2..60536c74c1ea 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h | |||
@@ -40,10 +40,12 @@ enum rc_driver_type { | |||
40 | * @driver_name: name of the hardware driver which registered this device | 40 | * @driver_name: name of the hardware driver which registered this device |
41 | * @map_name: name of the default keymap | 41 | * @map_name: name of the default keymap |
42 | * @rc_map: current scan/key table | 42 | * @rc_map: current scan/key table |
43 | * @lock: used to ensure we've filled in all protocol details before | ||
44 | * anyone can call show_protocols or store_protocols | ||
43 | * @devno: unique remote control device number | 45 | * @devno: unique remote control device number |
44 | * @raw: additional data for raw pulse/space devices | 46 | * @raw: additional data for raw pulse/space devices |
45 | * @input_dev: the input child device used to communicate events to userspace | 47 | * @input_dev: the input child device used to communicate events to userspace |
46 | * @driver_type: specifies if protocol decoding is done in hardware or software | 48 | * @driver_type: specifies if protocol decoding is done in hardware or software |
47 | * @idle: used to keep track of RX state | 49 | * @idle: used to keep track of RX state |
48 | * @allowed_protos: bitmask with the supported RC_TYPE_* protocols | 50 | * @allowed_protos: bitmask with the supported RC_TYPE_* protocols |
49 | * @scanmask: some hardware decoders are not capable of providing the full | 51 | * @scanmask: some hardware decoders are not capable of providing the full |
@@ -86,7 +88,8 @@ struct rc_dev { | |||
86 | struct input_id input_id; | 88 | struct input_id input_id; |
87 | char *driver_name; | 89 | char *driver_name; |
88 | const char *map_name; | 90 | const char *map_name; |
89 | struct rc_map rc_map; | 91 | struct rc_map rc_map; |
92 | struct mutex lock; | ||
90 | unsigned long devno; | 93 | unsigned long devno; |
91 | struct ir_raw_event_ctrl *raw; | 94 | struct ir_raw_event_ctrl *raw; |
92 | struct input_dev *input_dev; | 95 | struct input_dev *input_dev; |