Module: xenomai-3 Branch: wip/drivers Commit: 261d1e84678900e04db56f71e7930fea0e36970f URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=261d1e84678900e04db56f71e7930fea0e36970f
Author: Philippe Gerum <r...@xenomai.org> Date: Tue Dec 27 15:37:06 2016 +0100 drivers/gpio: auto-release pin upon close() --- kernel/drivers/gpio/gpio-core.c | 42 +++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/kernel/drivers/gpio/gpio-core.c b/kernel/drivers/gpio/gpio-core.c index 5c08355..c310a96 100644 --- a/kernel/drivers/gpio/gpio-core.c +++ b/kernel/drivers/gpio/gpio-core.c @@ -33,6 +33,10 @@ struct rtdm_gpio_pin { struct gpio_desc *desc; }; +struct rtdm_gpio_chan { + bool requested; +}; + static int gpio_pin_interrupt(rtdm_irq_t *irqh) { struct rtdm_gpio_pin *pin; @@ -45,6 +49,7 @@ static int gpio_pin_interrupt(rtdm_irq_t *irqh) } static int request_gpio_irq(unsigned int gpio, struct rtdm_gpio_pin *pin, + struct rtdm_gpio_chan *chan, int trigger) { static const int trigger_flags[] = { @@ -92,6 +97,8 @@ static int request_gpio_irq(unsigned int gpio, struct rtdm_gpio_pin *pin, goto fail; } + chan->requested = true; + rtdm_irq_enable(&pin->irqh); return 0; @@ -101,15 +108,18 @@ fail: return ret; } -static void release_gpio_irq(unsigned int gpio, struct rtdm_gpio_pin *pin) +static void release_gpio_irq(unsigned int gpio, struct rtdm_gpio_pin *pin, + struct rtdm_gpio_chan *chan) { rtdm_irq_free(&pin->irqh); gpio_free(gpio); + chan->requested = false; } static int gpio_pin_ioctl_nrt(struct rtdm_fd *fd, unsigned int request, void *arg) { + struct rtdm_gpio_chan *chan = rtdm_fd_to_private(fd); struct rtdm_device *dev = rtdm_fd_device(fd); unsigned int gpio = rtdm_fd_minor(fd); int ret = 0, val, trigger; @@ -128,14 +138,16 @@ static int gpio_pin_ioctl_nrt(struct rtdm_fd *fd, ret = gpio_direction_input(gpio); break; case GPIO_RTIOC_IRQEN: + if (chan->requested) + return -EBUSY; ret = rtdm_safe_copy_from_user(fd, &trigger, arg, sizeof(trigger)); if (ret) return ret; - ret = request_gpio_irq(gpio, pin, trigger); + ret = request_gpio_irq(gpio, pin, chan, trigger); break; case GPIO_RTIOC_IRQDIS: - release_gpio_irq(gpio, pin); + release_gpio_irq(gpio, pin, chan); break; default: return -EINVAL; @@ -147,6 +159,7 @@ static int gpio_pin_ioctl_nrt(struct rtdm_fd *fd, static ssize_t gpio_pin_read_rt(struct rtdm_fd *fd, void __user *buf, size_t len) { + struct rtdm_gpio_chan *chan = rtdm_fd_to_private(fd); struct rtdm_device *dev = rtdm_fd_device(fd); struct rtdm_gpio_pin *pin; int value, ret; @@ -154,6 +167,9 @@ static ssize_t gpio_pin_read_rt(struct rtdm_fd *fd, if (len < sizeof(value)) return -EINVAL; + if (!chan->requested) + return -EAGAIN; + pin = container_of(dev, struct rtdm_gpio_pin, dev); if (!(fd->oflags & O_NONBLOCK)) { @@ -191,14 +207,31 @@ static ssize_t gpio_pin_write_rt(struct rtdm_fd *fd, static int gpio_pin_select(struct rtdm_fd *fd, struct xnselector *selector, unsigned int type, unsigned int index) { + struct rtdm_gpio_chan *chan = rtdm_fd_to_private(fd); struct rtdm_device *dev = rtdm_fd_device(fd); struct rtdm_gpio_pin *pin; + if (!chan->requested) + return -EAGAIN; + pin = container_of(dev, struct rtdm_gpio_pin, dev); return rtdm_event_select(&pin->event, selector, type, index); } +static void gpio_pin_close(struct rtdm_fd *fd) +{ + struct rtdm_gpio_chan *chan = rtdm_fd_to_private(fd); + struct rtdm_device *dev = rtdm_fd_device(fd); + unsigned int gpio = rtdm_fd_minor(fd); + struct rtdm_gpio_pin *pin; + + if (chan->requested) { + pin = container_of(dev, struct rtdm_gpio_pin, dev); + release_gpio_irq(gpio, pin, chan); + } +} + static void delete_pin_devices(struct rtdm_gpio_chip *rgc) { struct rtdm_gpio_pin *pin, *n; @@ -304,8 +337,9 @@ int rtdm_gpiochip_add(struct rtdm_gpio_chip *rgc, rgc->driver.device_flags = RTDM_NAMED_DEVICE|RTDM_FIXED_MINOR; rgc->driver.base_minor = gc->base; rgc->driver.device_count = gc->ngpio; - rgc->driver.context_size = 0; + rgc->driver.context_size = sizeof(struct rtdm_gpio_chan); rgc->driver.ops = (struct rtdm_fd_ops){ + .close = gpio_pin_close, .ioctl_nrt = gpio_pin_ioctl_nrt, .read_rt = gpio_pin_read_rt, .write_rt = gpio_pin_write_rt, _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org https://xenomai.org/mailman/listinfo/xenomai-git