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

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
Loading
Loading
Loading
Loading
+32 −6
Original line number Diff line number Diff line
@@ -1083,10 +1083,20 @@ static u32 gpio_v2_line_config_debounce_period(struct gpio_v2_line_config *lc,
	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)
{
	if (line->irq) {
		free_irq(line->irq, line);
		free_irq_label(free_irq(line->irq, line));
		line->irq = 0;
	}

@@ -1110,6 +1120,7 @@ static int edge_detector_setup(struct line *line,
	unsigned long irqflags = 0;
	u64 eflags;
	int irq, ret;
	char *label;

	eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
	if (eflags && !kfifo_initialized(&line->req->events)) {
@@ -1146,11 +1157,17 @@ static int edge_detector_setup(struct line *line,
			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
	irqflags |= IRQF_ONESHOT;

	label = make_irq_label(line->req->label);
	if (!label)
		return -ENOMEM;

	/* Request a thread to read the events */
	ret = request_threaded_irq(irq, edge_irq_handler, edge_irq_thread,
				   irqflags, line->req->label, line);
	if (ret)
				   irqflags, label, line);
	if (ret) {
		free_irq_label(label);
		return ret;
	}

	line->irq = irq;
	return 0;
@@ -1973,7 +1990,7 @@ static void lineevent_free(struct lineevent_state *le)
		blocking_notifier_chain_unregister(&le->gdev->device_notifier,
						   &le->device_unregistered_nb);
	if (le->irq)
		free_irq(le->irq, le);
		free_irq_label(free_irq(le->irq, le));
	if (le->desc)
		gpiod_free(le->desc);
	kfree(le->label);
@@ -2114,6 +2131,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
	int fd;
	int ret;
	int irq, irqflags = 0;
	char *label;

	if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
		return -EFAULT;
@@ -2198,15 +2216,23 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
	if (ret)
		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 */
	ret = request_threaded_irq(irq,
				   lineevent_irq_handler,
				   lineevent_irq_thread,
				   irqflags,
				   le->label,
				   label,
				   le);
	if (ret)
	if (ret) {
		free_irq_label(label);
		goto out_free_le;
	}

	le->irq = irq;

+18 −14
Original line number Diff line number Diff line
@@ -2397,6 +2397,11 @@ char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset)
}
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
 * @gc: GPIO chip
@@ -2425,10 +2430,11 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
					    enum gpiod_flags dflags)
{
	struct gpio_desc *desc = gpiochip_get_desc(gc, hwnum);
	const char *name = function_name_or_default(label);
	int ret;

	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;
	}

@@ -2438,8 +2444,8 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,

	ret = gpiod_configure_flags(desc, label, lflags, dflags);
	if (ret) {
		chip_err(gc, "setup of own GPIO %s failed\n", label);
		gpiod_free_commit(desc);
		chip_err(gc, "setup of own GPIO %s failed\n", name);
		return ERR_PTR(ret);
	}

@@ -4153,19 +4159,17 @@ static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode,
					      enum gpiod_flags *flags,
					      unsigned long *lookupflags)
{
	const char *name = function_name_or_default(con_id);
	struct gpio_desc *desc = ERR_PTR(-ENOENT);

	if (is_of_node(fwnode)) {
		dev_dbg(consumer, "using DT '%pfw' for '%s' GPIO lookup\n",
			fwnode, con_id);
		dev_dbg(consumer, "using DT '%pfw' for '%s' GPIO lookup\n", fwnode, name);
		desc = of_find_gpio(to_of_node(fwnode), con_id, idx, lookupflags);
	} else if (is_acpi_node(fwnode)) {
		dev_dbg(consumer, "using ACPI '%pfw' for '%s' GPIO lookup\n",
			fwnode, con_id);
		dev_dbg(consumer, "using ACPI '%pfw' for '%s' GPIO lookup\n", fwnode, name);
		desc = acpi_find_gpio(fwnode, con_id, idx, flags, lookupflags);
	} else if (is_software_node(fwnode)) {
		dev_dbg(consumer, "using swnode '%pfw' for '%s' GPIO lookup\n",
			fwnode, con_id);
		dev_dbg(consumer, "using swnode '%pfw' for '%s' GPIO lookup\n", fwnode, name);
		desc = swnode_find_gpio(fwnode, con_id, idx, lookupflags);
	}

@@ -4181,6 +4185,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
					 bool platform_lookup_allowed)
{
	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
	 * analyzers will complain about these two not being initialized.
@@ -4203,8 +4208,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
		}

		if (IS_ERR(desc)) {
			dev_dbg(consumer, "No GPIO consumer %s found\n",
				con_id);
			dev_dbg(consumer, "No GPIO consumer %s found\n", name);
			return desc;
		}

@@ -4226,15 +4230,14 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
		 *
		 * FIXME: Make this more sane and safe.
		 */
		dev_info(consumer,
			 "nonexclusive access to GPIO for %s\n", con_id);
		dev_info(consumer, "nonexclusive access to GPIO for %s\n", name);
		return desc;
	}

	ret = gpiod_configure_flags(desc, con_id, lookupflags, flags);
	if (ret < 0) {
		dev_dbg(consumer, "setup of GPIO %s failed\n", con_id);
		gpiod_put(desc);
		dev_dbg(consumer, "setup of GPIO %s failed\n", name);
		return ERR_PTR(ret);
	}

@@ -4350,6 +4353,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional);
int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
		unsigned long lflags, enum gpiod_flags dflags)
{
	const char *name = function_name_or_default(con_id);
	int ret;

	if (lflags & GPIO_ACTIVE_LOW)
@@ -4393,7 +4397,7 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,

	/* No particular flag request, return here... */
	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;
	}

+15 −2
Original line number Diff line number Diff line
@@ -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,
				int (*match)(struct gpio_chip *gc,
					     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);
void gpio_device_put(struct gpio_device *gdev);
@@ -814,6 +812,9 @@ struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc);
int gpio_device_get_base(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 */

#include <asm/bug.h>
@@ -843,6 +844,18 @@ static inline const char *gpio_device_get_label(struct gpio_device *gdev)
	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,
				       unsigned int offset)
{