mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
gpio fixes for v7.4-rc1
- add ACPI quirks for Thinkpad L13 Gen 2a and Acer Nitro 16S AI to ignore a wrong GPIO interrupt declaration - add missing return value check of devm_gpiochip_add_data() to gpio-lpc32xx - don't set GPIOD_FLAG_IS_OUT from character device code as GPIO core already does it where needed and it can lead to providing invalid info to user-space on request errors - don't report a bogus -ENOMEM for a line requested without a label - propagate errors occurring when setting line values for pins for which we emulate open-drain or open-source drive settings - fix interrupt handling bugs in gpio-pca953x and gpio-davinci - fix more memory leaks in GPIO core - clear event clock flags from pins on GPIO release -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEkeUTLeW1Rh17omX8BZ0uy/82hMMFAmrbHSMACgkQBZ0uy/82 hMMEig//bCUhWF0A94cH7kCq4HBSm5to5wlBO8G08YRrwisca8sfV+RxwoT+uflW kgT4qvrip5PRxpA7V859fo9Fur+9Tfhf7euAPLsylF78bcnPynYVjxS9+ull6MOM UdHTn+kP8eVmRkD8btLD9GdU4UnTk4AZtVA8rr2a18YYxM1PvziAF5eP312tNqMm F/lks0qXLnSVkPiLyn4uCJ+Mn2I1lV4xRUBIIy67wOqDoWSh2eRMH11zBFBB0qUw Gw3mWo9b5utTd38tNtUj0r6kFmQ1J+WzwROwhF1AoQVKGveYHuhg1aaxmoNsHqF2 HskMezPM4T3K3JZUOFFGDc1CUAQ43hQUvpEXi5JJ+U/OSN754zCuyrCE0hQwRevG 8X53iCoUmqJBduE+m8BK6Hi1MWr3gf/kpeKqsWrcPuFegFuq3+i/wiA3gMsU8q3x EigbigPcfJoHqyMHAmJ7+OawHCoaP+lwp73rJmw7hb5a6gYeAX61Ppx0gc3jPmkE xrlnUo2zO7vtONlUHsvbf1Dqc4IbIV4PLXco/sG6dTTQ8AI+yuIl/BV7eSWdXPAh Nhv4IiBsNdKkyKTYrcco0V+X9o3XimqTgY5umGmznwI1DSl0QyNqy9Q3PIOP8WXN MFtijq48+6DuG6VXf4BHsabQDq+qBh0gn7io0v8zG1PQ9Fs1fJY= =UrAJ -----END PGP SIGNATURE----- Merge tag 'gpio-fixes-for-v7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux Pull gpio fixes from Bartosz Golaszewski: - add ACPI quirks for Thinkpad L13 Gen 2a and Acer Nitro 16S AI to ignore a wrong GPIO interrupt declaration - add missing return value check of devm_gpiochip_add_data() to gpio-lpc32xx - don't set GPIOD_FLAG_IS_OUT from character device code as GPIO core already does it where needed and it can lead to providing invalid info to user-space on request errors - don't report a bogus -ENOMEM for a line requested without a label - propagate errors occurring when setting line values for pins for which we emulate open-drain or open-source drive settings - fix interrupt handling bugs in gpio-pca953x and gpio-davinci - fix more memory leaks in GPIO core - clear event clock flags from pins on GPIO release * tag 'gpio-fixes-for-v7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpiolib: don't report -ENOMEM for a requested line without a label gpiolib: Propagate emulated drive errors when setting arrays gpio: pca953x: Handle direction register read errors in IRQ paths gpio: pca953x: Preserve wakeup accounting on parent IRQ failure gpio: davinci: Clear interrupt status in every bank on suspend gpiolib: Free chip resources when allocating the label fails gpiolib: cdev: don't set GPIOD_FLAG_IS_OUT gpiolib: clear the event clock flags when a line is released gpiolib: fix memory leak in gpiod_set_array_value_complex() EPERM error path gpiolib: acpi: Ignore GPIO 11 interrupt on Acer Nitro 16S AI gpio: lpc32xx: check devm_gpiochip_add_data() return value gpiolib: acpi: Ignore GPIO 11 interrupt on ThinkPad L13 Gen 2a
This commit is contained in:
commit
9628ee0c22
|
|
@ -611,10 +611,10 @@ static void davinci_gpio_save_context(struct davinci_gpio_controller *chips,
|
|||
context->set_data = readl_relaxed(&g->set_data);
|
||||
context->set_rising = readl_relaxed(&g->set_rising);
|
||||
context->set_falling = readl_relaxed(&g->set_falling);
|
||||
}
|
||||
|
||||
/* Clear all interrupt status registers */
|
||||
writel_relaxed(GENMASK(31, 0), &g->intstat);
|
||||
/* Clear stale interrupt status for this bank. */
|
||||
writel_relaxed(GENMASK(31, 0), &g->intstat);
|
||||
}
|
||||
}
|
||||
|
||||
static void davinci_gpio_restore_context(struct davinci_gpio_controller *chips,
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc,
|
|||
|
||||
static int lpc32xx_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
int i, ret;
|
||||
void __iomem *reg_base;
|
||||
|
||||
reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
|
|
@ -524,8 +524,11 @@ static int lpc32xx_gpio_probe(struct platform_device *pdev)
|
|||
lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
|
||||
lpc32xx_gpiochip[i].reg_base = reg_base;
|
||||
}
|
||||
devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,
|
||||
&lpc32xx_gpiochip[i]);
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,
|
||||
&lpc32xx_gpiochip[i]);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"failed to register gpio chip %d\n", i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -838,13 +838,18 @@ static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on)
|
|||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||
int ret;
|
||||
|
||||
ret = irq_set_irq_wake(chip->client->irq, on);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (on)
|
||||
atomic_inc(&chip->wakeup_path);
|
||||
else
|
||||
atomic_dec(&chip->wakeup_path);
|
||||
|
||||
return irq_set_irq_wake(chip->client->irq, on);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pca953x_irq_bus_lock(struct irq_data *d)
|
||||
|
|
@ -862,6 +867,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
|||
DECLARE_BITMAP(irq_mask, MAX_LINE);
|
||||
DECLARE_BITMAP(reg_direction, MAX_LINE);
|
||||
int level;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
|
|
@ -880,7 +886,9 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
|||
}
|
||||
|
||||
/* Switch direction to input if needed */
|
||||
pca953x_read_regs(chip, chip->regs->direction, reg_direction);
|
||||
ret = pca953x_read_regs(chip, chip->regs->direction, reg_direction);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
bitmap_or(irq_mask, chip->irq_trig_fall, chip->irq_trig_raise, gc->ngpio);
|
||||
bitmap_or(irq_mask, irq_mask, chip->irq_trig_level_high, gc->ngpio);
|
||||
|
|
@ -890,6 +898,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
|||
for_each_andnot_bit(level, irq_mask, reg_direction, gc->ngpio)
|
||||
pca953x_gpio_direction_input_unlocked(&chip->gpio_chip, level);
|
||||
|
||||
out:
|
||||
mutex_unlock(&chip->irq_lock);
|
||||
}
|
||||
|
||||
|
|
@ -984,7 +993,9 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pendin
|
|||
}
|
||||
|
||||
/* Remove output pins from the equation */
|
||||
pca953x_read_regs(chip, chip->regs->direction, reg_direction);
|
||||
ret = pca953x_read_regs(chip, chip->regs->direction, reg_direction);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
bitmap_copy(old_stat, chip->irq_stat, gc->ngpio);
|
||||
|
||||
|
|
@ -1084,7 +1095,9 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
|
|||
* interrupt. We have to rely on the previous read for
|
||||
* this purpose.
|
||||
*/
|
||||
pca953x_read_regs(chip, chip->regs->direction, reg_direction);
|
||||
ret = pca953x_read_regs(chip, chip->regs->direction, reg_direction);
|
||||
if (ret)
|
||||
return ret;
|
||||
bitmap_and(chip->irq_stat, irq_stat, reg_direction, gc->ngpio);
|
||||
mutex_init(&chip->irq_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -359,6 +359,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
|
|||
.ignore_interrupt = "AMDI0030:00@11",
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Same camera power enable on GPIO 11 as the Acer Nitro V 16S AI
|
||||
* above. It also powers the internal microphones.
|
||||
* Found in BIOS V1.53
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_FAMILY, "Acer Nitro 16S AI"),
|
||||
},
|
||||
.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
|
||||
.ignore_interrupt = "AMDI0030:00@11",
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Wakeup only works when keyboard backlight is turned off
|
||||
|
|
@ -372,6 +386,23 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
|
|||
.ignore_interrupt = "AMDI0030:00@8",
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* ACPI incorrectly declares GPIO 11 as an interrupt in _AEI,
|
||||
* although the EC uses the pin to control the Caps Lock LED.
|
||||
* Requesting the interrupt configures the pin as an input and
|
||||
* prevents the LED from working.
|
||||
* Found in BIOS R1QET54W (1.40).
|
||||
* https://lore.kernel.org/linux-gpio/CAAUQFRPW-rbcZV-=qV1NMjF_358sdJTiGvQuRxRqAsehY+J9Qg@mail.gmail.com/
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21AB"),
|
||||
},
|
||||
.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
|
||||
.ignore_interrupt = "AMDI0030:00@11",
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Spurious wakeups from TP_ATTN# pin
|
||||
|
|
|
|||
|
|
@ -1231,11 +1231,6 @@ static void gpio_v2_line_config_flags_to_desc_flags(u64 lflags,
|
|||
assign_bit(GPIOD_FLAG_ACTIVE_LOW, &flags,
|
||||
lflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW);
|
||||
|
||||
if (lflags & GPIO_V2_LINE_FLAG_OUTPUT)
|
||||
set_bit(GPIOD_FLAG_IS_OUT, &flags);
|
||||
else if (lflags & GPIO_V2_LINE_FLAG_INPUT)
|
||||
clear_bit(GPIOD_FLAG_IS_OUT, &flags);
|
||||
|
||||
assign_bit(GPIOD_FLAG_EDGE_RISING, &flags,
|
||||
lflags & GPIO_V2_LINE_FLAG_EDGE_RISING);
|
||||
assign_bit(GPIOD_FLAG_EDGE_FALLING, &flags,
|
||||
|
|
|
|||
|
|
@ -2648,10 +2648,13 @@ int gpiod_request_commit(struct gpio_desc *desc, const char *label)
|
|||
|
||||
ret = desc_set_label(desc, label ? : "?");
|
||||
if (ret)
|
||||
goto out_clear_bit;
|
||||
goto out_free_gpio;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_gpio:
|
||||
if (guard.gc->free)
|
||||
guard.gc->free(guard.gc, offset);
|
||||
out_clear_bit:
|
||||
clear_bit(GPIOD_FLAG_REQUESTED, &desc->flags);
|
||||
return ret;
|
||||
|
|
@ -2700,6 +2703,8 @@ void gpiod_free_commit(struct gpio_desc *desc)
|
|||
clear_bit(GPIOD_FLAG_BIAS_DISABLE, &flags);
|
||||
clear_bit(GPIOD_FLAG_EDGE_RISING, &flags);
|
||||
clear_bit(GPIOD_FLAG_EDGE_FALLING, &flags);
|
||||
clear_bit(GPIOD_FLAG_EVENT_CLOCK_REALTIME, &flags);
|
||||
clear_bit(GPIOD_FLAG_EVENT_CLOCK_HTE, &flags);
|
||||
clear_bit(GPIOD_FLAG_IS_HOGGED, &flags);
|
||||
#ifdef CONFIG_OF_DYNAMIC
|
||||
WRITE_ONCE(desc->hog, NULL);
|
||||
|
|
@ -2737,6 +2742,7 @@ void gpiod_free(struct gpio_desc *desc)
|
|||
char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
const char *name;
|
||||
char *label;
|
||||
|
||||
desc = gpiochip_get_desc(gc, offset);
|
||||
|
|
@ -2748,7 +2754,11 @@ char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset)
|
|||
|
||||
guard(srcu)(&desc->gdev->desc_srcu);
|
||||
|
||||
label = kstrdup(gpiod_get_label(desc), GFP_KERNEL);
|
||||
name = gpiod_get_label(desc);
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
label = kstrdup(name, GFP_KERNEL);
|
||||
if (!label)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
|
@ -3863,7 +3873,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
|
|||
unsigned long *value_bitmap)
|
||||
{
|
||||
struct gpio_chip *gc;
|
||||
int i = 0, ret;
|
||||
int i = 0, ret = 0;
|
||||
|
||||
/*
|
||||
* Validate array_info against desc_array and its size.
|
||||
|
|
@ -3941,8 +3951,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
|
|||
int hwgpio = gpiod_hwgpio(desc);
|
||||
int value = test_bit(i, value_bitmap);
|
||||
|
||||
if (unlikely(!test_bit(GPIOD_FLAG_IS_OUT, &desc->flags)))
|
||||
return -EPERM;
|
||||
if (unlikely(!test_bit(GPIOD_FLAG_IS_OUT, &desc->flags))) {
|
||||
ret = -EPERM;
|
||||
goto cleanup_bitmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pins applicable for fast input but not for
|
||||
|
|
@ -3959,9 +3971,13 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
|
|||
* open drain and open source outputs are set individually
|
||||
*/
|
||||
if (test_bit(GPIOD_FLAG_OPEN_DRAIN, &desc->flags) && !raw) {
|
||||
gpio_set_open_drain_value_commit(desc, value);
|
||||
ret = gpio_set_open_drain_value_commit(desc, value);
|
||||
if (ret)
|
||||
goto cleanup_bitmap;
|
||||
} else if (test_bit(GPIOD_FLAG_OPEN_SOURCE, &desc->flags) && !raw) {
|
||||
gpio_set_open_source_value_commit(desc, value);
|
||||
ret = gpio_set_open_source_value_commit(desc, value);
|
||||
if (ret)
|
||||
goto cleanup_bitmap;
|
||||
} else {
|
||||
__set_bit(hwgpio, mask);
|
||||
__assign_bit(hwgpio, bits, value);
|
||||
|
|
@ -3975,10 +3991,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
|
|||
} while ((i < array_size) &&
|
||||
gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc));
|
||||
/* push collected bits to outputs */
|
||||
ret = 0;
|
||||
if (count != 0)
|
||||
ret = gpiochip_set_multiple(guard.gc, mask, bits);
|
||||
|
||||
cleanup_bitmap:
|
||||
if (mask != fastpath_mask)
|
||||
bitmap_free(mask);
|
||||
if (bits != fastpath_bits)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user