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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user