Commit 033e4491 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-fixes-for-v6.9-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio fixes from Bartosz Golaszewski:

 - fix a procfs failure when requesting an interrupt with a label
   containing the '/' character

 - add missing stubs for GPIO lookup functions for !GPIOLIB

 - fix debug messages that would print "(null)" for NULL strings

* tag 'gpio-fixes-for-v6.9-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
  gpiolib: Fix debug messaging in gpiod_find_and_request()
  gpiolib: Add stubs for GPIO lookup functions
  gpio: cdev: sanitize the label before requesting the interrupt
parents 317c7bc0 5c887b65
...@@ -1083,10 +1083,20 @@ static u32 gpio_v2_line_config_debounce_period(struct gpio_v2_line_config *lc, ...@@ -1083,10 +1083,20 @@ static u32 gpio_v2_line_config_debounce_period(struct gpio_v2_line_config *lc,
return 0; return 0;
} }
static inline char *make_irq_label(const char *orig)
{
return kstrdup_and_replace(orig, '/', ':', GFP_KERNEL);
}
static inline void free_irq_label(const char *label)
{
kfree(label);
}
static void edge_detector_stop(struct line *line) static void edge_detector_stop(struct line *line)
{ {
if (line->irq) { if (line->irq) {
free_irq(line->irq, line); free_irq_label(free_irq(line->irq, line));
line->irq = 0; line->irq = 0;
} }
...@@ -1110,6 +1120,7 @@ static int edge_detector_setup(struct line *line, ...@@ -1110,6 +1120,7 @@ static int edge_detector_setup(struct line *line,
unsigned long irqflags = 0; unsigned long irqflags = 0;
u64 eflags; u64 eflags;
int irq, ret; int irq, ret;
char *label;
eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS; eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
if (eflags && !kfifo_initialized(&line->req->events)) { if (eflags && !kfifo_initialized(&line->req->events)) {
...@@ -1146,11 +1157,17 @@ static int edge_detector_setup(struct line *line, ...@@ -1146,11 +1157,17 @@ static int edge_detector_setup(struct line *line,
IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
irqflags |= IRQF_ONESHOT; irqflags |= IRQF_ONESHOT;
label = make_irq_label(line->req->label);
if (!label)
return -ENOMEM;
/* Request a thread to read the events */ /* Request a thread to read the events */
ret = request_threaded_irq(irq, edge_irq_handler, edge_irq_thread, ret = request_threaded_irq(irq, edge_irq_handler, edge_irq_thread,
irqflags, line->req->label, line); irqflags, label, line);
if (ret) if (ret) {
free_irq_label(label);
return ret; return ret;
}
line->irq = irq; line->irq = irq;
return 0; return 0;
...@@ -1973,7 +1990,7 @@ static void lineevent_free(struct lineevent_state *le) ...@@ -1973,7 +1990,7 @@ static void lineevent_free(struct lineevent_state *le)
blocking_notifier_chain_unregister(&le->gdev->device_notifier, blocking_notifier_chain_unregister(&le->gdev->device_notifier,
&le->device_unregistered_nb); &le->device_unregistered_nb);
if (le->irq) if (le->irq)
free_irq(le->irq, le); free_irq_label(free_irq(le->irq, le));
if (le->desc) if (le->desc)
gpiod_free(le->desc); gpiod_free(le->desc);
kfree(le->label); kfree(le->label);
...@@ -2114,6 +2131,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) ...@@ -2114,6 +2131,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
int fd; int fd;
int ret; int ret;
int irq, irqflags = 0; int irq, irqflags = 0;
char *label;
if (copy_from_user(&eventreq, ip, sizeof(eventreq))) if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
return -EFAULT; return -EFAULT;
...@@ -2198,15 +2216,23 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) ...@@ -2198,15 +2216,23 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
if (ret) if (ret)
goto out_free_le; goto out_free_le;
label = make_irq_label(le->label);
if (!label) {
ret = -ENOMEM;
goto out_free_le;
}
/* Request a thread to read the events */ /* Request a thread to read the events */
ret = request_threaded_irq(irq, ret = request_threaded_irq(irq,
lineevent_irq_handler, lineevent_irq_handler,
lineevent_irq_thread, lineevent_irq_thread,
irqflags, irqflags,
le->label, label,
le); le);
if (ret) if (ret) {
free_irq_label(label);
goto out_free_le; goto out_free_le;
}
le->irq = irq; le->irq = irq;
......
...@@ -2397,6 +2397,11 @@ char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset) ...@@ -2397,6 +2397,11 @@ char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset)
} }
EXPORT_SYMBOL_GPL(gpiochip_dup_line_label); EXPORT_SYMBOL_GPL(gpiochip_dup_line_label);
static inline const char *function_name_or_default(const char *con_id)
{
return con_id ?: "(default)";
}
/** /**
* gpiochip_request_own_desc - Allow GPIO chip to request its own descriptor * gpiochip_request_own_desc - Allow GPIO chip to request its own descriptor
* @gc: GPIO chip * @gc: GPIO chip
...@@ -2425,10 +2430,11 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc, ...@@ -2425,10 +2430,11 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
enum gpiod_flags dflags) enum gpiod_flags dflags)
{ {
struct gpio_desc *desc = gpiochip_get_desc(gc, hwnum); struct gpio_desc *desc = gpiochip_get_desc(gc, hwnum);
const char *name = function_name_or_default(label);
int ret; int ret;
if (IS_ERR(desc)) { if (IS_ERR(desc)) {
chip_err(gc, "failed to get GPIO descriptor\n"); chip_err(gc, "failed to get GPIO %s descriptor\n", name);
return desc; return desc;
} }
...@@ -2438,8 +2444,8 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc, ...@@ -2438,8 +2444,8 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
ret = gpiod_configure_flags(desc, label, lflags, dflags); ret = gpiod_configure_flags(desc, label, lflags, dflags);
if (ret) { if (ret) {
chip_err(gc, "setup of own GPIO %s failed\n", label);
gpiod_free_commit(desc); gpiod_free_commit(desc);
chip_err(gc, "setup of own GPIO %s failed\n", name);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -4153,19 +4159,17 @@ static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode, ...@@ -4153,19 +4159,17 @@ static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode,
enum gpiod_flags *flags, enum gpiod_flags *flags,
unsigned long *lookupflags) unsigned long *lookupflags)
{ {
const char *name = function_name_or_default(con_id);
struct gpio_desc *desc = ERR_PTR(-ENOENT); struct gpio_desc *desc = ERR_PTR(-ENOENT);
if (is_of_node(fwnode)) { if (is_of_node(fwnode)) {
dev_dbg(consumer, "using DT '%pfw' for '%s' GPIO lookup\n", dev_dbg(consumer, "using DT '%pfw' for '%s' GPIO lookup\n", fwnode, name);
fwnode, con_id);
desc = of_find_gpio(to_of_node(fwnode), con_id, idx, lookupflags); desc = of_find_gpio(to_of_node(fwnode), con_id, idx, lookupflags);
} else if (is_acpi_node(fwnode)) { } else if (is_acpi_node(fwnode)) {
dev_dbg(consumer, "using ACPI '%pfw' for '%s' GPIO lookup\n", dev_dbg(consumer, "using ACPI '%pfw' for '%s' GPIO lookup\n", fwnode, name);
fwnode, con_id);
desc = acpi_find_gpio(fwnode, con_id, idx, flags, lookupflags); desc = acpi_find_gpio(fwnode, con_id, idx, flags, lookupflags);
} else if (is_software_node(fwnode)) { } else if (is_software_node(fwnode)) {
dev_dbg(consumer, "using swnode '%pfw' for '%s' GPIO lookup\n", dev_dbg(consumer, "using swnode '%pfw' for '%s' GPIO lookup\n", fwnode, name);
fwnode, con_id);
desc = swnode_find_gpio(fwnode, con_id, idx, lookupflags); desc = swnode_find_gpio(fwnode, con_id, idx, lookupflags);
} }
...@@ -4181,6 +4185,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer, ...@@ -4181,6 +4185,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
bool platform_lookup_allowed) bool platform_lookup_allowed)
{ {
unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT; unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT;
const char *name = function_name_or_default(con_id);
/* /*
* scoped_guard() is implemented as a for loop, meaning static * scoped_guard() is implemented as a for loop, meaning static
* analyzers will complain about these two not being initialized. * analyzers will complain about these two not being initialized.
...@@ -4203,8 +4208,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer, ...@@ -4203,8 +4208,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
} }
if (IS_ERR(desc)) { if (IS_ERR(desc)) {
dev_dbg(consumer, "No GPIO consumer %s found\n", dev_dbg(consumer, "No GPIO consumer %s found\n", name);
con_id);
return desc; return desc;
} }
...@@ -4226,15 +4230,14 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer, ...@@ -4226,15 +4230,14 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
* *
* FIXME: Make this more sane and safe. * FIXME: Make this more sane and safe.
*/ */
dev_info(consumer, dev_info(consumer, "nonexclusive access to GPIO for %s\n", name);
"nonexclusive access to GPIO for %s\n", con_id);
return desc; return desc;
} }
ret = gpiod_configure_flags(desc, con_id, lookupflags, flags); ret = gpiod_configure_flags(desc, con_id, lookupflags, flags);
if (ret < 0) { if (ret < 0) {
dev_dbg(consumer, "setup of GPIO %s failed\n", con_id);
gpiod_put(desc); gpiod_put(desc);
dev_dbg(consumer, "setup of GPIO %s failed\n", name);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -4350,6 +4353,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional); ...@@ -4350,6 +4353,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional);
int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
unsigned long lflags, enum gpiod_flags dflags) unsigned long lflags, enum gpiod_flags dflags)
{ {
const char *name = function_name_or_default(con_id);
int ret; int ret;
if (lflags & GPIO_ACTIVE_LOW) if (lflags & GPIO_ACTIVE_LOW)
...@@ -4393,7 +4397,7 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, ...@@ -4393,7 +4397,7 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
/* No particular flag request, return here... */ /* No particular flag request, return here... */
if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) { if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
gpiod_dbg(desc, "no flags found for %s\n", con_id); gpiod_dbg(desc, "no flags found for GPIO %s\n", name);
return 0; return 0;
} }
......
...@@ -646,8 +646,6 @@ int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, ...@@ -646,8 +646,6 @@ int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc,
struct gpio_device *gpio_device_find(const void *data, struct gpio_device *gpio_device_find(const void *data,
int (*match)(struct gpio_chip *gc, int (*match)(struct gpio_chip *gc,
const void *data)); const void *data));
struct gpio_device *gpio_device_find_by_label(const char *label);
struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode);
struct gpio_device *gpio_device_get(struct gpio_device *gdev); struct gpio_device *gpio_device_get(struct gpio_device *gdev);
void gpio_device_put(struct gpio_device *gdev); void gpio_device_put(struct gpio_device *gdev);
...@@ -814,6 +812,9 @@ struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc); ...@@ -814,6 +812,9 @@ struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc);
int gpio_device_get_base(struct gpio_device *gdev); int gpio_device_get_base(struct gpio_device *gdev);
const char *gpio_device_get_label(struct gpio_device *gdev); const char *gpio_device_get_label(struct gpio_device *gdev);
struct gpio_device *gpio_device_find_by_label(const char *label);
struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode);
#else /* CONFIG_GPIOLIB */ #else /* CONFIG_GPIOLIB */
#include <asm/bug.h> #include <asm/bug.h>
...@@ -843,6 +844,18 @@ static inline const char *gpio_device_get_label(struct gpio_device *gdev) ...@@ -843,6 +844,18 @@ static inline const char *gpio_device_get_label(struct gpio_device *gdev)
return NULL; return NULL;
} }
static inline struct gpio_device *gpio_device_find_by_label(const char *label)
{
WARN_ON(1);
return NULL;
}
static inline struct gpio_device *gpio_device_find_by_fwnode(const struct fwnode_handle *fwnode)
{
WARN_ON(1);
return NULL;
}
static inline int gpiochip_lock_as_irq(struct gpio_chip *gc, static inline int gpiochip_lock_as_irq(struct gpio_chip *gc,
unsigned int offset) unsigned int offset)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment