Commit 89240c67 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v4.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO fixes from Linus Walleij:
 "Sorry for lagging behind on sending the first batch of GPIO fixes for
  this cycle. Just too busy conferencing and the weather was too nice.

  Here it is anyway: some real important polishing on the error path
  facing userspace (tagged for stable as well) and some normal driver
  fixes.

   - Fix proper IRQ unmasking in the Aspeed driver.

   - Do not free unrequested descriptors on the errorpath when creating
     line handles from the userspace chardev requested GPIO lines.

   - Also fix the errorpath in the linehandle creation function.

   - Fix the get/set multiple GPIO lines for a few of the funky
     industrial GPIO cards on the ISA bus"

* tag 'gpio-v4.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpio: pcie-idio-24: Fix off-by-one error in get_multiple loop
  gpio: pcie-idio-24: Fix port memory offset for get_multiple/set_multiple callbacks
  gpio: pci-idio-16: Fix port memory offset for get_multiple callback
  gpio: fix error path in lineevent_create
  gpioib: do not free unrequested descriptors
  gpio: fix aspeed_gpio unmask irq
parents f142f08b e026646c
...@@ -384,7 +384,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set) ...@@ -384,7 +384,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
if (set) if (set)
reg |= bit; reg |= bit;
else else
reg &= bit; reg &= ~bit;
iowrite32(reg, addr); iowrite32(reg, addr);
spin_unlock_irqrestore(&gpio->lock, flags); spin_unlock_irqrestore(&gpio->lock, flags);
......
...@@ -116,9 +116,9 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip, ...@@ -116,9 +116,9 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
unsigned long word_mask; unsigned long word_mask;
const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
unsigned long port_state; unsigned long port_state;
u8 __iomem ports[] = { void __iomem *ports[] = {
idio16gpio->reg->out0_7, idio16gpio->reg->out8_15, &idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
idio16gpio->reg->in0_7, idio16gpio->reg->in8_15, &idio16gpio->reg->in0_7, &idio16gpio->reg->in8_15,
}; };
/* clear bits array to a clean slate */ /* clear bits array to a clean slate */
...@@ -143,7 +143,7 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip, ...@@ -143,7 +143,7 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
} }
/* read bits from current gpio port */ /* read bits from current gpio port */
port_state = ioread8(ports + i); port_state = ioread8(ports[i]);
/* store acquired bits at respective bits array offset */ /* store acquired bits at respective bits array offset */
bits[word_index] |= port_state << word_offset; bits[word_index] |= port_state << word_offset;
......
...@@ -206,10 +206,10 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip, ...@@ -206,10 +206,10 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
unsigned long word_mask; unsigned long word_mask;
const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
unsigned long port_state; unsigned long port_state;
u8 __iomem ports[] = { void __iomem *ports[] = {
idio24gpio->reg->out0_7, idio24gpio->reg->out8_15, &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
idio24gpio->reg->out16_23, idio24gpio->reg->in0_7, &idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7,
idio24gpio->reg->in8_15, idio24gpio->reg->in16_23, &idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23,
}; };
const unsigned long out_mode_mask = BIT(1); const unsigned long out_mode_mask = BIT(1);
...@@ -217,7 +217,7 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip, ...@@ -217,7 +217,7 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
bitmap_zero(bits, chip->ngpio); bitmap_zero(bits, chip->ngpio);
/* get bits are evaluated a gpio port register at a time */ /* get bits are evaluated a gpio port register at a time */
for (i = 0; i < ARRAY_SIZE(ports); i++) { for (i = 0; i < ARRAY_SIZE(ports) + 1; i++) {
/* gpio offset in bits array */ /* gpio offset in bits array */
bits_offset = i * gpio_reg_size; bits_offset = i * gpio_reg_size;
...@@ -236,7 +236,7 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip, ...@@ -236,7 +236,7 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
/* read bits from current gpio port (port 6 is TTL GPIO) */ /* read bits from current gpio port (port 6 is TTL GPIO) */
if (i < 6) if (i < 6)
port_state = ioread8(ports + i); port_state = ioread8(ports[i]);
else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
port_state = ioread8(&idio24gpio->reg->ttl_out0_7); port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
else else
...@@ -301,9 +301,9 @@ static void idio_24_gpio_set_multiple(struct gpio_chip *chip, ...@@ -301,9 +301,9 @@ static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
const unsigned long port_mask = GENMASK(gpio_reg_size, 0); const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
unsigned long flags; unsigned long flags;
unsigned int out_state; unsigned int out_state;
u8 __iomem ports[] = { void __iomem *ports[] = {
idio24gpio->reg->out0_7, idio24gpio->reg->out8_15, &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
idio24gpio->reg->out16_23 &idio24gpio->reg->out16_23
}; };
const unsigned long out_mode_mask = BIT(1); const unsigned long out_mode_mask = BIT(1);
const unsigned int ttl_offset = 48; const unsigned int ttl_offset = 48;
...@@ -327,9 +327,9 @@ static void idio_24_gpio_set_multiple(struct gpio_chip *chip, ...@@ -327,9 +327,9 @@ static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
raw_spin_lock_irqsave(&idio24gpio->lock, flags); raw_spin_lock_irqsave(&idio24gpio->lock, flags);
/* process output lines */ /* process output lines */
out_state = ioread8(ports + i) & ~gpio_mask; out_state = ioread8(ports[i]) & ~gpio_mask;
out_state |= (*bits >> bits_offset) & gpio_mask; out_state |= (*bits >> bits_offset) & gpio_mask;
iowrite8(out_state, ports + i); iowrite8(out_state, ports[i]);
raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
} }
......
...@@ -497,7 +497,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) ...@@ -497,7 +497,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
struct gpiohandle_request handlereq; struct gpiohandle_request handlereq;
struct linehandle_state *lh; struct linehandle_state *lh;
struct file *file; struct file *file;
int fd, i, ret; int fd, i, count = 0, ret;
u32 lflags; u32 lflags;
if (copy_from_user(&handlereq, ip, sizeof(handlereq))) if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
...@@ -558,6 +558,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) ...@@ -558,6 +558,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
if (ret) if (ret)
goto out_free_descs; goto out_free_descs;
lh->descs[i] = desc; lh->descs[i] = desc;
count = i;
if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW) if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags); set_bit(FLAG_ACTIVE_LOW, &desc->flags);
...@@ -628,7 +629,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) ...@@ -628,7 +629,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
out_put_unused_fd: out_put_unused_fd:
put_unused_fd(fd); put_unused_fd(fd);
out_free_descs: out_free_descs:
for (; i >= 0; i--) for (i = 0; i < count; i++)
gpiod_free(lh->descs[i]); gpiod_free(lh->descs[i]);
kfree(lh->label); kfree(lh->label);
out_free_lh: out_free_lh:
...@@ -902,7 +903,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) ...@@ -902,7 +903,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
desc = &gdev->descs[offset]; desc = &gdev->descs[offset];
ret = gpiod_request(desc, le->label); ret = gpiod_request(desc, le->label);
if (ret) if (ret)
goto out_free_desc; goto out_free_label;
le->desc = desc; le->desc = desc;
le->eflags = eflags; le->eflags = eflags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment