Commit 71114cd1 authored by Andy Shevchenko's avatar Andy Shevchenko
Browse files

Merge patch series "gpiolib: acpi: Refactor to shrink the code by ~8%"

Andy Shevchenko <andriy.shevchenko@linux.intel.com> says:

A simple refactoring of the GPIO ACPI library parts to get an impressive
~8% code shrink on x86_64 and ~2% on x86_32. Also reduces a C code a bit.

add/remove: 0/2 grow/shrink: 0/5 up/down: 0/-1221 (-1221)
Function                                     old     new   delta
acpi_gpio_property_lookup                    425     414     -11
acpi_find_gpio.__UNIQUE_ID_ddebug478          56       -     -56
acpi_dev_gpio_irq_wake_get_by.__UNIQUE_ID_ddebug480      56       -     -56
acpi_find_gpio                               354     216    -138
acpi_get_gpiod_by_index                      462     307    -155
__acpi_find_gpio                             877     638    -239
acpi_dev_gpio_irq_wake_get_by                695     129    -566
Total: Before=15375, After=14154, chg -7.94%

Link: https://lore.kernel.org/r/20250403160034.2680485-1-andriy.shevchenko@linux.intel.com


Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
parents 0af2f6be 8b4f52ef
Loading
Loading
Loading
Loading
+71 −75
Original line number Diff line number Diff line
@@ -96,10 +96,10 @@ struct acpi_gpio_chip {
 * @adev: reference to ACPI device which consumes GPIO resource
 * @flags: GPIO initialization flags
 * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
 * @wake_capable: wake capability as provided by ACPI
 * @pin_config: pin bias as provided by ACPI
 * @polarity: interrupt polarity as provided by ACPI
 * @triggering: triggering type as provided by ACPI
 * @wake_capable: wake capability as provided by ACPI
 * @debounce: debounce timeout as provided by ACPI
 * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
 */
@@ -107,10 +107,10 @@ struct acpi_gpio_info {
	struct acpi_device *adev;
	enum gpiod_flags flags;
	bool gpioint;
	bool wake_capable;
	int pin_config;
	int polarity;
	int triggering;
	bool wake_capable;
	unsigned int debounce;
	unsigned int quirks;
};
@@ -653,12 +653,12 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev,

	for (gm = adev->driver_gpios; gm->name; gm++)
		if (!strcmp(name, gm->name) && gm->data && index < gm->size) {
			const struct acpi_gpio_params *par = gm->data + index;
			const struct acpi_gpio_params *params = gm->data + index;

			args->fwnode = acpi_fwnode_handle(adev);
			args->args[0] = par->crs_entry_index;
			args->args[1] = par->line_index;
			args->args[2] = par->active_low;
			args->args[0] = params->crs_entry_index;
			args->args[1] = params->line_index;
			args->args[2] = params->active_low;
			args->nargs = 3;

			*quirks = gm->quirks;
@@ -744,9 +744,7 @@ static int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,

struct acpi_gpio_lookup {
	struct acpi_gpio_info info;
	int index;
	u16 pin_index;
	bool active_low;
	struct acpi_gpio_params params;
	struct gpio_desc *desc;
	int n;
};
@@ -754,6 +752,7 @@ struct acpi_gpio_lookup {
static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
{
	struct acpi_gpio_lookup *lookup = data;
	struct acpi_gpio_params *params = &lookup->params;

	if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
		return 1;
@@ -765,12 +764,12 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
		u16 pin_index;

		if (lookup->info.quirks & ACPI_GPIO_QUIRK_ONLY_GPIOIO && gpioint)
			lookup->index++;
			params->crs_entry_index++;

		if (lookup->n++ != lookup->index)
		if (lookup->n++ != params->crs_entry_index)
			return 1;

		pin_index = lookup->pin_index;
		pin_index = params->line_index;
		if (pin_index >= agpio->pin_table_length)
			return 1;

@@ -796,7 +795,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
			lookup->info.polarity = agpio->polarity;
			lookup->info.triggering = agpio->triggering;
		} else {
			lookup->info.polarity = lookup->active_low;
			lookup->info.polarity = params->active_low;
		}

		lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio, lookup->info.polarity);
@@ -805,8 +804,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
	return 1;
}

static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
				     struct acpi_gpio_info *info)
static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup)
{
	struct acpi_device *adev = lookup->info.adev;
	struct list_head res_list;
@@ -825,22 +823,21 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
	if (!lookup->desc)
		return -ENOENT;

	if (info)
		*info = lookup->info;
	return 0;
}

static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
				     const char *propname, int index,
static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, const char *propname,
				     struct acpi_gpio_lookup *lookup)
{
	struct fwnode_reference_args args;
	struct acpi_gpio_params *params = &lookup->params;
	unsigned int index = params->crs_entry_index;
	unsigned int quirks = 0;
	int ret;

	memset(&args, 0, sizeof(args));
	ret = __acpi_node_get_property_reference(fwnode, propname, index, 3,
						 &args);

	ret = __acpi_node_get_property_reference(fwnode, propname, index, 3, &args);
	if (ret) {
		struct acpi_device *adev;

@@ -857,9 +854,9 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
	if (args.nargs != 3)
		return -EPROTO;

	lookup->index = args.args[0];
	lookup->pin_index = args.args[1];
	lookup->active_low = !!args.args[2];
	params->crs_entry_index = args.args[0];
	params->line_index = args.args[1];
	params->active_low = !!args.args[2];

	lookup->info.adev = to_acpi_device_node(args.fwnode);
	lookup->info.quirks = quirks;
@@ -871,96 +868,83 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
 * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
 * @adev: pointer to a ACPI device to get GPIO from
 * @propname: Property name of the GPIO (optional)
 * @index: index of GpioIo/GpioInt resource (starting from %0)
 * @info: info pointer to fill in (optional)
 * @lookup: pointer to struct acpi_gpio_lookup to fill in
 *
 * Function goes through ACPI resources for @adev and based on @index looks
 * Function goes through ACPI resources for @adev and based on @lookup.index looks
 * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
 * and returns it. @index matches GpioIo/GpioInt resources only so if there
 * are total %3 GPIO resources, the index goes from %0 to %2.
 * and returns it. @lookup.index matches GpioIo/GpioInt resources only so if there
 * are total 3 GPIO resources, the index goes from 0 to 2.
 *
 * If @propname is specified the GPIO is looked using device property. In
 * that case @index is used to select the GPIO entry in the property value
 * (in case of multiple).
 *
 * Returns:
 * GPIO descriptor to use with Linux generic GPIO API.
 * If the GPIO cannot be translated or there is an error an ERR_PTR is
 * returned.
 * 0 on success, negative errno on failure.
 *
 * The @lookup is filled with GPIO descriptor to use with Linux generic GPIO API.
 * If the GPIO cannot be translated an error will be returned.
 *
 * Note: if the GPIO resource has multiple entries in the pin list, this
 * function only returns the first.
 */
static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
						 const char *propname,
						 int index,
						 struct acpi_gpio_info *info)
static int acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
				   struct acpi_gpio_lookup *lookup)
{
	struct acpi_gpio_lookup lookup;
	struct acpi_gpio_info *info = &lookup->info;
	struct acpi_gpio_params *params = &lookup->params;
	int ret;

	memset(&lookup, 0, sizeof(lookup));
	lookup.index = index;

	if (propname) {
		dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname);

		ret = acpi_gpio_property_lookup(acpi_fwnode_handle(adev),
						propname, index, &lookup);
		ret = acpi_gpio_property_lookup(acpi_fwnode_handle(adev), propname, lookup);
		if (ret)
			return ERR_PTR(ret);
			return ret;

		dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %u %u\n",
			dev_name(&lookup.info.adev->dev), lookup.index,
			lookup.pin_index, lookup.active_low);
		dev_dbg(&adev->dev, "GPIO: _DSD returned %s %u %u %u\n",
			dev_name(&info->adev->dev),
			params->crs_entry_index, params->line_index, params->active_low);
	} else {
		dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
		lookup.info.adev = adev;
		dev_dbg(&adev->dev, "GPIO: looking up %u in _CRS\n", params->crs_entry_index);
		info->adev = adev;
	}

	ret = acpi_gpio_resource_lookup(&lookup, info);
	return ret ? ERR_PTR(ret) : lookup.desc;
	return acpi_gpio_resource_lookup(lookup);
}

/**
 * acpi_get_gpiod_from_data() - get a GPIO descriptor from ACPI data node
 * @fwnode: pointer to an ACPI firmware node to get the GPIO information from
 * @propname: Property name of the GPIO
 * @index: index of GpioIo/GpioInt resource (starting from %0)
 * @info: info pointer to fill in (optional)
 * @lookup: pointer to struct acpi_gpio_lookup to fill in
 *
 * This function uses the property-based GPIO lookup to get to the GPIO
 * resource with the relevant information from a data-only ACPI firmware node
 * and uses that to obtain the GPIO descriptor to return.
 *
 * Returns:
 * GPIO descriptor to use with Linux generic GPIO API.
 * If the GPIO cannot be translated or there is an error an ERR_PTR is
 * returned.
 * 0 on success, negative errno on failure.
 *
 * The @lookup is filled with GPIO descriptor to use with Linux generic GPIO API.
 * If the GPIO cannot be translated an error will be returned.
 */
static struct gpio_desc *acpi_get_gpiod_from_data(struct fwnode_handle *fwnode,
						  const char *propname,
						  int index,
						  struct acpi_gpio_info *info)
static int acpi_get_gpiod_from_data(struct fwnode_handle *fwnode, const char *propname,
				    struct acpi_gpio_lookup *lookup)
{
	struct acpi_gpio_lookup lookup;
	int ret;

	if (!is_acpi_data_node(fwnode))
		return ERR_PTR(-ENODEV);
		return -ENODEV;

	if (!propname)
		return ERR_PTR(-EINVAL);

	memset(&lookup, 0, sizeof(lookup));
	lookup.index = index;
		return -EINVAL;

	ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup);
	ret = acpi_gpio_property_lookup(fwnode, propname, lookup);
	if (ret)
		return ERR_PTR(ret);
		return ret;

	ret = acpi_gpio_resource_lookup(&lookup, info);
	return ret ? ERR_PTR(ret) : lookup.desc;
	return acpi_gpio_resource_lookup(lookup);
}

static bool acpi_can_fallback_to_crs(struct acpi_device *adev,
@@ -982,17 +966,24 @@ __acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int
		 bool can_fallback, struct acpi_gpio_info *info)
{
	struct acpi_device *adev = to_acpi_device_node(fwnode);
	struct acpi_gpio_lookup lookup;
	struct gpio_desc *desc;
	char propname[32];
	int ret;

	memset(&lookup, 0, sizeof(lookup));
	lookup.params.crs_entry_index = idx;

	/* Try first from _DSD */
	for_each_gpio_property_name(propname, con_id) {
		if (adev)
			desc = acpi_get_gpiod_by_index(adev,
						       propname, idx, info);
			ret = acpi_get_gpiod_by_index(adev, propname, &lookup);
		else
			desc = acpi_get_gpiod_from_data(fwnode,
							propname, idx, info);
			ret = acpi_get_gpiod_from_data(fwnode, propname, &lookup);
		if (ret)
			continue;

		desc = lookup.desc;
		if (PTR_ERR(desc) == -EPROBE_DEFER)
			return desc;

@@ -1001,8 +992,13 @@ __acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int
	}

	/* Then from plain _CRS GPIOs */
	if (can_fallback)
		return acpi_get_gpiod_by_index(adev, NULL, idx, info);
	if (can_fallback) {
		ret = acpi_get_gpiod_by_index(adev, NULL, &lookup);
		if (ret)
			return ERR_PTR(ret);

		return lookup.desc;
	}

	return ERR_PTR(-ENOENT);
}
+1 −1
Original line number Diff line number Diff line
@@ -587,7 +587,7 @@ struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev,

struct acpi_gpio_params {
	unsigned int crs_entry_index;
	unsigned int line_index;
	unsigned short line_index;
	bool active_low;
};