Skip to content

Commit 7bba9e8

Browse files
andy-shevchanwoochoi
authored andcommitted
extcon: Use unique number for the extcon device ID
The use of atomic variable is still racy when we do not control which device has been unregistered and there is a (theoretical) possibility of the overflow that may cause a duplicate extcon device ID number to be allocated next time a device is registered. Replace above mentioned approach by using IDA framework. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
1 parent 566825a commit 7bba9e8

2 files changed

Lines changed: 15 additions & 3 deletions

File tree

drivers/extcon/extcon.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <linux/module.h>
1818
#include <linux/types.h>
19+
#include <linux/idr.h>
1920
#include <linux/init.h>
2021
#include <linux/device.h>
2122
#include <linux/fs.h>
@@ -238,6 +239,7 @@ struct extcon_cable {
238239

239240
static struct class *extcon_class;
240241

242+
static DEFINE_IDA(extcon_dev_ids);
241243
static LIST_HEAD(extcon_dev_list);
242244
static DEFINE_MUTEX(extcon_dev_list_lock);
243245

@@ -1248,7 +1250,6 @@ static int extcon_alloc_groups(struct extcon_dev *edev)
12481250
int extcon_dev_register(struct extcon_dev *edev)
12491251
{
12501252
int ret, index = 0;
1251-
static atomic_t edev_no = ATOMIC_INIT(-1);
12521253

12531254
ret = create_extcon_class();
12541255
if (ret < 0)
@@ -1275,8 +1276,14 @@ int extcon_dev_register(struct extcon_dev *edev)
12751276
"extcon device name is null\n");
12761277
return -EINVAL;
12771278
}
1278-
dev_set_name(&edev->dev, "extcon%lu",
1279-
(unsigned long)atomic_inc_return(&edev_no));
1279+
1280+
ret = ida_alloc(&extcon_dev_ids, GFP_KERNEL);
1281+
if (ret < 0)
1282+
return ret;
1283+
1284+
edev->id = ret;
1285+
1286+
dev_set_name(&edev->dev, "extcon%d", edev->id);
12801287

12811288
ret = extcon_alloc_cables(edev);
12821289
if (ret < 0)
@@ -1339,6 +1346,7 @@ int extcon_dev_register(struct extcon_dev *edev)
13391346
if (edev->max_supported)
13401347
kfree(edev->cables);
13411348
err_alloc_cables:
1349+
ida_free(&extcon_dev_ids, edev->id);
13421350

13431351
return ret;
13441352
}
@@ -1367,6 +1375,8 @@ void extcon_dev_unregister(struct extcon_dev *edev)
13671375
return;
13681376
}
13691377

1378+
ida_free(&extcon_dev_ids, edev->id);
1379+
13701380
device_unregister(&edev->dev);
13711381

13721382
if (edev->mutually_exclusive && edev->max_supported) {

drivers/extcon/extcon.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
2121
* can be no simultaneous connections.
2222
* @dev: Device of this extcon.
23+
* @id: Unique device ID of this extcon.
2324
* @state: Attach/detach state of this extcon. Do not provide at
2425
* register-time.
2526
* @nh_all: Notifier for the state change events for all supported
@@ -46,6 +47,7 @@ struct extcon_dev {
4647

4748
/* Internal data. Please do not set. */
4849
struct device dev;
50+
unsigned int id;
4951
struct raw_notifier_head nh_all;
5052
struct raw_notifier_head *nh;
5153
struct list_head entry;

0 commit comments

Comments
 (0)