diff options
| -rw-r--r-- | drivers/gpio/gpio-virtuser.c | 47 | 
1 files changed, 40 insertions, 7 deletions
diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c index d6244f0d3bc7..e89f299f2140 100644 --- a/drivers/gpio/gpio-virtuser.c +++ b/drivers/gpio/gpio-virtuser.c @@ -1546,6 +1546,30 @@ gpio_virtuser_device_deactivate(struct gpio_virtuser_device *dev)  	dev->pdev = NULL;  } +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  gpio_virtuser_device_config_live_store(struct config_item *item,  				       const char *page, size_t count) @@ -1558,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_lockup_configfs(dev, true); -	if (live == gpio_virtuser_device_is_live(dev)) -		return -EPERM; +	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); +	} -	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;  }  | 
