[PATCH 2/4] gpiolib: add bitmask for valid GPIO lines

Timur Tabi timur at codeaurora.org
Fri Dec 1 09:16:37 PST 2017


On 12/01/2017 05:38 AM, Archit Taneja wrote:
> 
> We're hitting an issue here ^ when a consumer calls the devm_gpiod_get() 
> API. This API
> internally sets idx in gpiod_get_index to always 0. For example, in the 
> call sequence
> below, the idx argument to gpiochip_irqchip_line_valid is always 0:
> 
> devm_gpiod_get(dev, con_id, flags)
>     devm_gpiod_get_index(dev, con_id, 0, flags)
>        gpiod_get_index(dev, con_id, 0, flags)
>           if (!gpiochip_irqchip_line_valid(desc->gdev->chip, 0))
>               return ERR_PTR(-EACCES);
> 
> Therefore, with these patches, if we create a sparse gpio map, and the
> 0th gpio is set to "not accessible", all gpio requests end up failing 
> with EACCESS
> because idx is always passed as 0.

Ok, I can see the problem, but I don't know how to fix it.

struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
					      const char *con_id,
					      enum gpiod_flags flags)
{
	return devm_gpiod_get_index(dev, con_id, 0, flags);
}

I thought that by putting the check for "availability" inside of the 
GPIO request, it would handle all situations where a client (whether 
kernel or user-space) tries to access a specific GPIO.

However, this doesn't work with [devm_]gpiod_get.  This function 
attempts to claim the entire GPIO block by claiming only the first GPIO.

This is straining my understanding of gpiolib.  Maybe we need to do 
something like this:

struct gpio_desc *__must_check gpiod_get(struct device *dev, const char 
*con_id,
					 enum gpiod_flags flags)
{
	return gpiod_get_index(dev, con_id, -1, flags);
}

Where idx == -1 is a special-case for gpiod_get_index() where it returns 
the gpio_desc without actually requesting it?

> In gpiochip_irqchip_line_valid, shouldn't we test the nth bit (that 
> corresponds to
> this gpio_desc) in chip->line_valid_mask instead of idx passed above, 
> which is always
> 0?

The code has changed upstream, so I need to refactor that function.  But 
I think it's already testing the nth bit:

static bool gpiochip_irqchip_line_valid(const struct gpio_chip gpiochip,
					unsigned int offset)
{
	/* No mask means all valid */
	if (likely(!gpiochip->line_valid_mask))
		return true;
	return test_bit(offset, gpiochip->line_valid_mask);

'offset' is the nth bit.

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.



More information about the linux-arm-kernel mailing list