GPIO fixes for 5.0-rc4

- fix from Roger Quadros for a warning resulting from reusing the same
   irqchip for multiple pcf857x instances
 - fix for missing line event timestamp when using nested interrupts
 - two fixes for the sprd driver dealing with value reading and
   the irq chip
 - fix for the direction_output callback for altera-a10sr
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAlxIlloACgkQEacuoBRx
 13L0RA//X9WCQjCclQwhh5CE4KjMhEddTtI6+3VvP1Mijmu0ldq10zoPT63CqKkI
 dro0KsoVh/1VrhtZ1x6U06vl69utUPJOIkOiglCyfp4drhqQK03EPO927KmG5QP0
 NwJ6Yvn9fAWWPg1Y0nQq7O5HczlDDWWTlh8LidY6UQaC4OrxosF0sHIGXEFmY8a0
 HFfHRID6A7w6Dlkn1eg+8OmiLSnz6pzUlwSrlmA2nWmFLN2XrDYmnL14VVLICC5m
 oPMloM6ghJENs41IhfeXA8BqZNe/V+vFQLOk5p+AqXXmH1JelPoYviY0Z0hO8Luv
 dagSA0KQmgU7zaTovU5lWG5fNvwAfvGA/HRJbIIKvzuwu9ti5ara/+Wd/45xhct4
 /+vBA0/GRV8jcor82SDnr2c0VAI2qYWbmoHykmV32m5eoMxgiDjD2PcC6znmjXgb
 ivmBSEPJK3ybu8FAhzb9tqbQArs9dWSEq422D+9H7w95i5dnJNqcbtaosI32b2La
 kiS6YROflO7ZwDncYM1Nb8x5d2nVCX5sTmHfYL3jYtbmv83lNgGdEqMQxQpKq30v
 2tkVLTSdmFS8Y+KyNTD+YAS+stwi5KwEaNbWjIvMCpXHaZRBEnCh4PS7nfwf3mZV
 N7IMmdW46ymtIbKdSbbTSwvtZuak4qZLvYmo0Bkht9H9FqJSDcw=
 =kL5k
 -----END PGP SIGNATURE-----

Merge tag 'gpio-5.0-rc4-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into fixes

GPIO fixes for 5.0-rc4

- fix from Roger Quadros for a warning resulting from reusing the same
  irqchip for multiple pcf857x instances
- fix for missing line event timestamp when using nested interrupts
- two fixes for the sprd driver dealing with value reading and
  the irq chip
- fix for the direction_output callback for altera-a10sr
This commit is contained in:
Linus Walleij 2019-01-24 09:02:24 +01:00
commit aa284d64a9
4 changed files with 36 additions and 17 deletions

View File

@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
unsigned int nr, int value)
{
if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) {
altr_a10sr_gpio_set(gc, nr, value);
return 0;
}
return -EINVAL;
}

View File

@ -180,7 +180,18 @@ static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset)
static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset)
{
return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
switch (sprd_eic->type) {
case SPRD_EIC_DEBOUNCE:
return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
case SPRD_EIC_ASYNC:
return sprd_eic_read(chip, offset, SPRD_EIC_ASYNC_DATA);
case SPRD_EIC_SYNC:
return sprd_eic_read(chip, offset, SPRD_EIC_SYNC_DATA);
default:
return -ENOTSUPP;
}
}
static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int offset)
@ -368,6 +379,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
irq_set_handler_locked(data, handle_edge_irq);
break;
case IRQ_TYPE_EDGE_BOTH:
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1);
irq_set_handler_locked(data, handle_edge_irq);
break;

View File

@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table);
*/
struct pcf857x {
struct gpio_chip chip;
struct irq_chip irqchip;
struct i2c_client *client;
struct mutex lock; /* protect 'out' */
unsigned out; /* software latch */
@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
mutex_unlock(&gpio->lock);
}
static struct irq_chip pcf857x_irq_chip = {
.name = "pcf857x",
.irq_enable = pcf857x_irq_enable,
.irq_disable = pcf857x_irq_disable,
.irq_ack = noop,
.irq_mask = noop,
.irq_unmask = noop,
.irq_set_wake = pcf857x_irq_set_wake,
.irq_bus_lock = pcf857x_irq_bus_lock,
.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
};
/*-------------------------------------------------------------------------*/
static int pcf857x_probe(struct i2c_client *client,
@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client,
/* Enable irqchip if we have an interrupt */
if (client->irq) {
gpio->irqchip.name = "pcf857x",
gpio->irqchip.irq_enable = pcf857x_irq_enable,
gpio->irqchip.irq_disable = pcf857x_irq_disable,
gpio->irqchip.irq_ack = noop,
gpio->irqchip.irq_mask = noop,
gpio->irqchip.irq_unmask = noop,
gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake,
gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock,
gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
status = gpiochip_irqchip_add_nested(&gpio->chip,
&pcf857x_irq_chip,
&gpio->irqchip,
0, handle_level_irq,
IRQ_TYPE_NONE);
if (status) {
@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client,
if (status)
goto fail;
gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
client->irq);
gpio->irq_parent = client->irq;
}

View File

@ -828,7 +828,14 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
/* Do not leak kernel stack to userspace */
memset(&ge, 0, sizeof(ge));
ge.timestamp = le->timestamp;
/*
* We may be running from a nested threaded interrupt in which case
* we didn't get the timestamp from lineevent_irq_handler().
*/
if (!le->timestamp)
ge.timestamp = ktime_get_real_ns();
else
ge.timestamp = le->timestamp;
if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
&& le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {