drivers/gpio: Manage callback addition/removal properly

It needs to verify if the callback was not already installed, and if so:
if is was in controller's list.
It should return an error in case the node is not found though it was
requested to be removed.
If already inserted, it will be silently removed but added again, to
avoid circular list as stated in the bug.

Fixes #11394

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2018-11-15 09:45:54 +01:00 committed by Anas Nashif
commit 064f5f0cef
20 changed files with 37 additions and 59 deletions

View file

@ -202,9 +202,7 @@ static int gpio_sam3_manage_callback(struct device *dev,
{
struct gpio_sam3_runtime *context = dev->driver_data;
_gpio_manage_callback(&context->cb, callback, set);
return 0;
return _gpio_manage_callback(&context->cb, callback, set);
}
static int gpio_sam3_enable_callback(struct device *dev,

View file

@ -297,8 +297,7 @@ static int gpio_cc2650_manage_callback(struct device *port,
{
struct gpio_cc2650_data *data = port->driver_data;
_gpio_manage_callback(&data->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&data->callbacks, callback, set);
}
static int gpio_cc2650_enable_callback(struct device *port,

View file

@ -129,9 +129,7 @@ static int gpio_cc32xx_manage_callback(struct device *dev,
{
struct gpio_cc32xx_data *data = DEV_DATA(dev);
_gpio_manage_callback(&data->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&data->callbacks, callback, set);
}

View file

@ -217,9 +217,7 @@ static int gpio_cmsdk_ahb_manage_callback(struct device *dev,
{
struct gpio_cmsdk_ahb_dev_data *data = dev->driver_data;
_gpio_manage_callback(&data->gpio_cb, callback, set);
return 0;
return _gpio_manage_callback(&data->gpio_cb, callback, set);
}
static int gpio_cmsdk_ahb_enable_callback(struct device *dev,

View file

@ -291,9 +291,7 @@ static inline int gpio_dw_manage_callback(struct device *port,
{
struct gpio_dw_runtime *context = port->driver_data;
_gpio_manage_callback(&context->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&context->callbacks, callback, set);
}
static inline int gpio_dw_enable_callback(struct device *port, int access_op,

View file

@ -210,9 +210,7 @@ static int gpio_esp32_manage_callback(struct device *dev,
{
struct gpio_esp32_data *data = dev->driver_data;
_gpio_manage_callback(&data->cb, callback, set);
return 0;
return _gpio_manage_callback(&data->cb, callback, set);
}
static int gpio_esp32_enable_callback(struct device *dev,

View file

@ -192,9 +192,7 @@ static int gpio_gecko_manage_callback(struct device *dev,
{
struct gpio_gecko_data *data = dev->driver_data;
_gpio_manage_callback(&data->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&data->callbacks, callback, set);
}
static int gpio_gecko_enable_callback(struct device *dev,

View file

@ -109,9 +109,7 @@ static int imx_gpio_manage_callback(struct device *dev,
{
struct imx_gpio_data *data = dev->driver_data;
_gpio_manage_callback(&data->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&data->callbacks, callback, set);
}
static int imx_gpio_enable_callback(struct device *dev,

View file

@ -338,9 +338,7 @@ static int gpio_intel_apl_manage_callback(struct device *dev,
{
struct gpio_intel_apl_data *data = dev->driver_data;
_gpio_manage_callback(&data->cb, callback, set);
return 0;
return _gpio_manage_callback(&data->cb, callback, set);
}
static int gpio_intel_apl_enable_callback(struct device *dev,

View file

@ -174,9 +174,7 @@ static int gpio_mcux_manage_callback(struct device *dev,
{
struct gpio_mcux_data *data = dev->driver_data;
_gpio_manage_callback(&data->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&data->callbacks, callback, set);
}
static int gpio_mcux_enable_callback(struct device *dev,
@ -412,4 +410,3 @@ static int gpio_mcux_porte_init(struct device *dev)
#endif
}
#endif /* CONFIG_GPIO_MCUX_PORTE */

View file

@ -107,9 +107,7 @@ static int mcux_igpio_manage_callback(struct device *dev,
{
struct mcux_igpio_data *data = dev->driver_data;
_gpio_manage_callback(&data->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&data->callbacks, callback, set);
}
static int mcux_igpio_enable_callback(struct device *dev,

View file

@ -257,8 +257,8 @@ static int gpio_nrfx_manage_callback(struct device *port,
struct gpio_callback *callback,
bool set)
{
_gpio_manage_callback(&get_port_data(port)->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&get_port_data(port)->callbacks,
callback, set);
}
static int gpio_nrfx_pin_manage_callback(struct device *port,

View file

@ -193,9 +193,7 @@ static int gpio_pulpino_manage_callback(struct device *dev,
{
struct gpio_pulpino_data *data = DEV_GPIO_DATA(dev);
_gpio_manage_callback(&data->cb, callback, set);
return 0;
return _gpio_manage_callback(&data->cb, callback, set);
}
static int gpio_pulpino_enable_callback(struct device *dev,

View file

@ -298,9 +298,7 @@ static inline int gpio_qmsi_manage_callback(struct device *port,
{
struct gpio_qmsi_runtime *context = port->driver_data;
_gpio_manage_callback(&context->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&context->callbacks, callback, set);
}
static inline int gpio_qmsi_enable_callback(struct device *port,

View file

@ -290,9 +290,7 @@ static inline int ss_gpio_qmsi_manage_callback(struct device *port,
{
struct ss_gpio_qmsi_runtime *context = port->driver_data;
_gpio_manage_callback(&context->callbacks, callback, set);
return 0;
return _gpio_manage_callback(&context->callbacks, callback, set);
}
static inline int ss_gpio_qmsi_enable_callback(struct device *port,

View file

@ -202,9 +202,7 @@ static int gpio_sam_manage_callback(struct device *port,
{
struct gpio_sam_runtime *context = port->driver_data;
_gpio_manage_callback(&context->cb, callback, set);
return 0;
return _gpio_manage_callback(&context->cb, callback, set);
}
static int gpio_sam_enable_callback(struct device *port,

View file

@ -235,7 +235,9 @@ static int gpio_sch_manage_callback(struct device *dev,
{
struct gpio_sch_data *gpio = dev->driver_data;
_gpio_manage_callback(&gpio->callbacks, callback, set);
if (_gpio_manage_callback(&gpio->callbacks, callback, set)) {
return -EINVAL;
}
_gpio_sch_manage_callback(dev);

View file

@ -274,9 +274,7 @@ static int gpio_sifive_manage_callback(struct device *dev,
{
struct gpio_sifive_data *data = DEV_GPIO_DATA(dev);
_gpio_manage_callback(&data->cb, callback, set);
return 0;
return _gpio_manage_callback(&data->cb, callback, set);
}
static int gpio_sifive_enable_callback(struct device *dev,

View file

@ -332,9 +332,7 @@ static int gpio_stm32_manage_callback(struct device *dev,
{
struct gpio_stm32_data *data = dev->driver_data;
_gpio_manage_callback(&data->cb, callback, set);
return 0;
return _gpio_manage_callback(&data->cb, callback, set);
}
static int gpio_stm32_enable_callback(struct device *dev,

View file

@ -18,19 +18,29 @@
* @param callbacks A pointer to the original list of callbacks (can be NULL)
* @param callback A pointer of the callback to insert or remove from the list
* @param set A boolean indicating insertion or removal of the callback
*
* @return 0 on success, negative errno otherwise.
*/
static inline void _gpio_manage_callback(sys_slist_t *callbacks,
struct gpio_callback *callback,
bool set)
static inline int _gpio_manage_callback(sys_slist_t *callbacks,
struct gpio_callback *callback,
bool set)
{
__ASSERT(callback, "No callback!");
__ASSERT(callback->handler, "No callback handler!");
if (!sys_slist_is_empty(callbacks)) {
if (!sys_slist_find_and_remove(callbacks, &callback->node)) {
if (!set) {
return -EINVAL;
}
}
}
if (set) {
sys_slist_prepend(callbacks, &callback->node);
} else {
sys_slist_find_and_remove(callbacks, &callback->node);
}
return 0;
}
/**