Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 89240c67 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -384,7 +384,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
	if (set)
		reg |= bit;
	else
		reg &= bit;
		reg &= ~bit;
	iowrite32(reg, addr);

	spin_unlock_irqrestore(&gpio->lock, flags);
+4 −4
Original line number Diff line number Diff line
@@ -116,9 +116,9 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
	unsigned long word_mask;
	const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
	unsigned long port_state;
	u8 __iomem ports[] = {
		idio16gpio->reg->out0_7, idio16gpio->reg->out8_15,
		idio16gpio->reg->in0_7, idio16gpio->reg->in8_15,
	void __iomem *ports[] = {
		&idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
		&idio16gpio->reg->in0_7, &idio16gpio->reg->in8_15,
	};

	/* clear bits array to a clean slate */
@@ -143,7 +143,7 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
		}

		/* read bits from current gpio port */
		port_state = ioread8(ports + i);
		port_state = ioread8(ports[i]);

		/* store acquired bits at respective bits array offset */
		bits[word_index] |= port_state << word_offset;
+11 −11
Original line number Diff line number Diff line
@@ -206,10 +206,10 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
	unsigned long word_mask;
	const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
	unsigned long port_state;
	u8 __iomem ports[] = {
		idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
		idio24gpio->reg->out16_23, idio24gpio->reg->in0_7,
		idio24gpio->reg->in8_15, idio24gpio->reg->in16_23,
	void __iomem *ports[] = {
		&idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
		&idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7,
		&idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23,
	};
	const unsigned long out_mode_mask = BIT(1);

@@ -217,7 +217,7 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
	bitmap_zero(bits, chip->ngpio);

	/* 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 */
		bits_offset = i * gpio_reg_size;

@@ -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) */
		if (i < 6)
			port_state = ioread8(ports + i);
			port_state = ioread8(ports[i]);
		else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
			port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
		else
@@ -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);
	unsigned long flags;
	unsigned int out_state;
	u8 __iomem ports[] = {
		idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
		idio24gpio->reg->out16_23
	void __iomem *ports[] = {
		&idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
		&idio24gpio->reg->out16_23
	};
	const unsigned long out_mode_mask = BIT(1);
	const unsigned int ttl_offset = 48;
@@ -327,9 +327,9 @@ static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
		raw_spin_lock_irqsave(&idio24gpio->lock, flags);

		/* process output lines */
		out_state = ioread8(ports + i) & ~gpio_mask;
		out_state = ioread8(ports[i]) & ~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);
	}
+4 −3
Original line number Diff line number Diff line
@@ -497,7 +497,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
	struct gpiohandle_request handlereq;
	struct linehandle_state *lh;
	struct file *file;
	int fd, i, ret;
	int fd, i, count = 0, ret;
	u32 lflags;

	if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
@@ -558,6 +558,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
		if (ret)
			goto out_free_descs;
		lh->descs[i] = desc;
		count = i;

		if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
			set_bit(FLAG_ACTIVE_LOW, &desc->flags);
@@ -628,7 +629,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
out_put_unused_fd:
	put_unused_fd(fd);
out_free_descs:
	for (; i >= 0; i--)
	for (i = 0; i < count; i++)
		gpiod_free(lh->descs[i]);
	kfree(lh->label);
out_free_lh:
@@ -902,7 +903,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
	desc = &gdev->descs[offset];
	ret = gpiod_request(desc, le->label);
	if (ret)
		goto out_free_desc;
		goto out_free_label;
	le->desc = desc;
	le->eflags = eflags;