mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-29 07:02:29 -04:00
Merge tag 'gpio-fixes-for-v5.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into fixes
gpio fixes for v5.9-rc6 - fix the interrupt configuration in gpio-tc35894 - explicitly support only threaded irqs in gpio-siox - fix a resource leak in error path in gpio-mockup - fix line event handling in syscall compatible mode in GPIO chardev
This commit is contained in:
@@ -552,6 +552,7 @@ static int __init gpio_mockup_init(void)
|
||||
err = platform_driver_register(&gpio_mockup_driver);
|
||||
if (err) {
|
||||
gpio_mockup_err("error registering platform driver\n");
|
||||
debugfs_remove_recursive(gpio_mockup_dbg_dir);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -582,6 +583,7 @@ static int __init gpio_mockup_init(void)
|
||||
gpio_mockup_err("error registering device");
|
||||
platform_driver_unregister(&gpio_mockup_driver);
|
||||
gpio_mockup_unregister_pdevs();
|
||||
debugfs_remove_recursive(gpio_mockup_dbg_dir);
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
|
||||
|
||||
@@ -245,6 +245,7 @@ static int gpio_siox_probe(struct siox_device *sdevice)
|
||||
girq->chip = &ddata->ichip;
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_level_irq;
|
||||
girq->threaded = true;
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, &ddata->gchip, NULL);
|
||||
if (ret)
|
||||
|
||||
@@ -212,7 +212,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
|
||||
continue;
|
||||
|
||||
tc3589x_gpio->oldregs[i][j] = new;
|
||||
tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
|
||||
tc3589x_reg_write(tc3589x, regmap[i] + j, new);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -423,6 +423,21 @@ static __poll_t lineevent_poll(struct file *file,
|
||||
return events;
|
||||
}
|
||||
|
||||
static ssize_t lineevent_get_size(void)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
/* i386 has no padding after 'id' */
|
||||
if (in_ia32_syscall()) {
|
||||
struct compat_gpioeevent_data {
|
||||
compat_u64 timestamp;
|
||||
u32 id;
|
||||
};
|
||||
|
||||
return sizeof(struct compat_gpioeevent_data);
|
||||
}
|
||||
#endif
|
||||
return sizeof(struct gpioevent_data);
|
||||
}
|
||||
|
||||
static ssize_t lineevent_read(struct file *file,
|
||||
char __user *buf,
|
||||
@@ -432,9 +447,20 @@ static ssize_t lineevent_read(struct file *file,
|
||||
struct lineevent_state *le = file->private_data;
|
||||
struct gpioevent_data ge;
|
||||
ssize_t bytes_read = 0;
|
||||
ssize_t ge_size;
|
||||
int ret;
|
||||
|
||||
if (count < sizeof(ge))
|
||||
/*
|
||||
* When compatible system call is being used the struct gpioevent_data,
|
||||
* in case of at least ia32, has different size due to the alignment
|
||||
* differences. Because we have first member 64 bits followed by one of
|
||||
* 32 bits there is no gap between them. The only difference is the
|
||||
* padding at the end of the data structure. Hence, we calculate the
|
||||
* actual sizeof() and pass this as an argument to copy_to_user() to
|
||||
* drop unneeded bytes from the output.
|
||||
*/
|
||||
ge_size = lineevent_get_size();
|
||||
if (count < ge_size)
|
||||
return -EINVAL;
|
||||
|
||||
do {
|
||||
@@ -470,10 +496,10 @@ static ssize_t lineevent_read(struct file *file,
|
||||
break;
|
||||
}
|
||||
|
||||
if (copy_to_user(buf + bytes_read, &ge, sizeof(ge)))
|
||||
if (copy_to_user(buf + bytes_read, &ge, ge_size))
|
||||
return -EFAULT;
|
||||
bytes_read += sizeof(ge);
|
||||
} while (count >= bytes_read + sizeof(ge));
|
||||
bytes_read += ge_size;
|
||||
} while (count >= bytes_read + ge_size);
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user