Message ID | 20201012123358.1475928-4-u.kleine-koenig@pengutronix.de |
---|---|
State | Superseded |
Headers | show |
Series | leds: trigger: implement a tty trigger | expand |
Hi "Uwe, I love your patch! Perhaps something to improve: [auto build test WARNING on tty/tty-testing] [also build test WARNING on pavel-linux-leds/for-next linus/master j.anaszewski-leds/for-next v5.9 next-20201012] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Uwe-Kleine-K-nig/leds-trigger-implement-a-tty-trigger/20201012-203510 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing config: ia64-allmodconfig (attached as .config) compiler: ia64-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/4185c273a8de0340cee6655a363f98c3737665d0 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Uwe-Kleine-K-nig/leds-trigger-implement-a-tty-trigger/20201012-203510 git checkout 4185c273a8de0340cee6655a363f98c3737665d0 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=ia64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/leds/trigger/ledtrig-tty.c: In function 'ledtrig_tty_work': >> drivers/leds/trigger/ledtrig-tty.c:92:7: warning: variable 'firstrun' set but not used [-Wunused-but-set-variable] 92 | bool firstrun = false; | ^~~~~~~~ vim +/firstrun +92 drivers/leds/trigger/ledtrig-tty.c 85 86 static void ledtrig_tty_work(struct work_struct *work) 87 { 88 struct ledtrig_tty_data *trigger_data = 89 container_of(work, struct ledtrig_tty_data, dwork.work); 90 struct serial_icounter_struct icount; 91 int ret; > 92 bool firstrun = false; 93 94 mutex_lock(&trigger_data->mutex); 95 96 BUG_ON(!trigger_data->ttyname); 97 98 /* try to get the tty corresponding to $ttyname */ 99 if (!trigger_data->tty) { 100 dev_t devno; 101 struct tty_struct *tty; 102 int ret; 103 104 firstrun = true; 105 106 ret = tty_dev_name_to_number(trigger_data->ttyname, &devno); 107 if (ret < 0) 108 /* 109 * A device with this name might appear later, so keep 110 * retrying. 111 */ 112 goto out; 113 114 tty = tty_kopen_shared(devno); 115 if (IS_ERR(tty) || !tty) 116 /* What to do? retry or abort */ 117 goto out; 118 119 trigger_data->tty = tty; 120 } 121 122 ret = tty_get_icount(trigger_data->tty, &icount); 123 if (ret) { 124 mutex_unlock(&trigger_data->mutex); 125 dev_info(trigger_data->tty->dev, "Failed to get icount, stopped polling\n"); 126 mutex_unlock(&trigger_data->mutex); 127 return; 128 } 129 130 if (icount.rx != trigger_data->rx || 131 icount.tx != trigger_data->tx) { 132 led_set_brightness(trigger_data->led_cdev, LED_ON); 133 134 trigger_data->rx = icount.rx; 135 trigger_data->tx = icount.tx; 136 } else { 137 led_set_brightness(trigger_data->led_cdev, LED_OFF); 138 } 139 140 out: 141 mutex_unlock(&trigger_data->mutex); 142 schedule_delayed_work(&trigger_data->dwork, msecs_to_jiffies(100)); 143 } 144 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hello, On Mon, Oct 12, 2020 at 10:16:59PM +0800, kernel test robot wrote: > Hi "Uwe, I love your test report! Perhaps something to improve: The parser of the From: line should drop the " :-) > drivers/leds/trigger/ledtrig-tty.c: In function 'ledtrig_tty_work': > >> drivers/leds/trigger/ledtrig-tty.c:92:7: warning: variable 'firstrun' set but not used [-Wunused-but-set-variable] > 92 | bool firstrun = false; > | ^~~~~~~~ Indeed, this line should just be dropped. I won't resend yet, waiting for some feedback first and assuming reviewers are able to interpolate how v9 will look like :-) Best regards Uwe
Hi "Uwe,
I love your patch! Perhaps something to improve:
[auto build test WARNING on tty/tty-testing]
[also build test WARNING on pavel-linux-leds/for-next linus/master j.anaszewski-leds/for-next v5.9 next-20201015]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Uwe-Kleine-K-nig/leds-trigger-implement-a-tty-trigger/20201012-203510
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
config: openrisc-randconfig-s031-20201015 (attached as .config)
compiler: or1k-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.3-rc1-dirty
# https://github.com/0day-ci/linux/commit/4185c273a8de0340cee6655a363f98c3737665d0
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Uwe-Kleine-K-nig/leds-trigger-implement-a-tty-trigger/20201012-203510
git checkout 4185c273a8de0340cee6655a363f98c3737665d0
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=openrisc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
"sparse warnings: (new ones prefixed by >>)"
>> drivers/leds/trigger/ledtrig-tty.c:177:20: sparse: sparse: symbol 'ledtrig_tty' was not declared. Should it be static?
Please review and possibly fold the followup patch.
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-tty b/Documentation/ABI/testing/sysfs-class-led-trigger-tty new file mode 100644 index 000000000000..5c53ce3ede36 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-led-trigger-tty @@ -0,0 +1,6 @@ +What: /sys/class/leds/<led>/ttyname +Date: Jul 2020 +KernelVersion: 5.8 +Contact: linux-leds@vger.kernel.org +Description: + Specifies the tty device name of the triggering tty diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index ce9429ca6dde..b77a01bd27f4 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -144,4 +144,13 @@ config LEDS_TRIGGER_AUDIO the audio mute and mic-mute changes. If unsure, say N +config LEDS_TRIGGER_TTY + tristate "LED Trigger for TTY devices" + depends on TTY + help + This allows LEDs to be controlled by activity on ttys which includes + serial devices like /dev/ttyS0. + + When build as a module this driver will be called ledtrig-tty. + endif # LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 733a83e2a718..25c4db97cdd4 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o obj-$(CONFIG_LEDS_TRIGGER_PATTERN) += ledtrig-pattern.o obj-$(CONFIG_LEDS_TRIGGER_AUDIO) += ledtrig-audio.o +obj-$(CONFIG_LEDS_TRIGGER_TTY) += ledtrig-tty.o diff --git a/drivers/leds/trigger/ledtrig-tty.c b/drivers/leds/trigger/ledtrig-tty.c new file mode 100644 index 000000000000..806548e33cd8 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-tty.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/delay.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/tty.h> +#include <uapi/linux/serial.h> + +struct ledtrig_tty_data { + struct led_classdev *led_cdev; + struct delayed_work dwork; + struct mutex mutex; + const char *ttyname; + struct tty_struct *tty; + int rx, tx; +}; + +static void ledtrig_tty_halt(struct ledtrig_tty_data *trigger_data) +{ + cancel_delayed_work_sync(&trigger_data->dwork); +} + +static void ledtrig_tty_restart(struct ledtrig_tty_data *trigger_data) +{ + schedule_delayed_work(&trigger_data->dwork, 0); +} + +static ssize_t ttyname_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev); + ssize_t len = 0; + + mutex_lock(&trigger_data->mutex); + + if (trigger_data->ttyname) + len = sprintf(buf, "%s\n", trigger_data->ttyname); + + mutex_unlock(&trigger_data->mutex); + + return len; +} + +static ssize_t ttyname_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev); + char *ttyname; + ssize_t ret = size; + + ledtrig_tty_halt(trigger_data); + + mutex_lock(&trigger_data->mutex); + + if (size > 0 && buf[size - 1] == '\n') + size -= 1; + + if (size) { + ttyname = kmemdup_nul(buf, size, GFP_KERNEL); + if (!ttyname) { + ret = -ENOMEM; + goto out_unlock; + } + } else { + ttyname = NULL; + } + + kfree(trigger_data->ttyname); + tty_kref_put(trigger_data->tty); + trigger_data->tty = NULL; + + trigger_data->ttyname = ttyname; + +out_unlock: + mutex_unlock(&trigger_data->mutex); + + if (ttyname) + ledtrig_tty_restart(trigger_data); + + return ret; +} +static DEVICE_ATTR_RW(ttyname); + +static void ledtrig_tty_work(struct work_struct *work) +{ + struct ledtrig_tty_data *trigger_data = + container_of(work, struct ledtrig_tty_data, dwork.work); + struct serial_icounter_struct icount; + int ret; + bool firstrun = false; + + mutex_lock(&trigger_data->mutex); + + BUG_ON(!trigger_data->ttyname); + + /* try to get the tty corresponding to $ttyname */ + if (!trigger_data->tty) { + dev_t devno; + struct tty_struct *tty; + int ret; + + firstrun = true; + + ret = tty_dev_name_to_number(trigger_data->ttyname, &devno); + if (ret < 0) + /* + * A device with this name might appear later, so keep + * retrying. + */ + goto out; + + tty = tty_kopen_shared(devno); + if (IS_ERR(tty) || !tty) + /* What to do? retry or abort */ + goto out; + + trigger_data->tty = tty; + } + + ret = tty_get_icount(trigger_data->tty, &icount); + if (ret) { + mutex_unlock(&trigger_data->mutex); + dev_info(trigger_data->tty->dev, "Failed to get icount, stopped polling\n"); + mutex_unlock(&trigger_data->mutex); + return; + } + + if (icount.rx != trigger_data->rx || + icount.tx != trigger_data->tx) { + led_set_brightness(trigger_data->led_cdev, LED_ON); + + trigger_data->rx = icount.rx; + trigger_data->tx = icount.tx; + } else { + led_set_brightness(trigger_data->led_cdev, LED_OFF); + } + +out: + mutex_unlock(&trigger_data->mutex); + schedule_delayed_work(&trigger_data->dwork, msecs_to_jiffies(100)); +} + +static struct attribute *ledtrig_tty_attrs[] = { + &dev_attr_ttyname.attr, + NULL +}; +ATTRIBUTE_GROUPS(ledtrig_tty); + +static int ledtrig_tty_activate(struct led_classdev *led_cdev) +{ + struct ledtrig_tty_data *trigger_data; + + trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL); + if (!trigger_data) + return -ENOMEM; + + led_set_trigger_data(led_cdev, trigger_data); + + INIT_DELAYED_WORK(&trigger_data->dwork, ledtrig_tty_work); + trigger_data->led_cdev = led_cdev; + mutex_init(&trigger_data->mutex); + + return 0; +} + +static void ledtrig_tty_deactivate(struct led_classdev *led_cdev) +{ + struct ledtrig_tty_data *trigger_data = led_get_trigger_data(led_cdev); + + cancel_delayed_work_sync(&trigger_data->dwork); + + kfree(trigger_data); +} + +struct led_trigger ledtrig_tty = { + .name = "tty", + .activate = ledtrig_tty_activate, + .deactivate = ledtrig_tty_deactivate, + .groups = ledtrig_tty_groups, +}; +module_led_trigger(ledtrig_tty); + +MODULE_AUTHOR("Uwe Kleine-König <u.kleine-koenig@pengutronix.de>"); +MODULE_DESCRIPTION("UART LED trigger"); +MODULE_LICENSE("GPL v2");
Usage is as follows: myled=ledname tty=ttyS0 echo tty > /sys/class/leds/$myled/trigger echo $tty > /sys/class/leds/$myled/ttyname . When this new trigger is active it periodically checks the tty's statistics and when it changed since the last check the led is flashed once. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- .../ABI/testing/sysfs-class-led-trigger-tty | 6 + drivers/leds/trigger/Kconfig | 9 + drivers/leds/trigger/Makefile | 1 + drivers/leds/trigger/ledtrig-tty.c | 187 ++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-tty create mode 100644 drivers/leds/trigger/ledtrig-tty.c