Skip to content

Commit cfe102f

Browse files
author
Bartosz Golaszewski
committed
gpiolib: provide gpio_device_find()
gpiochip_find() is wrong and its kernel doc is misleading as the function doesn't return a reference to the gpio_chip but just a raw pointer. The chip itself is not guaranteed to stay alive, in fact it can be deleted at any point. Also: other than GPIO drivers themselves, nobody else has any business accessing gpio_chip structs. Provide a new gpio_device_find() function that returns a real reference to the opaque gpio_device structure that is guaranteed to stay alive for as long as there are active users of it. Signed-off-by: Bartosz Golaszewski <[email protected]> Reviewed-by: Linus Walleij <[email protected]>
1 parent 9e4555d commit cfe102f

File tree

2 files changed

+56
-18
lines changed

2 files changed

+56
-18
lines changed

drivers/gpio/gpiolib.c

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,38 +1014,73 @@ void gpiochip_remove(struct gpio_chip *gc)
10141014
}
10151015
EXPORT_SYMBOL_GPL(gpiochip_remove);
10161016

1017-
/**
1018-
* gpiochip_find() - iterator for locating a specific gpio_chip
1019-
* @data: data to pass to match function
1020-
* @match: Callback function to check gpio_chip
1017+
/*
1018+
* FIXME: This will be removed soon.
10211019
*
1022-
* Similar to bus_find_device. It returns a reference to a gpio_chip as
1023-
* determined by a user supplied @match callback. The callback should return
1024-
* 0 if the device doesn't match and non-zero if it does. If the callback is
1025-
* non-zero, this function will return to the caller and not iterate over any
1026-
* more gpio_chips.
1020+
* This function is depracated, don't use.
10271021
*/
10281022
struct gpio_chip *gpiochip_find(void *data,
10291023
int (*match)(struct gpio_chip *gc,
10301024
void *data))
10311025
{
10321026
struct gpio_device *gdev;
10331027
struct gpio_chip *gc = NULL;
1034-
unsigned long flags;
1035-
1036-
spin_lock_irqsave(&gpio_lock, flags);
1037-
list_for_each_entry(gdev, &gpio_devices, list)
1038-
if (gdev->chip && match(gdev->chip, data)) {
1039-
gc = gdev->chip;
1040-
break;
1041-
}
10421028

1043-
spin_unlock_irqrestore(&gpio_lock, flags);
1029+
gdev = gpio_device_find(data, match);
1030+
if (gdev) {
1031+
gc = gdev->chip;
1032+
gpio_device_put(gdev);
1033+
}
10441034

10451035
return gc;
10461036
}
10471037
EXPORT_SYMBOL_GPL(gpiochip_find);
10481038

1039+
/**
1040+
* gpio_device_find() - find a specific GPIO device
1041+
* @data: data to pass to match function
1042+
* @match: Callback function to check gpio_chip
1043+
*
1044+
* Returns:
1045+
* New reference to struct gpio_device.
1046+
*
1047+
* Similar to bus_find_device(). It returns a reference to a gpio_device as
1048+
* determined by a user supplied @match callback. The callback should return
1049+
* 0 if the device doesn't match and non-zero if it does. If the callback
1050+
* returns non-zero, this function will return to the caller and not iterate
1051+
* over any more gpio_devices.
1052+
*
1053+
* The callback takes the GPIO chip structure as argument. During the execution
1054+
* of the callback function the chip is protected from being freed. TODO: This
1055+
* actually has yet to be implemented.
1056+
*
1057+
* If the function returns non-NULL, the returned reference must be freed by
1058+
* the caller using gpio_device_put().
1059+
*/
1060+
struct gpio_device *gpio_device_find(void *data,
1061+
int (*match)(struct gpio_chip *gc,
1062+
void *data))
1063+
{
1064+
struct gpio_device *gdev;
1065+
1066+
/*
1067+
* Not yet but in the future the spinlock below will become a mutex.
1068+
* Annotate this function before anyone tries to use it in interrupt
1069+
* context like it happened with gpiochip_find().
1070+
*/
1071+
might_sleep();
1072+
1073+
guard(spinlock_irqsave)(&gpio_lock);
1074+
1075+
list_for_each_entry(gdev, &gpio_devices, list) {
1076+
if (gdev->chip && match(gdev->chip, data))
1077+
return gpio_device_get(gdev);
1078+
}
1079+
1080+
return NULL;
1081+
}
1082+
EXPORT_SYMBOL_GPL(gpio_device_find);
1083+
10491084
static int gpiochip_match_name(struct gpio_chip *gc, void *data)
10501085
{
10511086
const char *name = data;

include/linux/gpio/driver.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,9 @@ int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc,
608608
struct gpio_chip *gpiochip_find(void *data,
609609
int (*match)(struct gpio_chip *gc, void *data));
610610

611+
struct gpio_device *gpio_device_find(void *data,
612+
int (*match)(struct gpio_chip *gc, void *data));
613+
611614
struct gpio_device *gpio_device_get(struct gpio_device *gdev);
612615
void gpio_device_put(struct gpio_device *gdev);
613616

0 commit comments

Comments
 (0)