mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 11:37:47 +00:00
gpio fixes for v6.13-rc7
- fix resource leaks in error path in gpio-virtuser (and one consistent memory leak triggered on every device removal)) - fix the use-case of having multiple con_ids in a lookup table in gpio-virtuser which has never worked (despite being advertised) - don't allow rmdir() on configfs directories when they are in use in gpio-sim and gpio-virtuser - fix register offsets in gpio-loongson-64 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmeA4KEACgkQEacuoBRx 13LYrBAAwKM2OSgWdVjLoLDXQFfKXrjLzDjhZi4KBaDTZX2niphuyoKRKh5NBEMo 7w36v6Kp4YU6xrC4q1msInNXAYKuGrMfjghjQovPXbt1x1/adfSM916B0SyvgopM ObpgbiY2//LKgE7lPdMTdrliEJRTJluBKKnYA30DzdtWXyyFEaypH4xT+BgqQa09 biDJOVJEirHuMVgQxMJKz1hg/OMjyPTSknsUULF2rQIU2vt5XYCVu5QO7xAZ9LZe RPsJrRTZWkqYOopY5MPwV/g3yxFCuSC3ogfGP01ADPJGJOfJI5PyWi2OcWNTRctx q8ZvVgdfftP1hsBbjfQ90FAQzmmydk29FVNfvu+NJQkAbEi27YpYBG6g6atFE54e tJBAXZXgMdFEstaFp5PzD54w7EC302weAiKa9YW6cfdcABE0LrZQmmlkoGiwuwhU /HJyfkF+5BDl6zzMYpzfybqCZYlhJstzt4sSrO9Z5wfrfkpxaiD+rz1yZa7HSpnP lY7/TDundzarjMtUQfiussfT9EEYEpqsw8qx6LkiGW4JXqv7lujhUa1LaqNkDtkE R7bzAAWkijfHtEwPJM1ndKaJLhj5MjLDkLIORCdpar8crelh1chQsHBPDk/vCHXE qjNHG3dgZUQUmwD6AOFgbrtRlzxVa+AN2GxnFywAyBcGp7CmSE4= =aqRv -----END PGP SIGNATURE----- Merge tag 'gpio-fixes-for-v6.13-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux Pull gpio fixes from Bartosz Golaszewski: "There's one small fix for real HW - gpio-loongson. The rest concern two virtual testing drivers in which some issues were recently found and addressed: - fix resource leaks in error path in gpio-virtuser (and one consistent memory leak triggered on every device removal)) - fix the use-case of having multiple con_ids in a lookup table in gpio-virtuser which has never worked (despite being advertised) - don't allow rmdir() on configfs directories when they are in use in gpio-sim and gpio-virtuser - fix register offsets in gpio-loongson-64" * tag 'gpio-fixes-for-v6.13-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: loongson: Fix Loongson-2K2000 ACPI GPIO register offset gpio: sim: lock up configfs that an instantiated device depends on gpio: virtuser: lock up configfs that an instantiated device depends on gpio: virtuser: fix handling of multiple conn_ids in lookup table gpio: virtuser: fix missing lookup table cleanups
This commit is contained in:
commit
9d64558493
@ -237,9 +237,9 @@ static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data1 = {
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data2 = {
|
||||
.label = "ls2k2000_gpio",
|
||||
.mode = BIT_CTRL_MODE,
|
||||
.conf_offset = 0x84,
|
||||
.in_offset = 0x88,
|
||||
.out_offset = 0x80,
|
||||
.conf_offset = 0x4,
|
||||
.in_offset = 0x8,
|
||||
.out_offset = 0x0,
|
||||
};
|
||||
|
||||
static const struct loongson_gpio_chip_data loongson_gpio_ls3a5000_data = {
|
||||
|
@ -1027,6 +1027,30 @@ static void gpio_sim_device_deactivate(struct gpio_sim_device *dev)
|
||||
dev->pdev = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gpio_sim_device_lockup_configfs(struct gpio_sim_device *dev, bool lock)
|
||||
{
|
||||
struct configfs_subsystem *subsys = dev->group.cg_subsys;
|
||||
struct gpio_sim_bank *bank;
|
||||
struct gpio_sim_line *line;
|
||||
|
||||
/*
|
||||
* The device only needs to depend on leaf line entries. This is
|
||||
* sufficient to lock up all the configfs entries that the
|
||||
* instantiated, alive device depends on.
|
||||
*/
|
||||
list_for_each_entry(bank, &dev->bank_list, siblings) {
|
||||
list_for_each_entry(line, &bank->line_list, siblings) {
|
||||
if (lock)
|
||||
WARN_ON(configfs_depend_item_unlocked(
|
||||
subsys, &line->group.cg_item));
|
||||
else
|
||||
configfs_undepend_item_unlocked(
|
||||
&line->group.cg_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
gpio_sim_device_config_live_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
@ -1039,14 +1063,24 @@ gpio_sim_device_config_live_store(struct config_item *item,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
guard(mutex)(&dev->lock);
|
||||
if (live)
|
||||
gpio_sim_device_lockup_configfs(dev, true);
|
||||
|
||||
if (live == gpio_sim_device_is_live(dev))
|
||||
ret = -EPERM;
|
||||
else if (live)
|
||||
ret = gpio_sim_device_activate(dev);
|
||||
else
|
||||
gpio_sim_device_deactivate(dev);
|
||||
scoped_guard(mutex, &dev->lock) {
|
||||
if (live == gpio_sim_device_is_live(dev))
|
||||
ret = -EPERM;
|
||||
else if (live)
|
||||
ret = gpio_sim_device_activate(dev);
|
||||
else
|
||||
gpio_sim_device_deactivate(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Undepend is required only if device disablement (live == 0)
|
||||
* succeeds or if device enablement (live == 1) fails.
|
||||
*/
|
||||
if (live == !!ret)
|
||||
gpio_sim_device_lockup_configfs(dev, false);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
@ -1410,7 +1410,7 @@ gpio_virtuser_make_lookup_table(struct gpio_virtuser_device *dev)
|
||||
size_t num_entries = gpio_virtuser_get_lookup_count(dev);
|
||||
struct gpio_virtuser_lookup_entry *entry;
|
||||
struct gpio_virtuser_lookup *lookup;
|
||||
unsigned int i = 0;
|
||||
unsigned int i = 0, idx;
|
||||
|
||||
lockdep_assert_held(&dev->lock);
|
||||
|
||||
@ -1424,12 +1424,12 @@ gpio_virtuser_make_lookup_table(struct gpio_virtuser_device *dev)
|
||||
return -ENOMEM;
|
||||
|
||||
list_for_each_entry(lookup, &dev->lookup_list, siblings) {
|
||||
idx = 0;
|
||||
list_for_each_entry(entry, &lookup->entry_list, siblings) {
|
||||
table->table[i] =
|
||||
table->table[i++] =
|
||||
GPIO_LOOKUP_IDX(entry->key,
|
||||
entry->offset < 0 ? U16_MAX : entry->offset,
|
||||
lookup->con_id, i, entry->flags);
|
||||
i++;
|
||||
lookup->con_id, idx++, entry->flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1439,6 +1439,15 @@ gpio_virtuser_make_lookup_table(struct gpio_virtuser_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gpio_virtuser_remove_lookup_table(struct gpio_virtuser_device *dev)
|
||||
{
|
||||
gpiod_remove_lookup_table(dev->lookup_table);
|
||||
kfree(dev->lookup_table->dev_id);
|
||||
kfree(dev->lookup_table);
|
||||
dev->lookup_table = NULL;
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
gpio_virtuser_make_device_swnode(struct gpio_virtuser_device *dev)
|
||||
{
|
||||
@ -1487,10 +1496,8 @@ gpio_virtuser_device_activate(struct gpio_virtuser_device *dev)
|
||||
pdevinfo.fwnode = swnode;
|
||||
|
||||
ret = gpio_virtuser_make_lookup_table(dev);
|
||||
if (ret) {
|
||||
fwnode_remove_software_node(swnode);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto err_remove_swnode;
|
||||
|
||||
reinit_completion(&dev->probe_completion);
|
||||
dev->driver_bound = false;
|
||||
@ -1498,23 +1505,31 @@ gpio_virtuser_device_activate(struct gpio_virtuser_device *dev)
|
||||
|
||||
pdev = platform_device_register_full(&pdevinfo);
|
||||
if (IS_ERR(pdev)) {
|
||||
ret = PTR_ERR(pdev);
|
||||
bus_unregister_notifier(&platform_bus_type, &dev->bus_notifier);
|
||||
fwnode_remove_software_node(swnode);
|
||||
return PTR_ERR(pdev);
|
||||
goto err_remove_lookup_table;
|
||||
}
|
||||
|
||||
wait_for_completion(&dev->probe_completion);
|
||||
bus_unregister_notifier(&platform_bus_type, &dev->bus_notifier);
|
||||
|
||||
if (!dev->driver_bound) {
|
||||
platform_device_unregister(pdev);
|
||||
fwnode_remove_software_node(swnode);
|
||||
return -ENXIO;
|
||||
ret = -ENXIO;
|
||||
goto err_unregister_pdev;
|
||||
}
|
||||
|
||||
dev->pdev = pdev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_pdev:
|
||||
platform_device_unregister(pdev);
|
||||
err_remove_lookup_table:
|
||||
gpio_virtuser_remove_lookup_table(dev);
|
||||
err_remove_swnode:
|
||||
fwnode_remove_software_node(swnode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1526,10 +1541,33 @@ gpio_virtuser_device_deactivate(struct gpio_virtuser_device *dev)
|
||||
|
||||
swnode = dev_fwnode(&dev->pdev->dev);
|
||||
platform_device_unregister(dev->pdev);
|
||||
gpio_virtuser_remove_lookup_table(dev);
|
||||
fwnode_remove_software_node(swnode);
|
||||
dev->pdev = NULL;
|
||||
gpiod_remove_lookup_table(dev->lookup_table);
|
||||
kfree(dev->lookup_table);
|
||||
}
|
||||
|
||||
static void
|
||||
gpio_virtuser_device_lockup_configfs(struct gpio_virtuser_device *dev, bool lock)
|
||||
{
|
||||
struct configfs_subsystem *subsys = dev->group.cg_subsys;
|
||||
struct gpio_virtuser_lookup_entry *entry;
|
||||
struct gpio_virtuser_lookup *lookup;
|
||||
|
||||
/*
|
||||
* The device only needs to depend on leaf lookup entries. This is
|
||||
* sufficient to lock up all the configfs entries that the
|
||||
* instantiated, alive device depends on.
|
||||
*/
|
||||
list_for_each_entry(lookup, &dev->lookup_list, siblings) {
|
||||
list_for_each_entry(entry, &lookup->entry_list, siblings) {
|
||||
if (lock)
|
||||
WARN_ON(configfs_depend_item_unlocked(
|
||||
subsys, &entry->group.cg_item));
|
||||
else
|
||||
configfs_undepend_item_unlocked(
|
||||
&entry->group.cg_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@ -1544,15 +1582,24 @@ gpio_virtuser_device_config_live_store(struct config_item *item,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
guard(mutex)(&dev->lock);
|
||||
|
||||
if (live == gpio_virtuser_device_is_live(dev))
|
||||
return -EPERM;
|
||||
|
||||
if (live)
|
||||
ret = gpio_virtuser_device_activate(dev);
|
||||
else
|
||||
gpio_virtuser_device_deactivate(dev);
|
||||
gpio_virtuser_device_lockup_configfs(dev, true);
|
||||
|
||||
scoped_guard(mutex, &dev->lock) {
|
||||
if (live == gpio_virtuser_device_is_live(dev))
|
||||
ret = -EPERM;
|
||||
else if (live)
|
||||
ret = gpio_virtuser_device_activate(dev);
|
||||
else
|
||||
gpio_virtuser_device_deactivate(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Undepend is required only if device disablement (live == 0)
|
||||
* succeeds or if device enablement (live == 1) fails.
|
||||
*/
|
||||
if (live == !!ret)
|
||||
gpio_virtuser_device_lockup_configfs(dev, false);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user