Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] rc-core: allow calling rc_open with device not initialized

The device initialization completes only after calling
input_register_device(). However, rc_open() can be called while
the device is being registered by the input/evdev core. So, we
can't expect that rc_dev->initialized to be true.

Change the logic to don't require initialized == true at rc_open
and change the type of initialized to be atomic.

this way, we can check for it earlier where it is really needed,
without needing to lock the mutex just for testing it.

Tested with nuvoton_cir driver on a NUC5i7RYB with CIR integrated on it.

Reported-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

+23 -28
+21 -26
drivers/media/rc/rc-main.c
··· 13 13 */ 14 14 15 15 #include <media/rc-core.h> 16 + #include <linux/atomic.h> 16 17 #include <linux/spinlock.h> 17 18 #include <linux/delay.h> 18 19 #include <linux/input.h> ··· 724 723 return -EINVAL; 725 724 726 725 mutex_lock(&rdev->lock); 727 - if (!rdev->initialized) { 728 - rval = -EINVAL; 729 - goto unlock; 730 - } 731 726 732 727 if (!rdev->users++ && rdev->open != NULL) 733 728 rval = rdev->open(rdev); ··· 731 734 if (rval) 732 735 rdev->users--; 733 736 734 - unlock: 735 737 mutex_unlock(&rdev->lock); 736 738 737 739 return rval; ··· 875 879 if (!dev) 876 880 return -EINVAL; 877 881 882 + if (!atomic_read(&dev->initialized)) 883 + return -ERESTARTSYS; 884 + 878 885 mutex_lock(&dev->lock); 879 - if (!dev->initialized) { 880 - mutex_unlock(&dev->lock); 881 - return -EINVAL; 882 - } 883 886 884 887 if (fattr->type == RC_FILTER_NORMAL) { 885 888 enabled = dev->enabled_protocols; ··· 1059 1064 if (!dev) 1060 1065 return -EINVAL; 1061 1066 1067 + if (!atomic_read(&dev->initialized)) 1068 + return -ERESTARTSYS; 1069 + 1062 1070 if (fattr->type == RC_FILTER_NORMAL) { 1063 1071 IR_dprintk(1, "Normal protocol change requested\n"); 1064 1072 current_protocols = &dev->enabled_protocols; ··· 1082 1084 } 1083 1085 1084 1086 mutex_lock(&dev->lock); 1085 - if (!dev->initialized) { 1086 - rc = -EINVAL; 1087 - goto out; 1088 - } 1089 1087 1090 1088 old_protocols = *current_protocols; 1091 1089 new_protocols = old_protocols; ··· 1162 1168 if (!dev) 1163 1169 return -EINVAL; 1164 1170 1171 + if (!atomic_read(&dev->initialized)) 1172 + return -ERESTARTSYS; 1173 + 1165 1174 mutex_lock(&dev->lock); 1166 - if (!dev->initialized) { 1167 - mutex_unlock(&dev->lock); 1168 - return -EINVAL; 1169 - } 1170 1175 1171 1176 if (fattr->type == RC_FILTER_NORMAL) 1172 1177 filter = &dev->scancode_filter; ··· 1216 1223 if (!dev) 1217 1224 return -EINVAL; 1218 1225 1226 + if (!atomic_read(&dev->initialized)) 1227 + return -ERESTARTSYS; 1228 + 1219 1229 ret = kstrtoul(buf, 0, &val); 1220 1230 if (ret < 0) 1221 1231 return ret; ··· 1237 1241 return -EINVAL; 1238 1242 1239 1243 mutex_lock(&dev->lock); 1240 - if (!dev->initialized) { 1241 - ret = -EINVAL; 1242 - goto unlock; 1243 - } 1244 1244 1245 1245 new_filter = *filter; 1246 1246 if (fattr->mask) ··· 1423 1431 dev->minor = minor; 1424 1432 dev_set_name(&dev->dev, "rc%u", dev->minor); 1425 1433 dev_set_drvdata(&dev->dev, dev); 1434 + atomic_set(&dev->initialized, 0); 1426 1435 1427 1436 dev->dev.groups = dev->sysfs_groups; 1428 1437 dev->sysfs_groups[attr++] = &rc_dev_protocol_attr_grp; ··· 1448 1455 dev->input_dev->phys = dev->input_phys; 1449 1456 dev->input_dev->name = dev->input_name; 1450 1457 1451 - rc = input_register_device(dev->input_dev); 1452 - if (rc) 1453 - goto out_table; 1454 - 1455 1458 /* 1456 1459 * Default delay of 250ms is too short for some protocols, especially 1457 1460 * since the timeout is currently set to 250ms. Increase it to 500ms, ··· 1462 1473 * to do. 1463 1474 */ 1464 1475 dev->input_dev->rep[REP_PERIOD] = 125; 1476 + 1477 + /* rc_open will be called here */ 1478 + rc = input_register_device(dev->input_dev); 1479 + if (rc) 1480 + goto out_table; 1465 1481 1466 1482 path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); 1467 1483 dev_info(&dev->dev, "%s as %s\n", ··· 1491 1497 dev->enabled_protocols = rc_type; 1492 1498 } 1493 1499 1500 + /* Allow the RC sysfs nodes to be accessible */ 1494 1501 mutex_lock(&dev->lock); 1495 - dev->initialized = true; 1502 + atomic_set(&dev->initialized, 1); 1496 1503 mutex_unlock(&dev->lock); 1497 1504 1498 1505 IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n",
+2 -2
include/media/rc-core.h
··· 60 60 /** 61 61 * struct rc_dev - represents a remote control device 62 62 * @dev: driver model's view of this device 63 - * @initialized: true if the device init has completed 63 + * @initialized: 1 if the device init has completed, 0 otherwise 64 64 * @sysfs_groups: sysfs attribute groups 65 65 * @input_name: name of the input child device 66 66 * @input_phys: physical path to the input child device ··· 122 122 */ 123 123 struct rc_dev { 124 124 struct device dev; 125 - bool initialized; 125 + atomic_t initialized; 126 126 const struct attribute_group *sysfs_groups[5]; 127 127 const char *input_name; 128 128 const char *input_phys;