Skip to content

Commit c4c958a

Browse files
jkrzysztlinusw
authored andcommitted
gpiolib: Fix array members of same chip processed separately
New code introduced by commit bf9346f ("gpiolib: Identify arrays matching GPIO hardware") forcibly tries to find an array member which has its array index number equal to its hardware pin number and set up an array info for possible fast bitmap processing of all arrray pins belonging to that chip which also satisfy that numbering rule. Depending on array content, it may happen that consecutive array members which belong to the same chip but don't have array indexes equal to their pin hardware numbers will be split into groups, some of them processed together via the fast bitmap path, and rest of them separetely. However, applications may expect all those pins being processed together with a single call to .set_multiple() chip callback, like that was done before the change. Limit applicability of fast bitmap processing path to cases where all pins of consecutive array members starting from 0 which belong to the same chip have their hardware numbers equal to their corresponding array indexes. That should still speed up processing of applications using whole GPIO banks as I/O ports, while not breaking simultaneous manipulation of consecutive pins of the same chip which don't follow the equal numbering rule. Cc: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent 35ae7f9 commit c4c958a

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

Documentation/driver-api/gpio/board.rst

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,18 @@ mapped to the device determines if the array qualifies for fast bitmap
202202
processing. If yes, a bitmap is passed over get/set array functions directly
203203
between a caller and a respective .get/set_multiple() callback of a GPIO chip.
204204

205-
In order to qualify for fast bitmap processing, the pin mapping must meet the
205+
In order to qualify for fast bitmap processing, the array must meet the
206206
following requirements:
207-
- it must belong to the same chip as other 'fast' pins of the function,
208-
- its index within the function must match its hardware number within the chip.
209-
210-
Open drain and open source pins are excluded from fast bitmap output processing.
207+
- pin hardware number of array member 0 must also be 0,
208+
- pin hardware numbers of consecutive array members which belong to the same
209+
chip as member 0 does must also match their array indexes.
210+
211+
Otherwise fast bitmap processing path is not used in order to avoid consecutive
212+
pins which belong to the same chip but are not in hardware order being processed
213+
separately.
214+
215+
If the array applies for fast bitmap processing path, pins which belong to
216+
different chips than member 0 does, as well as those with indexes different from
217+
their hardware pin numbers, are excluded from the fast path, both input and
218+
output. Moreover, open drain and open source pins are excluded from fast bitmap
219+
output processing.

drivers/gpio/gpiolib.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4376,11 +4376,10 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
43764376

43774377
chip = gpiod_to_chip(desc);
43784378
/*
4379-
* Select a chip of first array member
4380-
* whose index matches its pin hardware number
4381-
* as a candidate for fast bitmap processing.
4379+
* If pin hardware number of array member 0 is also 0, select
4380+
* its chip as a candidate for fast bitmap processing path.
43824381
*/
4383-
if (!array_info && gpio_chip_hwgpio(desc) == descs->ndescs) {
4382+
if (descs->ndescs == 0 && gpio_chip_hwgpio(desc) == 0) {
43844383
struct gpio_descs *array;
43854384

43864385
bitmap_size = BITS_TO_LONGS(chip->ngpio > count ?
@@ -4414,14 +4413,30 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
44144413
count - descs->ndescs);
44154414
descs->info = array_info;
44164415
}
4417-
/*
4418-
* Unmark members which don't qualify for fast bitmap
4419-
* processing (different chip, not in hardware order)
4420-
*/
4421-
if (array_info && (chip != array_info->chip ||
4422-
gpio_chip_hwgpio(desc) != descs->ndescs)) {
4416+
/* Unmark array members which don't belong to the 'fast' chip */
4417+
if (array_info && array_info->chip != chip) {
44234418
__clear_bit(descs->ndescs, array_info->get_mask);
44244419
__clear_bit(descs->ndescs, array_info->set_mask);
4420+
}
4421+
/*
4422+
* Detect array members which belong to the 'fast' chip
4423+
* but their pins are not in hardware order.
4424+
*/
4425+
else if (array_info &&
4426+
gpio_chip_hwgpio(desc) != descs->ndescs) {
4427+
/*
4428+
* Don't use fast path if all array members processed so
4429+
* far belong to the same chip as this one but its pin
4430+
* hardware number is different from its array index.
4431+
*/
4432+
if (bitmap_full(array_info->get_mask, descs->ndescs)) {
4433+
array_info = NULL;
4434+
} else {
4435+
__clear_bit(descs->ndescs,
4436+
array_info->get_mask);
4437+
__clear_bit(descs->ndescs,
4438+
array_info->set_mask);
4439+
}
44254440
} else if (array_info) {
44264441
/* Exclude open drain or open source from fast output */
44274442
if (gpiochip_line_is_open_drain(chip, descs->ndescs) ||

0 commit comments

Comments
 (0)