From d30c8d2031259d6dc360f8c96d362bb36665c99c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 19 Jun 2018 10:18:56 +0200 Subject: leds: ledtrig-activity: use ktime_get_boot_ns() get_monotonic_boottime() is deprecated, so let's convert this to the simpler ktime_get_boot_ns(). Signed-off-by: Arnd Bergmann Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-activity.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-activity.c b/drivers/leds/trigger/ledtrig-activity.c index 5081894082bd..6c6f8a9b8d9a 100644 --- a/drivers/leds/trigger/ledtrig-activity.c +++ b/drivers/leds/trigger/ledtrig-activity.c @@ -37,7 +37,6 @@ static void led_activity_function(struct timer_list *t) struct activity_data *activity_data = from_timer(activity_data, t, timer); struct led_classdev *led_cdev = activity_data->led_cdev; - struct timespec boot_time; unsigned int target; unsigned int usage; int delay; @@ -57,8 +56,6 @@ static void led_activity_function(struct timer_list *t) return; } - get_monotonic_boottime(&boot_time); - cpus = 0; curr_used = 0; @@ -76,7 +73,7 @@ static void led_activity_function(struct timer_list *t) * down to 16us, ensuring we won't overflow 32-bit computations below * even up to 3k CPUs, while keeping divides cheap on smaller systems. */ - curr_boot = timespec_to_ns(&boot_time) * cpus; + curr_boot = ktime_get_boot_ns() * cpus; diff_boot = (curr_boot - activity_data->last_boot) >> 16; diff_used = (curr_used - activity_data->last_used) >> 16; activity_data->last_boot = curr_boot; -- cgit v1.2.3-59-g8ed1b From 8cb21086cc6359c6d4f003a788050308afb211ad Mon Sep 17 00:00:00 2001 From: "Raffaello D. Di Napoli" Date: Mon, 25 Jun 2018 08:50:02 -0400 Subject: leds: Modify PC Engines apu/apu2 driver to support apu3 PC Engines apu3 is an improved version of the apu2, using the same SoC and almost everything else. This patch reuses as much as possible from the apu2 definitions, to avoid redundancy. Signed-off-by: Raffaello D. Di Napoli Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/Kconfig | 5 +++-- drivers/leds/leds-apu.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6e3a998f3370..44097a3e0fcc 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -57,12 +57,13 @@ config LEDS_AAT1290 depends on PINCTRL help This option enables support for the LEDs on the AAT1290. + config LEDS_APU - tristate "Front panel LED support for PC Engines APU/APU2 boards" + tristate "Front panel LED support for PC Engines APU/APU2/APU3 boards" depends on LEDS_CLASS depends on X86 && DMI help - This driver makes the PC Engines APU/APU2 front panel LEDs + This driver makes the PC Engines APU/APU2/APU3 front panel LEDs accessible from userspace programs through the LED subsystem. To compile this driver as a module, choose M here: the diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c index 8c93d68964c7..8d42e46e2de3 100644 --- a/drivers/leds/leds-apu.c +++ b/drivers/leds/leds-apu.c @@ -102,6 +102,13 @@ static const struct apu_led_profile apu2_led_profile[] = { { "apu2:green:3", LED_OFF, APU2_FCH_GPIO_BASE + 70 * APU2_IOSIZE }, }; +/* Same as apu2_led_profile, but with "3" in the LED names. */ +static const struct apu_led_profile apu3_led_profile[] = { + { "apu3:green:1", LED_ON, APU2_FCH_GPIO_BASE + 68 * APU2_IOSIZE }, + { "apu3:green:2", LED_OFF, APU2_FCH_GPIO_BASE + 69 * APU2_IOSIZE }, + { "apu3:green:3", LED_OFF, APU2_FCH_GPIO_BASE + 70 * APU2_IOSIZE }, +}; + static const struct dmi_system_id apu_led_dmi_table[] __initconst = { { .ident = "apu", @@ -134,6 +141,30 @@ static const struct dmi_system_id apu_led_dmi_table[] __initconst = { DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu2") } }, + /* PC Engines APU3 with "Legacy" bios < 4.0.8 */ + { + .ident = "apu3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), + DMI_MATCH(DMI_BOARD_NAME, "APU3") + } + }, + /* PC Engines APU3 with "Legacy" bios >= 4.0.8 */ + { + .ident = "apu3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), + DMI_MATCH(DMI_BOARD_NAME, "apu3") + } + }, + /* PC Engines APU2 with "Mainline" bios */ + { + .ident = "apu3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"), + DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu3") + } + }, {} }; MODULE_DEVICE_TABLE(dmi, apu_led_dmi_table); @@ -235,6 +266,14 @@ static int __init apu_led_probe(struct platform_device *pdev) apu_led->platform = APU2_LED_PLATFORM; apu_led->num_led_instances = ARRAY_SIZE(apu2_led_profile); apu_led->iosize = APU2_IOSIZE; + } else if (dmi_match(DMI_BOARD_NAME, "APU3") || + dmi_match(DMI_BOARD_NAME, "apu3") || + dmi_match(DMI_BOARD_NAME, "PC Engines apu3")) { + apu_led->profile = apu3_led_profile; + /* Otherwise identical to APU2. */ + apu_led->platform = APU2_LED_PLATFORM; + apu_led->num_led_instances = ARRAY_SIZE(apu3_led_profile); + apu_led->iosize = APU2_IOSIZE; } spin_lock_init(&apu_led->lock); @@ -259,7 +298,10 @@ static int __init apu_led_init(void) if (!(dmi_match(DMI_PRODUCT_NAME, "APU") || dmi_match(DMI_PRODUCT_NAME, "APU2") || dmi_match(DMI_PRODUCT_NAME, "apu2") || - dmi_match(DMI_PRODUCT_NAME, "PC Engines apu2"))) { + dmi_match(DMI_PRODUCT_NAME, "PC Engines apu2") || + dmi_match(DMI_PRODUCT_NAME, "APU3") || + dmi_match(DMI_PRODUCT_NAME, "apu3") || + dmi_match(DMI_PRODUCT_NAME, "PC Engines apu3"))) { pr_err("Unknown PC Engines board: %s\n", dmi_get_system_info(DMI_PRODUCT_NAME)); return -ENODEV; -- cgit v1.2.3-59-g8ed1b From 3d74243db89f9c7cea7afc471f67e15b96cc6278 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 26 Jun 2018 11:37:58 +0200 Subject: leds: triggers: don't depend on LEDS_TRIGGERS twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the triggers are defined in a big if LEDS_TRIGGERS...endif block. So there is no need to let each driver depend on LEDS_TRIGGERS explicitly once more. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/Kconfig | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index a2559b4fdfff..4018af769969 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -10,7 +10,6 @@ if LEDS_TRIGGERS config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by a programmable timer via sysfs. Some LED hardware can be programmed to start @@ -21,7 +20,6 @@ config LEDS_TRIGGER_TIMER config LEDS_TRIGGER_ONESHOT tristate "LED One-shot Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to blink in one-shot pulses with parameters controlled via sysfs. It's useful to notify the user on @@ -36,7 +34,6 @@ config LEDS_TRIGGER_ONESHOT config LEDS_TRIGGER_DISK bool "LED Disk Trigger" depends on IDE_GD_ATA || ATA - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by disk activity. If unsure, say Y. @@ -44,14 +41,12 @@ config LEDS_TRIGGER_DISK config LEDS_TRIGGER_MTD bool "LED MTD (NAND/NOR) Trigger" depends on MTD - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by MTD activity. If unsure, say N. config LEDS_TRIGGER_HEARTBEAT tristate "LED Heartbeat Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by a CPU load average. The flash frequency is a hyperbolic function of the 1-minute @@ -60,7 +55,6 @@ config LEDS_TRIGGER_HEARTBEAT config LEDS_TRIGGER_BACKLIGHT tristate "LED backlight Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled as a backlight device: they turn off and on when the display is blanked and unblanked. @@ -69,7 +63,6 @@ config LEDS_TRIGGER_BACKLIGHT config LEDS_TRIGGER_CPU bool "LED CPU Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by active CPUs. This shows the active CPUs across an array of LEDs so you can see which @@ -79,7 +72,6 @@ config LEDS_TRIGGER_CPU config LEDS_TRIGGER_ACTIVITY tristate "LED activity Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled by an immediate CPU usage. The flash frequency and duty cycle varies from faint flashes to @@ -88,7 +80,6 @@ config LEDS_TRIGGER_ACTIVITY config LEDS_TRIGGER_GPIO tristate "LED GPIO Trigger" - depends on LEDS_TRIGGERS depends on GPIOLIB || COMPILE_TEST help This allows LEDs to be controlled by gpio events. It's good @@ -101,7 +92,6 @@ config LEDS_TRIGGER_GPIO config LEDS_TRIGGER_DEFAULT_ON tristate "LED Default ON Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be initialised in the ON state. If unsure, say Y. @@ -111,7 +101,6 @@ comment "iptables trigger is under Netfilter config (LED target)" config LEDS_TRIGGER_TRANSIENT tristate "LED Transient Trigger" - depends on LEDS_TRIGGERS help This allows one time activation of a transient state on GPIO/PWM based hardware. @@ -119,7 +108,6 @@ config LEDS_TRIGGER_TRANSIENT config LEDS_TRIGGER_CAMERA tristate "LED Camera Flash/Torch Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be controlled as a camera flash/torch device. This enables direct flash/torch on/off by the driver, kernel space. @@ -127,7 +115,6 @@ config LEDS_TRIGGER_CAMERA config LEDS_TRIGGER_PANIC bool "LED Panic Trigger" - depends on LEDS_TRIGGERS help This allows LEDs to be configured to blink on a kernel panic. Enabling this option will allow to mark certain LEDs as panic indicators, @@ -137,7 +124,7 @@ config LEDS_TRIGGER_PANIC config LEDS_TRIGGER_NETDEV tristate "LED Netdev Trigger" - depends on NET && LEDS_TRIGGERS + depends on NET help This allows LEDs to be controlled by network device activity. If unsure, say Y. -- cgit v1.2.3-59-g8ed1b From 868ec1cad0d93365ddbb1cba2b671c6c8c9221ba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jun 2018 06:49:06 -0300 Subject: devicectree: bindings: fix location of leds common file The leds.txt was moved and renamed. Fix references to it accordingly. Fixes: f67605394f0b ("devicetree/bindings: Move gpio-leds binding into leds directory") Signed-off-by: Mauro Carvalho Chehab Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- Documentation/devicetree/bindings/leds/common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt index 1d4afe9644b6..aa1399814a2a 100644 --- a/Documentation/devicetree/bindings/leds/common.txt +++ b/Documentation/devicetree/bindings/leds/common.txt @@ -31,7 +31,7 @@ Optional properties for child nodes: "backlight" - LED will act as a back-light, controlled by the framebuffer system "default-on" - LED will turn on (but for leds-gpio see "default-state" - property in Documentation/devicetree/bindings/gpio/led.txt) + property in Documentation/devicetree/bindings/leds/leds-gpio.txt) "heartbeat" - LED "double" flashes at a load average based rate "disk-activity" - LED indicates disk activity "ide-disk" - LED indicates IDE disk activity (deprecated), -- cgit v1.2.3-59-g8ed1b From 30f3b42147ba6f29bc95c1bba34468740762d91b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 27 Jun 2018 11:20:52 +0200 Subject: can: mark led trigger as broken MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver was suggested for deletion as it implements a subset of the netdev trigger. It's in the way for further cleanups in the trigger code but doesn't get an Ack by someone who can actually test and confirm that the netdev trigger works for can devices. So marking as broken to get forward with the cleanups. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/net/can/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 2cb75988b328..7cdd0cead693 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -73,6 +73,12 @@ config CAN_CALC_BITTIMING config CAN_LEDS bool "Enable LED triggers for Netlink based drivers" depends on LEDS_CLASS + # The netdev trigger (LEDS_TRIGGER_NETDEV) should be able to do + # everything that this driver is doing. This is marked as broken + # because it uses stuff that is intended to be changed or removed. + # Please consider switching to the netdev trigger and confirm it + # fulfills your needs instead of fixing this driver. + depends on BROKEN select LEDS_TRIGGERS ---help--- This option adds two LED triggers for packet receive and transmit -- cgit v1.2.3-59-g8ed1b From f041f96abcf8718540e94aac6e73604c5d33d9f9 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:33 +0200 Subject: dt-bindings: leds: Add bindings for lltc,lt3593 This patch adds the bindings document for LT3593 LED drivers. The binding is kept consistent with other LED driver bindings in that it stores all the LED-specific properties in its own subnode. As the hardware only supports one channel, there can consequently only be one sub-node. Signed-off-by: Daniel Mack Reviewed-by: Rob Herring Signed-off-by: Jacek Anaszewski --- .../devicetree/bindings/leds/leds-lt3593.txt | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/leds-lt3593.txt diff --git a/Documentation/devicetree/bindings/leds/leds-lt3593.txt b/Documentation/devicetree/bindings/leds/leds-lt3593.txt new file mode 100644 index 000000000000..6b2cabc36c0c --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-lt3593.txt @@ -0,0 +1,32 @@ +Bindings for Linear Technologies LT3593 LED controller + +Required properties: +- compatible: Should be "lltc,lt3593". +- lltc,ctrl-gpios: A handle to the GPIO that is connected to the 'CTRL' + pin of the chip. + +The hardware supports only one LED. The properties of this LED are +configured in a sub-node in the device node. + +Optional sub-node properties: +- label: A label for the LED. If none is given, the LED will be + named "lt3595::". +- linux,default-trigger: The default trigger for the LED. + See Documentation/devicetree/bindings/leds/common.txt +- default-state: The initial state of the LED. + See Documentation/devicetree/bindings/leds/common.txt + +If multiple chips of this type are found in a design, each one needs to +be handled by its own device node. + +Example: + +led-controller { + compatible = "lltc,lt3593"; + lltc,ctrl-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; + + led { + label = "white:backlight"; + default-state = "on"; + }; +}; -- cgit v1.2.3-59-g8ed1b From d8be286739d6317b2c4b2a6c2cbf63d76410ff90 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:34 +0200 Subject: leds: lt3593: merge functions and clean up code In preparation to DT probe functionality, merge create_lt3593_led() into its only call-site. The DT based setup code will be quite different, so this internal helper function is of no help. This also changes the way the driver works by only handling one entry inside 'struct gpio_led_platform_data'. If multiple devices of the same type are found in a design, there should be a platform device for each of them. The only mainline user of this driver is not affected by this change. Last, use devm_led_classdev_register() instead of led_classdev_register(), so the driver's remove callback can go away. Signed-off-by: Daniel Mack Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lt3593.c | 103 +++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 68 deletions(-) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 5ec730a31b65..1a3dc347db21 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -71,104 +71,71 @@ static int lt3593_led_set(struct led_classdev *led_cdev, return 0; } -static int create_lt3593_led(const struct gpio_led *template, - struct lt3593_led_data *led_dat, struct device *parent) +static struct lt3593_led_data *lt3593_led_probe_pdata(struct device *dev) { + struct gpio_led_platform_data *pdata = dev_get_platdata(dev); + const struct gpio_led *template = &pdata->leds[0]; + struct lt3593_led_data *led_data; int ret, state; - /* skip leds on GPIOs that aren't available */ + if (pdata->num_leds != 1) + return ERR_PTR(-EINVAL); + + led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL); + if (!led_data) + return ERR_PTR(-ENOMEM); + if (!gpio_is_valid(template->gpio)) { - dev_info(parent, "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n", - KBUILD_MODNAME, template->gpio, template->name); - return 0; + dev_info(dev, "skipping unavailable LT3593 LED at gpio " + "%d (%s)\n", template->gpio, template->name); + return ERR_PTR(-EINVAL); } - led_dat->cdev.name = template->name; - led_dat->cdev.default_trigger = template->default_trigger; - led_dat->gpio = template->gpio; - - led_dat->cdev.brightness_set_blocking = lt3593_led_set; + led_data->cdev.name = template->name; + led_data->cdev.default_trigger = template->default_trigger; + led_data->gpio = template->gpio; + led_data->cdev.brightness_set_blocking = lt3593_led_set; state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); - led_dat->cdev.brightness = state ? LED_FULL : LED_OFF; + led_data->cdev.brightness = state ? LED_FULL : LED_OFF; if (!template->retain_state_suspended) - led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; + led_data->cdev.flags |= LED_CORE_SUSPENDRESUME; - ret = devm_gpio_request_one(parent, template->gpio, state ? + ret = devm_gpio_request_one(dev, template->gpio, state ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, template->name); if (ret < 0) - return ret; + return ERR_PTR(ret); - ret = led_classdev_register(parent, &led_dat->cdev); + ret = devm_led_classdev_register(dev, &led_data->cdev); if (ret < 0) - return ret; - - dev_info(parent, "%s: registered LT3593 LED '%s' at GPIO %d\n", - KBUILD_MODNAME, template->name, template->gpio); + return ERR_PTR(ret); - return 0; -} + dev_info(dev, "registered LT3593 LED '%s' at GPIO %d\n", + template->name, template->gpio); -static void delete_lt3593_led(struct lt3593_led_data *led) -{ - if (!gpio_is_valid(led->gpio)) - return; - - led_classdev_unregister(&led->cdev); + return led_data; } static int lt3593_led_probe(struct platform_device *pdev) { - struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct lt3593_led_data *leds_data; - int i, ret = 0; - - if (!pdata) - return -EBUSY; - - leds_data = devm_kcalloc(&pdev->dev, - pdata->num_leds, sizeof(struct lt3593_led_data), - GFP_KERNEL); - if (!leds_data) - return -ENOMEM; - - for (i = 0; i < pdata->num_leds; i++) { - ret = create_lt3593_led(&pdata->leds[i], &leds_data[i], - &pdev->dev); - if (ret < 0) - goto err; - } + struct device *dev = &pdev->dev; + struct lt3593_led_data *led_data; - platform_set_drvdata(pdev, leds_data); - - return 0; - -err: - for (i = i - 1; i >= 0; i--) - delete_lt3593_led(&leds_data[i]); - - return ret; -} - -static int lt3593_led_remove(struct platform_device *pdev) -{ - int i; - struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct lt3593_led_data *leds_data; - - leds_data = platform_get_drvdata(pdev); + if (dev_get_platdata(dev)) { + led_data = lt3593_led_probe_pdata(dev); + if (IS_ERR(led_data)) + return PTR_ERR(led_data); + } - for (i = 0; i < pdata->num_leds; i++) - delete_lt3593_led(&leds_data[i]); + platform_set_drvdata(pdev, led_data); return 0; } static struct platform_driver lt3593_led_driver = { .probe = lt3593_led_probe, - .remove = lt3593_led_remove, .driver = { .name = "leds-lt3593", }, -- cgit v1.2.3-59-g8ed1b From 73f103c9528135bc896459a58e2371ce86090aea Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:35 +0200 Subject: leds: lt3593: switch to gpiod interface Clean up the code a bit and transition over to the gpiod based interface. Signed-off-by: Daniel Mack Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lt3593.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 1a3dc347db21..a096ee64cbbb 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -21,12 +21,13 @@ #include #include #include +#include #include #include struct lt3593_led_data { struct led_classdev cdev; - unsigned gpio; + struct gpio_desc *gpiod; }; static int lt3593_led_set(struct led_classdev *led_cdev, @@ -46,25 +47,25 @@ static int lt3593_led_set(struct led_classdev *led_cdev, */ if (value == 0) { - gpio_set_value_cansleep(led_dat->gpio, 0); + gpiod_set_value_cansleep(led_dat->gpiod, 0); return 0; } pulses = 32 - (value * 32) / 255; if (pulses == 0) { - gpio_set_value_cansleep(led_dat->gpio, 0); + gpiod_set_value_cansleep(led_dat->gpiod, 0); mdelay(1); - gpio_set_value_cansleep(led_dat->gpio, 1); + gpiod_set_value_cansleep(led_dat->gpiod, 1); return 0; } - gpio_set_value_cansleep(led_dat->gpio, 1); + gpiod_set_value_cansleep(led_dat->gpiod, 1); while (pulses--) { - gpio_set_value_cansleep(led_dat->gpio, 0); + gpiod_set_value_cansleep(led_dat->gpiod, 0); udelay(1); - gpio_set_value_cansleep(led_dat->gpio, 1); + gpiod_set_value_cansleep(led_dat->gpiod, 1); udelay(1); } @@ -85,15 +86,8 @@ static struct lt3593_led_data *lt3593_led_probe_pdata(struct device *dev) if (!led_data) return ERR_PTR(-ENOMEM); - if (!gpio_is_valid(template->gpio)) { - dev_info(dev, "skipping unavailable LT3593 LED at gpio " - "%d (%s)\n", template->gpio, template->name); - return ERR_PTR(-EINVAL); - } - led_data->cdev.name = template->name; led_data->cdev.default_trigger = template->default_trigger; - led_data->gpio = template->gpio; led_data->cdev.brightness_set_blocking = lt3593_led_set; state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); @@ -108,6 +102,10 @@ static struct lt3593_led_data *lt3593_led_probe_pdata(struct device *dev) if (ret < 0) return ERR_PTR(ret); + led_data->gpiod = gpio_to_desc(template->gpio); + if (!led_data->gpiod) + return ERR_PTR(-EPROBE_DEFER); + ret = devm_led_classdev_register(dev, &led_data->cdev); if (ret < 0) return ERR_PTR(ret); -- cgit v1.2.3-59-g8ed1b From 8cd7d6daba9330383259686d1cc1d64caf857b11 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:36 +0200 Subject: leds: lt3593: Add device tree probing glue The binding details are described in an earlier commit that adds the documentation. Signed-off-by: Daniel Mack Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lt3593.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index a096ee64cbbb..2e35a4a4c571 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -24,8 +24,11 @@ #include #include #include +#include +#include struct lt3593_led_data { + char name[LED_MAX_NAME_SIZE]; struct led_classdev cdev; struct gpio_desc *gpiod; }; @@ -120,22 +123,89 @@ static int lt3593_led_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct lt3593_led_data *led_data; + struct fwnode_handle *child; + int ret, state = LEDS_GPIO_DEFSTATE_OFF; + enum gpiod_flags flags = GPIOD_OUT_LOW; + const char *tmp; if (dev_get_platdata(dev)) { led_data = lt3593_led_probe_pdata(dev); if (IS_ERR(led_data)) return PTR_ERR(led_data); + + goto out; } + if (!dev->of_node) + return -ENODEV; + + led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL); + if (!led_data) + return -ENOMEM; + + if (device_get_child_node_count(dev) != 1) { + dev_err(dev, "Device must have exactly one LED sub-node."); + return -EINVAL; + } + + led_data->gpiod = devm_gpiod_get(dev, "lltc,ctrl", 0); + if (IS_ERR(led_data->gpiod)) + return PTR_ERR(led_data->gpiod); + + child = device_get_next_child_node(dev, NULL); + + ret = fwnode_property_read_string(child, "label", &tmp); + if (ret < 0) + snprintf(led_data->name, sizeof(led_data->name), + "lt3593::"); + else + snprintf(led_data->name, sizeof(led_data->name), + "lt3593:%s", tmp); + + fwnode_property_read_string(child, "linux,default-trigger", + &led_data->cdev.default_trigger); + + if (!fwnode_property_read_string(child, "default-state", &tmp)) { + if (!strcmp(tmp, "keep")) { + state = LEDS_GPIO_DEFSTATE_KEEP; + flags = GPIOD_ASIS; + } else if (!strcmp(tmp, "on")) { + state = LEDS_GPIO_DEFSTATE_ON; + flags = GPIOD_OUT_HIGH; + } + } + + led_data->cdev.name = led_data->name; + led_data->cdev.brightness_set_blocking = lt3593_led_set; + led_data->cdev.brightness = state ? LED_FULL : LED_OFF; + + ret = devm_led_classdev_register(dev, &led_data->cdev); + if (ret < 0) { + fwnode_handle_put(child); + return ret; + } + + led_data->cdev.dev->of_node = dev->of_node; + +out: platform_set_drvdata(pdev, led_data); return 0; } +#ifdef CONFIG_OF +static const struct of_device_id of_lt3593_leds_match[] = { + { .compatible = "lltc,lt3593", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_lt3593_leds_match); +#endif + static struct platform_driver lt3593_led_driver = { .probe = lt3593_led_probe, .driver = { .name = "leds-lt3593", + .of_match_table = of_match_ptr(of_lt3593_leds_match), }, }; -- cgit v1.2.3-59-g8ed1b From dd08ac2e5fbc867c5793c3fc0404ef16390b5206 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 27 Jun 2018 20:52:37 +0200 Subject: leds: lt3593: update email address and switch to SPDX license header Update the email address in the module information and in the comments and in the module information, and drop the existing boilerplate in favor of a SPDX header. Also sync the module license information with the header. Signed-off-by: Daniel Mack Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lt3593.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 2e35a4a4c571..de3623e0d094 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -1,20 +1,5 @@ -/* - * LEDs driver for LT3593 controllers - * - * See the datasheet at http://cds.linear.com/docs/Datasheet/3593f.pdf - * - * Copyright (c) 2009 Daniel Mack - * - * Based on leds-gpio.c, - * - * Copyright (C) 2007 8D Technologies inc. - * Raphael Assenat - * Copyright (C) 2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2009,2018 Daniel Mack #include #include @@ -211,7 +196,7 @@ static struct platform_driver lt3593_led_driver = { module_platform_driver(lt3593_led_driver); -MODULE_AUTHOR("Daniel Mack "); +MODULE_AUTHOR("Daniel Mack "); MODULE_DESCRIPTION("LED driver for LT3593 controllers"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:leds-lt3593"); -- cgit v1.2.3-59-g8ed1b From 7a5de56db902ea632a0ff0c2b47481d278db645f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 2 Jul 2018 17:50:37 +0100 Subject: leds: max8997: use mode when calling max8997_led_set_mode Variable mode is assigned to pdata->led_pdata->mode[led->id] and yet is not being used when calling function max8997_led_set_mode. Fix this by using mode when calling max8997_led_set_mode. Cleans up clang warning: warning: variable 'mode' set but not used [-Wunused-but-set-variable] Fixes: 8584cb82f151 ("leds: Add suuport for MAX8997-LED driver") Signed-off-by: Colin Ian King Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-max8997.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c index 4edf74f1d6d4..8c019c28f9f5 100644 --- a/drivers/leds/leds-max8997.c +++ b/drivers/leds/leds-max8997.c @@ -268,7 +268,7 @@ static int max8997_led_probe(struct platform_device *pdev) mode = pdata->led_pdata->mode[led->id]; brightness = pdata->led_pdata->brightness[led->id]; - max8997_led_set_mode(led, pdata->led_pdata->mode[led->id]); + max8997_led_set_mode(led, mode); if (brightness > led->cdev.max_brightness) brightness = led->cdev.max_brightness; -- cgit v1.2.3-59-g8ed1b From 43d20ff3633112322de38c18b4b35bbbf04438d7 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 2 Jul 2018 13:12:13 -0500 Subject: leds: lm3692x: Update license header to SPDX Update the license header to the current SPDX licensing format. Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3692x.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index 437173d1712c..e518ae36f410 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -1,17 +1,6 @@ -/* - * TI lm3692x LED Driver - * - * Copyright (C) 2017 Texas Instruments - * - * Author: Dan Murphy - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Data sheet is located - * http://www.ti.com/lit/ds/snvsa29/snvsa29.pdf - */ +// SPDX-License-Identifier: GPL-2.0 +// TI LM3692x LED chip family driver +// Copyright (C) 2017-18 Texas Instruments Incorporated - http://www.ti.com/ #include #include -- cgit v1.2.3-59-g8ed1b From 9a5c1c64ac0a4d01c78328283dac7a9dc33ff0f9 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 2 Jul 2018 13:12:14 -0500 Subject: leds: lm3692x: Change DT calls to fwnode calls Update the code to use the fwnode calls as opposed to ARM DT node api's. This allows the device to be used with either DT configurations or ACPI definitions. Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3692x.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index e518ae36f410..9e6432b6a3b5 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -267,30 +267,15 @@ out: static int lm3692x_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int ret; + struct fwnode_handle *child = NULL; struct lm3692x_led *led; - struct device_node *np = client->dev.of_node; - struct device_node *child_node; const char *name; + int ret; led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; - for_each_available_child_of_node(np, child_node) { - led->led_dev.default_trigger = of_get_property(child_node, - "linux,default-trigger", - NULL); - - ret = of_property_read_string(child_node, "label", &name); - if (!ret) - snprintf(led->label, sizeof(led->label), - "%s:%s", id->name, name); - else - snprintf(led->label, sizeof(led->label), - "%s::backlight_cluster", id->name); - }; - led->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(led->enable_gpio)) { @@ -323,6 +308,25 @@ static int lm3692x_probe(struct i2c_client *client, if (ret) return ret; + child = device_get_next_child_node(&led->client->dev, child); + if (!child) { + dev_err(&led->client->dev, "No LED Child node\n"); + return ret; + } + + fwnode_property_read_string(child, "linux,default-trigger", + &led->led_dev.default_trigger); + + ret = fwnode_property_read_string(child, "label", &name); + if (ret) + snprintf(led->label, sizeof(led->label), + "%s::", led->client->name); + else + snprintf(led->label, sizeof(led->label), + "%s:%s", led->client->name, name); + + led->led_dev.dev->of_node = to_of_node(child); + ret = devm_led_classdev_register(&client->dev, &led->led_dev); if (ret) { dev_err(&client->dev, "led register err: %d\n", ret); -- cgit v1.2.3-59-g8ed1b From 581e3ca38a1aa40b742baad39026f440445488d4 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 2 Jul 2018 13:12:15 -0500 Subject: dt: bindings: lm3692x: Update binding for LED sync control Update the binding to be able to configure the LED sync to turn on. The LM36922 has one output but can sync current to 2 LED strings. The user may only use one sync so the other syncs need to be disabled. The LM36923 has 3 LED syncs. Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- Documentation/devicetree/bindings/leds/leds-lm3692x.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt index 6c9074f84a51..08b352840bd7 100644 --- a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt +++ b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt @@ -20,7 +20,10 @@ Optional properties: - vled-supply : LED supply Required child properties: - - reg : 0 + - reg : 0 - Will enable all LED sync paths + 1 - Will enable the LED1 sync + 2 - Will enable the LED2 sync + 3 - Will enable the LED3 sync (LM36923 only) Optional child properties: - label : see Documentation/devicetree/bindings/leds/common.txt -- cgit v1.2.3-59-g8ed1b From 07abd4325e7013c728bf9642fbb862aa9eb4a367 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 2 Jul 2018 13:12:16 -0500 Subject: leds: lm3692x: Support LED sync configuration The LM36922 has one output but can sync current to 2 LED strings. The user may only use one sync so the other syncs need to be disabled. The LM36923 has 3 LED syncs. Signed-off-by: Dan Murphy Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-lm3692x.c | 158 +++++++++++++++++++++++++++++++++----------- 1 file changed, 120 insertions(+), 38 deletions(-) diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index 9e6432b6a3b5..4f413a7c5f05 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -15,6 +15,9 @@ #include #include +#define LM36922_MODEL 0 +#define LM36923_MODEL 1 + #define LM3692X_REV 0x0 #define LM3692X_RESET 0x1 #define LM3692X_EN 0x10 @@ -33,6 +36,9 @@ #define LM3692X_DEVICE_EN BIT(0) #define LM3692X_LED1_EN BIT(1) #define LM3692X_LED2_EN BIT(2) +#define LM36923_LED3_EN BIT(3) +#define LM3692X_ENABLE_MASK (LM3692X_DEVICE_EN | LM3692X_LED1_EN | \ + LM3692X_LED2_EN | LM36923_LED3_EN) /* Brightness Control Bits */ #define LM3692X_BL_ADJ_POL BIT(0) @@ -98,6 +104,8 @@ * @enable_gpio - VDDIO/EN gpio to enable communication interface * @regulator - LED supply regulator pointer * @label - LED label + * @led_enable - LED sync to be enabled + * @model_id - Current device model ID enumerated */ struct lm3692x_led { struct mutex lock; @@ -107,6 +115,8 @@ struct lm3692x_led { struct gpio_desc *enable_gpio; struct regulator *regulator; char label[LED_MAX_NAME_SIZE]; + int led_enable; + int model_id; }; static const struct reg_default lm3692x_reg_defs[] = { @@ -189,6 +199,7 @@ out: static int lm3692x_init(struct lm3692x_led *led) { + int enable_state; int ret; if (led->regulator) { @@ -215,9 +226,25 @@ static int lm3692x_init(struct lm3692x_led *led) /* * For glitch free operation, the following data should - * only be written while device enable bit is 0 + * only be written while LEDx enable bits are 0 and the device enable + * bit is set to 1. * per Section 7.5.14 of the data sheet */ + ret = regmap_write(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN); + if (ret) + goto out; + + /* Set the brightness to 0 so when enabled the LEDs do not come + * on with full brightness. + */ + ret = regmap_write(led->regmap, LM3692X_BRT_MSB, 0); + if (ret) + goto out; + + ret = regmap_write(led->regmap, LM3692X_BRT_LSB, 0); + if (ret) + goto out; + ret = regmap_write(led->regmap, LM3692X_PWM_CTRL, LM3692X_PWM_FILTER_100 | LM3692X_PWM_SAMP_24MHZ); if (ret) @@ -247,6 +274,38 @@ static int lm3692x_init(struct lm3692x_led *led) if (ret) goto out; + switch (led->led_enable) { + case 0: + default: + if (led->model_id == LM36923_MODEL) + enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN | + LM36923_LED3_EN; + else + enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN; + + break; + case 1: + enable_state = LM3692X_LED1_EN; + break; + case 2: + enable_state = LM3692X_LED2_EN; + break; + + case 3: + if (led->model_id == LM36923_MODEL) { + enable_state = LM36923_LED3_EN; + break; + } + + ret = -EINVAL; + dev_err(&led->client->dev, + "LED3 sync not available on this device\n"); + goto out; + } + + ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_ENABLE_MASK, + enable_state | LM3692X_DEVICE_EN); + return ret; out: dev_err(&led->client->dev, "Fail writing initialization values\n"); @@ -263,55 +322,29 @@ out: return ret; } - -static int lm3692x_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int lm3692x_probe_dt(struct lm3692x_led *led) { struct fwnode_handle *child = NULL; - struct lm3692x_led *led; const char *name; int ret; - led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); - if (!led) - return -ENOMEM; - - led->enable_gpio = devm_gpiod_get_optional(&client->dev, + led->enable_gpio = devm_gpiod_get_optional(&led->client->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(led->enable_gpio)) { ret = PTR_ERR(led->enable_gpio); - dev_err(&client->dev, "Failed to get enable gpio: %d\n", ret); + dev_err(&led->client->dev, "Failed to get enable gpio: %d\n", + ret); return ret; } - led->regulator = devm_regulator_get(&client->dev, "vled"); + led->regulator = devm_regulator_get(&led->client->dev, "vled"); if (IS_ERR(led->regulator)) led->regulator = NULL; - led->client = client; - led->led_dev.name = led->label; - led->led_dev.brightness_set_blocking = lm3692x_brightness_set; - - mutex_init(&led->lock); - - i2c_set_clientdata(client, led); - - led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config); - if (IS_ERR(led->regmap)) { - ret = PTR_ERR(led->regmap); - dev_err(&client->dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } - - ret = lm3692x_init(led); - if (ret) - return ret; - child = device_get_next_child_node(&led->client->dev, child); if (!child) { dev_err(&led->client->dev, "No LED Child node\n"); - return ret; + return -ENODEV; } fwnode_property_read_string(child, "linux,default-trigger", @@ -325,14 +358,57 @@ static int lm3692x_probe(struct i2c_client *client, snprintf(led->label, sizeof(led->label), "%s:%s", led->client->name, name); - led->led_dev.dev->of_node = to_of_node(child); + ret = fwnode_property_read_u32(child, "reg", &led->led_enable); + if (ret) { + dev_err(&led->client->dev, "reg DT property missing\n"); + return ret; + } + + led->led_dev.name = led->label; - ret = devm_led_classdev_register(&client->dev, &led->led_dev); + ret = devm_led_classdev_register(&led->client->dev, &led->led_dev); if (ret) { - dev_err(&client->dev, "led register err: %d\n", ret); + dev_err(&led->client->dev, "led register err: %d\n", ret); + return ret; + } + + led->led_dev.dev->of_node = to_of_node(child); + + return 0; +} + +static int lm3692x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lm3692x_led *led; + int ret; + + led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); + if (!led) + return -ENOMEM; + + mutex_init(&led->lock); + led->client = client; + led->led_dev.brightness_set_blocking = lm3692x_brightness_set; + led->model_id = id->driver_data; + i2c_set_clientdata(client, led); + + led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config); + if (IS_ERR(led->regmap)) { + ret = PTR_ERR(led->regmap); + dev_err(&client->dev, "Failed to allocate register map: %d\n", + ret); return ret; } + ret = lm3692x_probe_dt(led); + if (ret) + return ret; + + ret = lm3692x_init(led); + if (ret) + return ret; + return 0; } @@ -341,6 +417,12 @@ static int lm3692x_remove(struct i2c_client *client) struct lm3692x_led *led = i2c_get_clientdata(client); int ret; + ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN, 0); + if (ret) { + dev_err(&led->client->dev, "Failed to disable regulator\n"); + return ret; + } + if (led->enable_gpio) gpiod_direction_output(led->enable_gpio, 0); @@ -357,8 +439,8 @@ static int lm3692x_remove(struct i2c_client *client) } static const struct i2c_device_id lm3692x_id[] = { - { "lm36922", 0 }, - { "lm36923", 1 }, + { "lm36922", LM36922_MODEL }, + { "lm36923", LM36923_MODEL }, { } }; MODULE_DEVICE_TABLE(i2c, lm3692x_id); -- cgit v1.2.3-59-g8ed1b From 033692eb3ec8305f6e9998b297aaec6899680637 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:20 +0200 Subject: leds: triggers: make the MODULE_LICENSE string match the actual license MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These files are licensed under GPL version 2 only. So use "GPL v2" instead of "GPL" (which means v2 or later). Also remove an empty (but commented) line at the end of the license header which nicely proves in the context that the drivers are really v2 only :-) Signed-off-by: Uwe Kleine-König Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-activity.c | 4 ++-- drivers/leds/trigger/ledtrig-camera.c | 3 +-- drivers/leds/trigger/ledtrig-default-on.c | 3 +-- drivers/leds/trigger/ledtrig-gpio.c | 3 +-- drivers/leds/trigger/ledtrig-heartbeat.c | 4 ++-- drivers/leds/trigger/ledtrig-timer.c | 3 +-- 6 files changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-activity.c b/drivers/leds/trigger/ledtrig-activity.c index 6c6f8a9b8d9a..b39e1bb9a9ec 100644 --- a/drivers/leds/trigger/ledtrig-activity.c +++ b/drivers/leds/trigger/ledtrig-activity.c @@ -7,8 +7,8 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ + #include #include #include @@ -269,4 +269,4 @@ module_exit(activity_exit); MODULE_AUTHOR("Willy Tarreau "); MODULE_DESCRIPTION("Activity LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-camera.c b/drivers/leds/trigger/ledtrig-camera.c index 9bd73a8bad5c..091a09a20c58 100644 --- a/drivers/leds/trigger/ledtrig-camera.c +++ b/drivers/leds/trigger/ledtrig-camera.c @@ -10,7 +10,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include @@ -54,4 +53,4 @@ module_exit(ledtrig_camera_exit); MODULE_DESCRIPTION("LED Trigger for Camera Flash/Torch Control"); MODULE_AUTHOR("Milo Kim"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-default-on.c b/drivers/leds/trigger/ledtrig-default-on.c index ff455cb46680..4ccea04b7a6b 100644 --- a/drivers/leds/trigger/ledtrig-default-on.c +++ b/drivers/leds/trigger/ledtrig-default-on.c @@ -8,7 +8,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include @@ -42,4 +41,4 @@ module_exit(defon_trig_exit); MODULE_AUTHOR("Nick Forbes "); MODULE_DESCRIPTION("Default-ON LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c index 8891e88d54dd..93906a17a4b6 100644 --- a/drivers/leds/trigger/ledtrig-gpio.c +++ b/drivers/leds/trigger/ledtrig-gpio.c @@ -6,7 +6,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include @@ -235,4 +234,4 @@ module_exit(gpio_trig_exit); MODULE_AUTHOR("Felipe Balbi "); MODULE_DESCRIPTION("GPIO LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c index f0896de410b8..304b929edb8e 100644 --- a/drivers/leds/trigger/ledtrig-heartbeat.c +++ b/drivers/leds/trigger/ledtrig-heartbeat.c @@ -9,8 +9,8 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ + #include #include #include @@ -213,4 +213,4 @@ module_exit(heartbeat_trig_exit); MODULE_AUTHOR("Atsushi Nemoto "); MODULE_DESCRIPTION("Heartbeat LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c index 8d09327b5719..10fc0966b0e3 100644 --- a/drivers/leds/trigger/ledtrig-timer.c +++ b/drivers/leds/trigger/ledtrig-timer.c @@ -8,7 +8,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include @@ -127,4 +126,4 @@ module_exit(timer_trig_exit); MODULE_AUTHOR("Richard Purdie "); MODULE_DESCRIPTION("Timer LED trigger"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-59-g8ed1b From 2282e125a406e09331c5a785e3df29035c99a607 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:21 +0200 Subject: leds: triggers: let struct led_trigger::activate() return an error code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that activating a trigger can fail, let the callback return an indication. This prevents to have a trigger active according to the "trigger" sysfs attribute but not functional. All users are changed accordingly to return 0 for now. There is no intended change in behaviour. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/led-triggers.c | 24 +++++++++++++++++++++--- drivers/leds/trigger/ledtrig-activity.c | 8 +++++--- drivers/leds/trigger/ledtrig-backlight.c | 8 +++++--- drivers/leds/trigger/ledtrig-default-on.c | 3 ++- drivers/leds/trigger/ledtrig-gpio.c | 8 +++++--- drivers/leds/trigger/ledtrig-heartbeat.c | 8 +++++--- drivers/leds/trigger/ledtrig-netdev.c | 8 +++++--- drivers/leds/trigger/ledtrig-oneshot.c | 8 +++++--- drivers/leds/trigger/ledtrig-timer.c | 8 +++++--- drivers/leds/trigger/ledtrig-transient.c | 8 +++++--- drivers/tty/vt/keyboard.c | 4 +++- drivers/usb/core/ledtrig-usbport.c | 7 ++++--- include/linux/leds.h | 14 +++++++++----- net/bluetooth/leds.c | 6 ++++-- net/mac80211/led.c | 20 +++++++++++++++----- net/rfkill/core.c | 4 +++- 16 files changed, 101 insertions(+), 45 deletions(-) diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 431123b048a2..a8786f4b3453 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -103,15 +103,16 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, EXPORT_SYMBOL_GPL(led_trigger_show); /* Caller must ensure led_cdev->trigger_lock held */ -void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) +int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) { unsigned long flags; char *event = NULL; char *envp[2]; const char *name; + int ret; if (!led_cdev->trigger && !trig) - return; + return 0; name = trig ? trig->name : "none"; event = kasprintf(GFP_KERNEL, "TRIGGER=%s", name); @@ -134,8 +135,14 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) list_add_tail(&led_cdev->trig_list, &trig->led_cdevs); write_unlock_irqrestore(&trig->leddev_list_lock, flags); led_cdev->trigger = trig; + if (trig->activate) - trig->activate(led_cdev); + ret = trig->activate(led_cdev); + else + ret = 0; + + if (ret) + goto err_activate; } if (event) { @@ -146,6 +153,17 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) "%s: Error sending uevent\n", __func__); kfree(event); } + + return 0; + +err_activate: + led_cdev->trigger = NULL; + write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); + list_del(&led_cdev->trig_list); + write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); + led_set_brightness(led_cdev, LED_OFF); + + return ret; } EXPORT_SYMBOL_GPL(led_trigger_set); diff --git a/drivers/leds/trigger/ledtrig-activity.c b/drivers/leds/trigger/ledtrig-activity.c index b39e1bb9a9ec..2fc065fb1754 100644 --- a/drivers/leds/trigger/ledtrig-activity.c +++ b/drivers/leds/trigger/ledtrig-activity.c @@ -178,20 +178,20 @@ static ssize_t led_invert_store(struct device *dev, static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); -static void activity_activate(struct led_classdev *led_cdev) +static int activity_activate(struct led_classdev *led_cdev) { struct activity_data *activity_data; int rc; activity_data = kzalloc(sizeof(*activity_data), GFP_KERNEL); if (!activity_data) - return; + return 0; led_cdev->trigger_data = activity_data; rc = device_create_file(led_cdev->dev, &dev_attr_invert); if (rc) { kfree(led_cdev->trigger_data); - return; + return 0; } activity_data->led_cdev = led_cdev; @@ -201,6 +201,8 @@ static void activity_activate(struct led_classdev *led_cdev) led_activity_function(&activity_data->timer); set_bit(LED_BLINK_SW, &led_cdev->work_flags); led_cdev->activated = true; + + return 0; } static void activity_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-backlight.c b/drivers/leds/trigger/ledtrig-backlight.c index 1ca1f1608f76..84512960d630 100644 --- a/drivers/leds/trigger/ledtrig-backlight.c +++ b/drivers/leds/trigger/ledtrig-backlight.c @@ -97,7 +97,7 @@ static ssize_t bl_trig_invert_store(struct device *dev, } static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store); -static void bl_trig_activate(struct led_classdev *led) +static int bl_trig_activate(struct led_classdev *led) { int ret; @@ -107,7 +107,7 @@ static void bl_trig_activate(struct led_classdev *led) led->trigger_data = n; if (!n) { dev_err(led->dev, "unable to allocate backlight trigger\n"); - return; + return 0; } ret = device_create_file(led->dev, &dev_attr_inverted); @@ -124,11 +124,13 @@ static void bl_trig_activate(struct led_classdev *led) dev_err(led->dev, "unable to register backlight trigger\n"); led->activated = true; - return; + return 0; err_invert: led->trigger_data = NULL; kfree(n); + + return 0; } static void bl_trig_deactivate(struct led_classdev *led) diff --git a/drivers/leds/trigger/ledtrig-default-on.c b/drivers/leds/trigger/ledtrig-default-on.c index 4ccea04b7a6b..2996fe672198 100644 --- a/drivers/leds/trigger/ledtrig-default-on.c +++ b/drivers/leds/trigger/ledtrig-default-on.c @@ -16,9 +16,10 @@ #include #include "../leds.h" -static void defon_trig_activate(struct led_classdev *led_cdev) +static int defon_trig_activate(struct led_classdev *led_cdev) { led_set_brightness_nosleep(led_cdev, led_cdev->max_brightness); + return 0; } static struct led_trigger defon_led_trigger = { diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c index 93906a17a4b6..f5358c40d03f 100644 --- a/drivers/leds/trigger/ledtrig-gpio.c +++ b/drivers/leds/trigger/ledtrig-gpio.c @@ -162,14 +162,14 @@ static ssize_t gpio_trig_gpio_store(struct device *dev, } static DEVICE_ATTR(gpio, 0644, gpio_trig_gpio_show, gpio_trig_gpio_store); -static void gpio_trig_activate(struct led_classdev *led) +static int gpio_trig_activate(struct led_classdev *led) { struct gpio_trig_data *gpio_data; int ret; gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL); if (!gpio_data) - return; + return 0; ret = device_create_file(led->dev, &dev_attr_gpio); if (ret) @@ -187,7 +187,7 @@ static void gpio_trig_activate(struct led_classdev *led) led->trigger_data = gpio_data; led->activated = true; - return; + return 0; err_brightness: device_remove_file(led->dev, &dev_attr_inverted); @@ -197,6 +197,8 @@ err_inverted: err_gpio: kfree(gpio_data); + + return 0; } static void gpio_trig_deactivate(struct led_classdev *led) diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c index 304b929edb8e..03a8dfce8fb9 100644 --- a/drivers/leds/trigger/ledtrig-heartbeat.c +++ b/drivers/leds/trigger/ledtrig-heartbeat.c @@ -121,21 +121,21 @@ static ssize_t led_invert_store(struct device *dev, static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); -static void heartbeat_trig_activate(struct led_classdev *led_cdev) +static int heartbeat_trig_activate(struct led_classdev *led_cdev) { struct heartbeat_trig_data *heartbeat_data; int rc; heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); if (!heartbeat_data) - return; + return 0; led_cdev->trigger_data = heartbeat_data; heartbeat_data->led_cdev = led_cdev; rc = device_create_file(led_cdev->dev, &dev_attr_invert); if (rc) { kfree(led_cdev->trigger_data); - return; + return 0; } timer_setup(&heartbeat_data->timer, led_heartbeat_function, 0); @@ -145,6 +145,8 @@ static void heartbeat_trig_activate(struct led_classdev *led_cdev) led_heartbeat_function(&heartbeat_data->timer); set_bit(LED_BLINK_SW, &led_cdev->work_flags); led_cdev->activated = true; + + return 0; } static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index 6df4781a6308..bb05937255de 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -388,14 +388,14 @@ static void netdev_trig_work(struct work_struct *work) (atomic_read(&trigger_data->interval)*2)); } -static void netdev_trig_activate(struct led_classdev *led_cdev) +static int netdev_trig_activate(struct led_classdev *led_cdev) { struct led_netdev_data *trigger_data; int rc; trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); if (!trigger_data) - return; + return 0; spin_lock_init(&trigger_data->lock); @@ -432,7 +432,7 @@ static void netdev_trig_activate(struct led_classdev *led_cdev) rc = register_netdevice_notifier(&trigger_data->notifier); if (rc) goto err_out_interval; - return; + return 0; err_out_interval: device_remove_file(led_cdev->dev, &dev_attr_interval); @@ -447,6 +447,8 @@ err_out_device_name: err_out: led_cdev->trigger_data = NULL; kfree(trigger_data); + + return 0; } static void netdev_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-oneshot.c b/drivers/leds/trigger/ledtrig-oneshot.c index b8ea9f0f1e19..7bbf92bd7f80 100644 --- a/drivers/leds/trigger/ledtrig-oneshot.c +++ b/drivers/leds/trigger/ledtrig-oneshot.c @@ -122,14 +122,14 @@ static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); static DEVICE_ATTR(shot, 0200, NULL, led_shot); -static void oneshot_trig_activate(struct led_classdev *led_cdev) +static int oneshot_trig_activate(struct led_classdev *led_cdev) { struct oneshot_trig_data *oneshot_data; int rc; oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL); if (!oneshot_data) - return; + return 0; led_cdev->trigger_data = oneshot_data; @@ -151,7 +151,7 @@ static void oneshot_trig_activate(struct led_classdev *led_cdev) led_cdev->activated = true; - return; + return 0; err_out_invert: device_remove_file(led_cdev->dev, &dev_attr_invert); @@ -161,6 +161,8 @@ err_out_delayon: device_remove_file(led_cdev->dev, &dev_attr_delay_on); err_out_trig_data: kfree(led_cdev->trigger_data); + + return 0; } static void oneshot_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c index 10fc0966b0e3..527055d815ad 100644 --- a/drivers/leds/trigger/ledtrig-timer.c +++ b/drivers/leds/trigger/ledtrig-timer.c @@ -70,7 +70,7 @@ static ssize_t led_delay_off_store(struct device *dev, static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); -static void timer_trig_activate(struct led_classdev *led_cdev) +static int timer_trig_activate(struct led_classdev *led_cdev) { int rc; @@ -78,7 +78,7 @@ static void timer_trig_activate(struct led_classdev *led_cdev) rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); if (rc) - return; + return 0; rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); if (rc) goto err_out_delayon; @@ -87,10 +87,12 @@ static void timer_trig_activate(struct led_classdev *led_cdev) &led_cdev->blink_delay_off); led_cdev->activated = true; - return; + return 0; err_out_delayon: device_remove_file(led_cdev->dev, &dev_attr_delay_on); + + return 0; } static void timer_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/leds/trigger/ledtrig-transient.c b/drivers/leds/trigger/ledtrig-transient.c index 9d1769073562..a55fc58179a9 100644 --- a/drivers/leds/trigger/ledtrig-transient.c +++ b/drivers/leds/trigger/ledtrig-transient.c @@ -152,7 +152,7 @@ static DEVICE_ATTR(duration, 0644, transient_duration_show, transient_duration_store); static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store); -static void transient_trig_activate(struct led_classdev *led_cdev) +static int transient_trig_activate(struct led_classdev *led_cdev) { int rc; struct transient_trig_data *tdata; @@ -161,7 +161,7 @@ static void transient_trig_activate(struct led_classdev *led_cdev) if (!tdata) { dev_err(led_cdev->dev, "unable to allocate transient trigger\n"); - return; + return 0; } led_cdev->trigger_data = tdata; tdata->led_cdev = led_cdev; @@ -181,7 +181,7 @@ static void transient_trig_activate(struct led_classdev *led_cdev) timer_setup(&tdata->timer, transient_timer_function, 0); led_cdev->activated = true; - return; + return 0; err_out_state: device_remove_file(led_cdev->dev, &dev_attr_duration); @@ -191,6 +191,8 @@ err_out: dev_err(led_cdev->dev, "unable to register transient trigger\n"); led_cdev->trigger_data = NULL; kfree(tdata); + + return 0; } static void transient_trig_deactivate(struct led_classdev *led_cdev) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index d5b4a2b44ab8..de310621b8e7 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -959,7 +959,7 @@ struct kbd_led_trigger { unsigned int mask; }; -static void kbd_led_trigger_activate(struct led_classdev *cdev) +static int kbd_led_trigger_activate(struct led_classdev *cdev) { struct kbd_led_trigger *trigger = container_of(cdev->trigger, struct kbd_led_trigger, trigger); @@ -970,6 +970,8 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev) ledstate & trigger->mask ? LED_FULL : LED_OFF); tasklet_enable(&keyboard_tasklet); + + return 0; } #define KBD_LED_TRIGGER(_led_bit, _name) { \ diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c index d775ffea20c3..aa1d51458da7 100644 --- a/drivers/usb/core/ledtrig-usbport.c +++ b/drivers/usb/core/ledtrig-usbport.c @@ -298,14 +298,14 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action, return NOTIFY_DONE; } -static void usbport_trig_activate(struct led_classdev *led_cdev) +static int usbport_trig_activate(struct led_classdev *led_cdev) { struct usbport_trig_data *usbport_data; int err; usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL); if (!usbport_data) - return; + return 0; usbport_data->led_cdev = led_cdev; /* List of ports */ @@ -322,10 +322,11 @@ static void usbport_trig_activate(struct led_classdev *led_cdev) usb_register_notify(&usbport_data->nb); led_cdev->activated = true; - return; + return 0; err_free: kfree(usbport_data); + return 0; } static void usbport_trig_deactivate(struct led_classdev *led_cdev) diff --git a/include/linux/leds.h b/include/linux/leds.h index b7e82550e655..ba5baaaa43bf 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -253,7 +253,7 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) struct led_trigger { /* Trigger Properties */ const char *name; - void (*activate)(struct led_classdev *led_cdev); + int (*activate)(struct led_classdev *led_cdev); void (*deactivate)(struct led_classdev *led_cdev); /* LEDs under control by this trigger (for simple triggers) */ @@ -288,8 +288,8 @@ extern void led_trigger_blink_oneshot(struct led_trigger *trigger, unsigned long *delay_off, int invert); extern void led_trigger_set_default(struct led_classdev *led_cdev); -extern void led_trigger_set(struct led_classdev *led_cdev, - struct led_trigger *trigger); +extern int led_trigger_set(struct led_classdev *led_cdev, + struct led_trigger *trigger); extern void led_trigger_remove(struct led_classdev *led_cdev); static inline void *led_get_trigger_data(struct led_classdev *led_cdev) @@ -334,8 +334,12 @@ static inline void led_trigger_blink_oneshot(struct led_trigger *trigger, unsigned long *delay_off, int invert) {} static inline void led_trigger_set_default(struct led_classdev *led_cdev) {} -static inline void led_trigger_set(struct led_classdev *led_cdev, - struct led_trigger *trigger) {} +static inline int led_trigger_set(struct led_classdev *led_cdev, + struct led_trigger *trigger) +{ + return 0; +} + static inline void led_trigger_remove(struct led_classdev *led_cdev) {} static inline void *led_get_trigger_data(struct led_classdev *led_cdev) { diff --git a/net/bluetooth/leds.c b/net/bluetooth/leds.c index cb670b5594eb..6d59a5023231 100644 --- a/net/bluetooth/leds.c +++ b/net/bluetooth/leds.c @@ -43,7 +43,7 @@ void hci_leds_update_powered(struct hci_dev *hdev, bool enabled) led_trigger_event(bt_power_led_trigger, enabled ? LED_FULL : LED_OFF); } -static void power_activate(struct led_classdev *led_cdev) +static int power_activate(struct led_classdev *led_cdev) { struct hci_basic_led_trigger *htrig; bool powered; @@ -52,10 +52,12 @@ static void power_activate(struct led_classdev *led_cdev) powered = test_bit(HCI_UP, &htrig->hdev->flags); led_trigger_event(led_cdev->trigger, powered ? LED_FULL : LED_OFF); + + return 0; } static struct led_trigger *led_allocate_basic(struct hci_dev *hdev, - void (*activate)(struct led_classdev *led_cdev), + int (*activate)(struct led_classdev *led_cdev), const char *name) { struct hci_basic_led_trigger *htrig; diff --git a/net/mac80211/led.c b/net/mac80211/led.c index ba0b507ea691..d6c66fc19716 100644 --- a/net/mac80211/led.c +++ b/net/mac80211/led.c @@ -52,13 +52,15 @@ void ieee80211_free_led_names(struct ieee80211_local *local) kfree(local->radio_led.name); } -static void ieee80211_tx_led_activate(struct led_classdev *led_cdev) +static int ieee80211_tx_led_activate(struct led_classdev *led_cdev) { struct ieee80211_local *local = container_of(led_cdev->trigger, struct ieee80211_local, tx_led); atomic_inc(&local->tx_led_active); + + return 0; } static void ieee80211_tx_led_deactivate(struct led_classdev *led_cdev) @@ -70,13 +72,15 @@ static void ieee80211_tx_led_deactivate(struct led_classdev *led_cdev) atomic_dec(&local->tx_led_active); } -static void ieee80211_rx_led_activate(struct led_classdev *led_cdev) +static int ieee80211_rx_led_activate(struct led_classdev *led_cdev) { struct ieee80211_local *local = container_of(led_cdev->trigger, struct ieee80211_local, rx_led); atomic_inc(&local->rx_led_active); + + return 0; } static void ieee80211_rx_led_deactivate(struct led_classdev *led_cdev) @@ -88,13 +92,15 @@ static void ieee80211_rx_led_deactivate(struct led_classdev *led_cdev) atomic_dec(&local->rx_led_active); } -static void ieee80211_assoc_led_activate(struct led_classdev *led_cdev) +static int ieee80211_assoc_led_activate(struct led_classdev *led_cdev) { struct ieee80211_local *local = container_of(led_cdev->trigger, struct ieee80211_local, assoc_led); atomic_inc(&local->assoc_led_active); + + return 0; } static void ieee80211_assoc_led_deactivate(struct led_classdev *led_cdev) @@ -106,13 +112,15 @@ static void ieee80211_assoc_led_deactivate(struct led_classdev *led_cdev) atomic_dec(&local->assoc_led_active); } -static void ieee80211_radio_led_activate(struct led_classdev *led_cdev) +static int ieee80211_radio_led_activate(struct led_classdev *led_cdev) { struct ieee80211_local *local = container_of(led_cdev->trigger, struct ieee80211_local, radio_led); atomic_inc(&local->radio_led_active); + + return 0; } static void ieee80211_radio_led_deactivate(struct led_classdev *led_cdev) @@ -124,13 +132,15 @@ static void ieee80211_radio_led_deactivate(struct led_classdev *led_cdev) atomic_dec(&local->radio_led_active); } -static void ieee80211_tpt_led_activate(struct led_classdev *led_cdev) +static int ieee80211_tpt_led_activate(struct led_classdev *led_cdev) { struct ieee80211_local *local = container_of(led_cdev->trigger, struct ieee80211_local, tpt_led); atomic_inc(&local->tpt_led_active); + + return 0; } static void ieee80211_tpt_led_deactivate(struct led_classdev *led_cdev) diff --git a/net/rfkill/core.c b/net/rfkill/core.c index a7a4e6ff9be2..1355f5ca8d22 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -141,13 +141,15 @@ static void rfkill_led_trigger_event(struct rfkill *rfkill) led_trigger_event(trigger, LED_FULL); } -static void rfkill_led_trigger_activate(struct led_classdev *led) +static int rfkill_led_trigger_activate(struct led_classdev *led) { struct rfkill *rfkill; rfkill = container_of(led->trigger, struct rfkill, led_trigger); rfkill_led_trigger_event(rfkill); + + return 0; } const char *rfkill_get_led_trigger_name(struct rfkill *rfkill) -- cgit v1.2.3-59-g8ed1b From a7e7a3156300a7e1982b03cc9cb8fb0c86434c49 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:22 +0200 Subject: leds: triggers: add device attribute support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As many triggers use device attributes, add support for these in led_trigger_set which allows simplifying the drivers accordingly. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/led-triggers.c | 12 ++++++++++++ include/linux/leds.h | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index a8786f4b3453..3f3e8728d82c 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -127,6 +127,7 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) led_stop_software_blink(led_cdev); if (led_cdev->trigger->deactivate) led_cdev->trigger->deactivate(led_cdev); + device_remove_groups(led_cdev->dev, led_cdev->trigger->groups); led_cdev->trigger = NULL; led_set_brightness(led_cdev, LED_OFF); } @@ -143,6 +144,12 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) if (ret) goto err_activate; + + ret = device_add_groups(led_cdev->dev, trig->groups); + if (ret) { + dev_err(led_cdev->dev, "Failed to add trigger attributes\n"); + goto err_add_groups; + } } if (event) { @@ -156,7 +163,12 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) return 0; +err_add_groups: + + if (trig->deactivate) + trig->deactivate(led_cdev); err_activate: + led_cdev->trigger = NULL; write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); list_del(&led_cdev->trig_list); diff --git a/include/linux/leds.h b/include/linux/leds.h index ba5baaaa43bf..33484a5c7478 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -262,8 +262,19 @@ struct led_trigger { /* Link to next registered trigger */ struct list_head next_trig; + + const struct attribute_group **groups; }; +/* + * Currently the attributes in struct led_trigger::groups are added directly to + * the LED device. As this might change in the future, the following + * macros abstract getting the LED device and its trigger_data from the dev + * parameter passed to the attribute accessor functions. + */ +#define led_trigger_get_led(dev) ((struct led_classdev *)dev_get_drvdata((dev))) +#define led_trigger_get_drvdata(dev) (led_get_trigger_data(led_trigger_get_led(dev))) + ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, -- cgit v1.2.3-59-g8ed1b From a7d5904a6f44e0da05d62197521ec7d96cebb6aa Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:23 +0200 Subject: leds: triggers: handle .trigger_data and .activated() in the core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps keeping these two fields consistent and drivers don't need to care for this themselves any more. Note that .activated isn't set to true automatically because that might confuse some triggers when deactivating (e.g. ledtrig-gpio). Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/led-triggers.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 3f3e8728d82c..17d73db1456e 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -129,6 +129,8 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) led_cdev->trigger->deactivate(led_cdev); device_remove_groups(led_cdev->dev, led_cdev->trigger->groups); led_cdev->trigger = NULL; + led_cdev->trigger_data = NULL; + led_cdev->activated = false; led_set_brightness(led_cdev, LED_OFF); } if (trig) { @@ -170,6 +172,7 @@ err_add_groups: err_activate: led_cdev->trigger = NULL; + led_cdev->trigger_data = NULL; write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); list_del(&led_cdev->trig_list); write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); -- cgit v1.2.3-59-g8ed1b From a0b750768371e410d77b60bcf49c18bd45078d55 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:24 +0200 Subject: leds: triggers: define module_led_trigger helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps to simplify modules that provide a simple led_trigger. It's inspired by module_platform_driver, module_i2c_driver et al. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- include/linux/leds.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/leds.h b/include/linux/leds.h index 33484a5c7478..a3ee10846a4b 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -326,6 +326,10 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev) extern void led_trigger_rename_static(const char *name, struct led_trigger *trig); +#define module_led_trigger(__led_trigger) \ + module_driver(__led_trigger, led_trigger_register, \ + led_trigger_unregister) + #else /* Trigger has no members */ -- cgit v1.2.3-59-g8ed1b From 9acc560de2aac73ef99c54f0fdfb86b4684296b5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:25 +0200 Subject: leds: triggers: new function led_set_trigger_data() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the natural counter part to the already existing led_get_trigger_data(). Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- include/linux/leds.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/leds.h b/include/linux/leds.h index a3ee10846a4b..834683d603f9 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -303,6 +303,12 @@ extern int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger); extern void led_trigger_remove(struct led_classdev *led_cdev); +static inline void led_set_trigger_data(struct led_classdev *led_cdev, + void *trigger_data) +{ + led_cdev->trigger_data = trigger_data; +} + static inline void *led_get_trigger_data(struct led_classdev *led_cdev) { return led_cdev->trigger_data; @@ -356,6 +362,7 @@ static inline int led_trigger_set(struct led_classdev *led_cdev, } static inline void led_trigger_remove(struct led_classdev *led_cdev) {} +static inline void led_set_trigger_data(struct led_classdev *led_cdev) {} static inline void *led_get_trigger_data(struct led_classdev *led_cdev) { return NULL; -- cgit v1.2.3-59-g8ed1b From f8112a1de1a728ffef0dd9f6c3005490c5f79ab1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:26 +0200 Subject: leds: netdev trigger: simplifications from core changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trigger core learned error handling for the activate callback and can handle device attributes now. This allows simplifying the driver considerably. Note that .deactivate() is only called when .activate() succeeded, so the check for trigger_data being non-NULL can go away. (It was broken before because the core didn't clear .trigger_data, so it might have been non-NULL even if .activate() failed before.) Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-netdev.c | 99 +++++++++++------------------------ 1 file changed, 31 insertions(+), 68 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index bb05937255de..3dd3ed46d473 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -94,8 +94,7 @@ static void set_baseline_state(struct led_netdev_data *trigger_data) static ssize_t device_name_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); ssize_t len; spin_lock_bh(&trigger_data->lock); @@ -109,8 +108,7 @@ static ssize_t device_name_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); if (size >= IFNAMSIZ) return -EINVAL; @@ -150,8 +148,7 @@ static DEVICE_ATTR_RW(device_name); static ssize_t netdev_led_attr_show(struct device *dev, char *buf, enum netdev_led_attr attr) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); int bit; switch (attr) { @@ -174,8 +171,7 @@ static ssize_t netdev_led_attr_show(struct device *dev, char *buf, static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, size_t size, enum netdev_led_attr attr) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); unsigned long state; int ret; int bit; @@ -255,8 +251,7 @@ static DEVICE_ATTR_RW(rx); static ssize_t interval_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); return sprintf(buf, "%u\n", jiffies_to_msecs(atomic_read(&trigger_data->interval))); @@ -266,8 +261,7 @@ static ssize_t interval_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct led_netdev_data *trigger_data = led_cdev->trigger_data; + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); unsigned long value; int ret; @@ -288,15 +282,23 @@ static ssize_t interval_store(struct device *dev, static DEVICE_ATTR_RW(interval); +static struct attribute *netdev_trig_attrs[] = { + &dev_attr_device_name.attr, + &dev_attr_link.attr, + &dev_attr_rx.attr, + &dev_attr_tx.attr, + &dev_attr_interval.attr, + NULL +}; +ATTRIBUTE_GROUPS(netdev_trig); + static int netdev_trig_notify(struct notifier_block *nb, unsigned long evt, void *dv) { struct net_device *dev = netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv); - struct led_netdev_data *trigger_data = container_of(nb, - struct - led_netdev_data, - notifier); + struct led_netdev_data *trigger_data = + container_of(nb, struct led_netdev_data, notifier); if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER @@ -342,10 +344,8 @@ static int netdev_trig_notify(struct notifier_block *nb, /* here's the real work! */ static void netdev_trig_work(struct work_struct *work) { - struct led_netdev_data *trigger_data = container_of(work, - struct - led_netdev_data, - work.work); + struct led_netdev_data *trigger_data = + container_of(work, struct led_netdev_data, work.work); struct rtnl_link_stats64 *dev_stats; unsigned int new_activity; struct rtnl_link_stats64 temp; @@ -395,7 +395,7 @@ static int netdev_trig_activate(struct led_classdev *led_cdev) trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); if (!trigger_data) - return 0; + return -ENOMEM; spin_lock_init(&trigger_data->lock); @@ -412,71 +412,34 @@ static int netdev_trig_activate(struct led_classdev *led_cdev) atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); trigger_data->last_activity = 0; - led_cdev->trigger_data = trigger_data; + led_set_trigger_data(led_cdev, trigger_data); - rc = device_create_file(led_cdev->dev, &dev_attr_device_name); - if (rc) - goto err_out; - rc = device_create_file(led_cdev->dev, &dev_attr_link); - if (rc) - goto err_out_device_name; - rc = device_create_file(led_cdev->dev, &dev_attr_rx); - if (rc) - goto err_out_link; - rc = device_create_file(led_cdev->dev, &dev_attr_tx); - if (rc) - goto err_out_rx; - rc = device_create_file(led_cdev->dev, &dev_attr_interval); - if (rc) - goto err_out_tx; rc = register_netdevice_notifier(&trigger_data->notifier); if (rc) - goto err_out_interval; - return 0; - -err_out_interval: - device_remove_file(led_cdev->dev, &dev_attr_interval); -err_out_tx: - device_remove_file(led_cdev->dev, &dev_attr_tx); -err_out_rx: - device_remove_file(led_cdev->dev, &dev_attr_rx); -err_out_link: - device_remove_file(led_cdev->dev, &dev_attr_link); -err_out_device_name: - device_remove_file(led_cdev->dev, &dev_attr_device_name); -err_out: - led_cdev->trigger_data = NULL; - kfree(trigger_data); + kfree(trigger_data); - return 0; + return rc; } static void netdev_trig_deactivate(struct led_classdev *led_cdev) { - struct led_netdev_data *trigger_data = led_cdev->trigger_data; + struct led_netdev_data *trigger_data = led_get_trigger_data(led_cdev); - if (trigger_data) { - unregister_netdevice_notifier(&trigger_data->notifier); + unregister_netdevice_notifier(&trigger_data->notifier); - device_remove_file(led_cdev->dev, &dev_attr_device_name); - device_remove_file(led_cdev->dev, &dev_attr_link); - device_remove_file(led_cdev->dev, &dev_attr_rx); - device_remove_file(led_cdev->dev, &dev_attr_tx); - device_remove_file(led_cdev->dev, &dev_attr_interval); - - cancel_delayed_work_sync(&trigger_data->work); + cancel_delayed_work_sync(&trigger_data->work); - if (trigger_data->net_dev) - dev_put(trigger_data->net_dev); + if (trigger_data->net_dev) + dev_put(trigger_data->net_dev); - kfree(trigger_data); - } + kfree(trigger_data); } static struct led_trigger netdev_led_trigger = { .name = "netdev", .activate = netdev_trig_activate, .deactivate = netdev_trig_deactivate, + .groups = netdev_trig_groups, }; static int __init netdev_trig_init(void) -- cgit v1.2.3-59-g8ed1b From 2b7b6d44e29160eb12abd950c374babf21ed83d4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:27 +0200 Subject: leds: timer trigger: simplifications from core changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trigger core learned error handling for the activate callback and can handle device attributes now. This allows simplifying the driver considerably. Note that .deactivate() is only called when .activate() succeeded, so the check for .trigger_data being non-NULL can go away. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-timer.c | 53 +++++++++--------------------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c index 527055d815ad..7c14983781ee 100644 --- a/drivers/leds/trigger/ledtrig-timer.c +++ b/drivers/leds/trigger/ledtrig-timer.c @@ -20,7 +20,7 @@ static ssize_t led_delay_on_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_classdev *led_cdev = led_trigger_get_led(dev); return sprintf(buf, "%lu\n", led_cdev->blink_delay_on); } @@ -28,7 +28,7 @@ static ssize_t led_delay_on_show(struct device *dev, static ssize_t led_delay_on_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_classdev *led_cdev = led_trigger_get_led(dev); unsigned long state; ssize_t ret = -EINVAL; @@ -45,7 +45,7 @@ static ssize_t led_delay_on_store(struct device *dev, static ssize_t led_delay_off_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_classdev *led_cdev = led_trigger_get_led(dev); return sprintf(buf, "%lu\n", led_cdev->blink_delay_off); } @@ -53,7 +53,7 @@ static ssize_t led_delay_off_show(struct device *dev, static ssize_t led_delay_off_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_classdev *led_cdev = led_trigger_get_led(dev); unsigned long state; ssize_t ret = -EINVAL; @@ -70,39 +70,23 @@ static ssize_t led_delay_off_store(struct device *dev, static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); +static struct attribute *timer_trig_attrs[] = { + &dev_attr_delay_on.attr, + &dev_attr_delay_off.attr, + NULL +}; +ATTRIBUTE_GROUPS(timer_trig); + static int timer_trig_activate(struct led_classdev *led_cdev) { - int rc; - - led_cdev->trigger_data = NULL; - - rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); - if (rc) - return 0; - rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); - if (rc) - goto err_out_delayon; - led_blink_set(led_cdev, &led_cdev->blink_delay_on, &led_cdev->blink_delay_off); - led_cdev->activated = true; - - return 0; - -err_out_delayon: - device_remove_file(led_cdev->dev, &dev_attr_delay_on); return 0; } static void timer_trig_deactivate(struct led_classdev *led_cdev) { - if (led_cdev->activated) { - device_remove_file(led_cdev->dev, &dev_attr_delay_on); - device_remove_file(led_cdev->dev, &dev_attr_delay_off); - led_cdev->activated = false; - } - /* Stop blinking */ led_set_brightness(led_cdev, LED_OFF); } @@ -111,20 +95,9 @@ static struct led_trigger timer_led_trigger = { .name = "timer", .activate = timer_trig_activate, .deactivate = timer_trig_deactivate, + .groups = timer_trig_groups, }; - -static int __init timer_trig_init(void) -{ - return led_trigger_register(&timer_led_trigger); -} - -static void __exit timer_trig_exit(void) -{ - led_trigger_unregister(&timer_led_trigger); -} - -module_init(timer_trig_init); -module_exit(timer_trig_exit); +module_led_trigger(timer_led_trigger); MODULE_AUTHOR("Richard Purdie "); MODULE_DESCRIPTION("Timer LED trigger"); -- cgit v1.2.3-59-g8ed1b From 823f786ac7615f1bf822227fc4cbeafe11fb6bf8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:28 +0200 Subject: leds: transient trigger: simplifications from core changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trigger core learned error handling for the activate callback and can handle device attributes now. This allows simplifying the driver considerably. Note that .deactivate() is only called when .activate() succeeded, so the check for .activated can go away. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-transient.c | 98 ++++++++++---------------------- 1 file changed, 30 insertions(+), 68 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-transient.c b/drivers/leds/trigger/ledtrig-transient.c index a55fc58179a9..a80bb82aacc2 100644 --- a/drivers/leds/trigger/ledtrig-transient.c +++ b/drivers/leds/trigger/ledtrig-transient.c @@ -42,8 +42,8 @@ static void transient_timer_function(struct timer_list *t) static ssize_t transient_activate_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct transient_trig_data *transient_data = led_cdev->trigger_data; + struct transient_trig_data *transient_data = + led_trigger_get_drvdata(dev); return sprintf(buf, "%d\n", transient_data->activate); } @@ -51,8 +51,9 @@ static ssize_t transient_activate_show(struct device *dev, static ssize_t transient_activate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct transient_trig_data *transient_data = led_cdev->trigger_data; + struct led_classdev *led_cdev = led_trigger_get_led(dev); + struct transient_trig_data *transient_data = + led_trigger_get_drvdata(dev); unsigned long state; ssize_t ret; @@ -94,8 +95,7 @@ static ssize_t transient_activate_store(struct device *dev, static ssize_t transient_duration_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct transient_trig_data *transient_data = led_cdev->trigger_data; + struct transient_trig_data *transient_data = led_trigger_get_drvdata(dev); return sprintf(buf, "%lu\n", transient_data->duration); } @@ -103,8 +103,8 @@ static ssize_t transient_duration_show(struct device *dev, static ssize_t transient_duration_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct transient_trig_data *transient_data = led_cdev->trigger_data; + struct transient_trig_data *transient_data = + led_trigger_get_drvdata(dev); unsigned long state; ssize_t ret; @@ -119,8 +119,8 @@ static ssize_t transient_duration_store(struct device *dev, static ssize_t transient_state_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct transient_trig_data *transient_data = led_cdev->trigger_data; + struct transient_trig_data *transient_data = + led_trigger_get_drvdata(dev); int state; state = (transient_data->state == LED_FULL) ? 1 : 0; @@ -130,8 +130,8 @@ static ssize_t transient_state_show(struct device *dev, static ssize_t transient_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct transient_trig_data *transient_data = led_cdev->trigger_data; + struct transient_trig_data *transient_data = + led_trigger_get_drvdata(dev); unsigned long state; ssize_t ret; @@ -152,84 +152,46 @@ static DEVICE_ATTR(duration, 0644, transient_duration_show, transient_duration_store); static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store); +static struct attribute *transient_trig_attrs[] = { + &dev_attr_activate.attr, + &dev_attr_duration.attr, + &dev_attr_state.attr, + NULL +}; +ATTRIBUTE_GROUPS(transient_trig); + static int transient_trig_activate(struct led_classdev *led_cdev) { - int rc; struct transient_trig_data *tdata; tdata = kzalloc(sizeof(struct transient_trig_data), GFP_KERNEL); - if (!tdata) { - dev_err(led_cdev->dev, - "unable to allocate transient trigger\n"); - return 0; - } - led_cdev->trigger_data = tdata; - tdata->led_cdev = led_cdev; - - rc = device_create_file(led_cdev->dev, &dev_attr_activate); - if (rc) - goto err_out; + if (!tdata) + return -ENOMEM; - rc = device_create_file(led_cdev->dev, &dev_attr_duration); - if (rc) - goto err_out_duration; - - rc = device_create_file(led_cdev->dev, &dev_attr_state); - if (rc) - goto err_out_state; + led_set_trigger_data(led_cdev, tdata); + tdata->led_cdev = led_cdev; timer_setup(&tdata->timer, transient_timer_function, 0); - led_cdev->activated = true; - - return 0; - -err_out_state: - device_remove_file(led_cdev->dev, &dev_attr_duration); -err_out_duration: - device_remove_file(led_cdev->dev, &dev_attr_activate); -err_out: - dev_err(led_cdev->dev, "unable to register transient trigger\n"); - led_cdev->trigger_data = NULL; - kfree(tdata); return 0; } static void transient_trig_deactivate(struct led_classdev *led_cdev) { - struct transient_trig_data *transient_data = led_cdev->trigger_data; + struct transient_trig_data *transient_data = led_get_trigger_data(led_cdev); - if (led_cdev->activated) { - del_timer_sync(&transient_data->timer); - led_set_brightness_nosleep(led_cdev, - transient_data->restore_state); - device_remove_file(led_cdev->dev, &dev_attr_activate); - device_remove_file(led_cdev->dev, &dev_attr_duration); - device_remove_file(led_cdev->dev, &dev_attr_state); - led_cdev->trigger_data = NULL; - led_cdev->activated = false; - kfree(transient_data); - } + del_timer_sync(&transient_data->timer); + led_set_brightness_nosleep(led_cdev, transient_data->restore_state); + kfree(transient_data); } static struct led_trigger transient_trigger = { .name = "transient", .activate = transient_trig_activate, .deactivate = transient_trig_deactivate, + .groups = transient_trig_groups, }; - -static int __init transient_trig_init(void) -{ - return led_trigger_register(&transient_trigger); -} - -static void __exit transient_trig_exit(void) -{ - led_trigger_unregister(&transient_trigger); -} - -module_init(transient_trig_init); -module_exit(transient_trig_exit); +module_led_trigger(transient_trigger); MODULE_AUTHOR("Shuah Khan "); MODULE_DESCRIPTION("Transient LED trigger"); -- cgit v1.2.3-59-g8ed1b From 81d5533297fb672012bb298c1f7545f9c168ccb0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:29 +0200 Subject: leds: oneshot trigger: simplifications from core changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trigger core learned error handling for the activate callback and can handle device attributes now. This allows simplifying the driver considerably. Note that .deactivate() is only called when .activate() succeeded, so the check for .activated can go away in .deactivate(). Also make use of module_led_trigger() and do some minor coding style improvements. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-oneshot.c | 89 ++++++++++------------------------ 1 file changed, 26 insertions(+), 63 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-oneshot.c b/drivers/leds/trigger/ledtrig-oneshot.c index 7bbf92bd7f80..95c9be4b6e7e 100644 --- a/drivers/leds/trigger/ledtrig-oneshot.c +++ b/drivers/leds/trigger/ledtrig-oneshot.c @@ -8,7 +8,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * */ #include @@ -29,8 +28,8 @@ struct oneshot_trig_data { static ssize_t led_shot(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; + struct led_classdev *led_cdev = led_trigger_get_led(dev); + struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev); led_blink_set_oneshot(led_cdev, &led_cdev->blink_delay_on, &led_cdev->blink_delay_off, @@ -42,8 +41,7 @@ static ssize_t led_shot(struct device *dev, static ssize_t led_invert_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; + struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev); return sprintf(buf, "%u\n", oneshot_data->invert); } @@ -51,8 +49,8 @@ static ssize_t led_invert_show(struct device *dev, static ssize_t led_invert_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; + struct led_classdev *led_cdev = led_trigger_get_led(dev); + struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev); unsigned long state; int ret; @@ -73,7 +71,7 @@ static ssize_t led_invert_store(struct device *dev, static ssize_t led_delay_on_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_classdev *led_cdev = led_trigger_get_led(dev); return sprintf(buf, "%lu\n", led_cdev->blink_delay_on); } @@ -81,7 +79,7 @@ static ssize_t led_delay_on_show(struct device *dev, static ssize_t led_delay_on_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_classdev *led_cdev = led_trigger_get_led(dev); unsigned long state; int ret; @@ -93,10 +91,11 @@ static ssize_t led_delay_on_store(struct device *dev, return size; } + static ssize_t led_delay_off_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_classdev *led_cdev = led_trigger_get_led(dev); return sprintf(buf, "%lu\n", led_cdev->blink_delay_off); } @@ -104,7 +103,7 @@ static ssize_t led_delay_off_show(struct device *dev, static ssize_t led_delay_off_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct led_classdev *led_cdev = led_trigger_get_led(dev); unsigned long state; int ret; @@ -122,61 +121,36 @@ static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); static DEVICE_ATTR(shot, 0200, NULL, led_shot); +static struct attribute *oneshot_trig_attrs[] = { + &dev_attr_delay_on.attr, + &dev_attr_delay_off.attr, + &dev_attr_invert.attr, + &dev_attr_shot.attr, + NULL +}; +ATTRIBUTE_GROUPS(oneshot_trig); + static int oneshot_trig_activate(struct led_classdev *led_cdev) { struct oneshot_trig_data *oneshot_data; - int rc; oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL); if (!oneshot_data) - return 0; - - led_cdev->trigger_data = oneshot_data; - - rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); - if (rc) - goto err_out_trig_data; - rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); - if (rc) - goto err_out_delayon; - rc = device_create_file(led_cdev->dev, &dev_attr_invert); - if (rc) - goto err_out_delayoff; - rc = device_create_file(led_cdev->dev, &dev_attr_shot); - if (rc) - goto err_out_invert; + return -ENOMEM; + + led_set_trigger_data(led_cdev, oneshot_data); led_cdev->blink_delay_on = DEFAULT_DELAY; led_cdev->blink_delay_off = DEFAULT_DELAY; - led_cdev->activated = true; - - return 0; - -err_out_invert: - device_remove_file(led_cdev->dev, &dev_attr_invert); -err_out_delayoff: - device_remove_file(led_cdev->dev, &dev_attr_delay_off); -err_out_delayon: - device_remove_file(led_cdev->dev, &dev_attr_delay_on); -err_out_trig_data: - kfree(led_cdev->trigger_data); - return 0; } static void oneshot_trig_deactivate(struct led_classdev *led_cdev) { - struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; + struct oneshot_trig_data *oneshot_data = led_get_trigger_data(led_cdev); - if (led_cdev->activated) { - device_remove_file(led_cdev->dev, &dev_attr_delay_on); - device_remove_file(led_cdev->dev, &dev_attr_delay_off); - device_remove_file(led_cdev->dev, &dev_attr_invert); - device_remove_file(led_cdev->dev, &dev_attr_shot); - kfree(oneshot_data); - led_cdev->activated = false; - } + kfree(oneshot_data); /* Stop blinking */ led_set_brightness(led_cdev, LED_OFF); @@ -186,20 +160,9 @@ static struct led_trigger oneshot_led_trigger = { .name = "oneshot", .activate = oneshot_trig_activate, .deactivate = oneshot_trig_deactivate, + .groups = oneshot_trig_groups, }; - -static int __init oneshot_trig_init(void) -{ - return led_trigger_register(&oneshot_led_trigger); -} - -static void __exit oneshot_trig_exit(void) -{ - led_trigger_unregister(&oneshot_led_trigger); -} - -module_init(oneshot_trig_init); -module_exit(oneshot_trig_exit); +module_led_trigger(oneshot_led_trigger); MODULE_AUTHOR("Fabio Baltieri "); MODULE_DESCRIPTION("One-shot LED trigger"); -- cgit v1.2.3-59-g8ed1b From 71c4af71e597f429d37c89f5db2e44c59c8ba88c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:30 +0200 Subject: leds: heartbeat trigger: simplifications from core changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trigger core learned error handling for the activate callback and can handle device attributes now. This allows simplifying the driver considerably. Note that .deactivate() is only called when .activate() succeeded, so the check for .activated can go away in .deactivate(). Also make use of module_led_trigger() and the accessor function to get and set trigger_data. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-heartbeat.c | 41 +++++++++++++++----------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c index 03a8dfce8fb9..7a2b12e19329 100644 --- a/drivers/leds/trigger/ledtrig-heartbeat.c +++ b/drivers/leds/trigger/ledtrig-heartbeat.c @@ -96,8 +96,8 @@ static void led_heartbeat_function(struct timer_list *t) static ssize_t led_invert_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + struct heartbeat_trig_data *heartbeat_data = + led_trigger_get_drvdata(dev); return sprintf(buf, "%u\n", heartbeat_data->invert); } @@ -105,8 +105,8 @@ static ssize_t led_invert_show(struct device *dev, static ssize_t led_invert_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + struct heartbeat_trig_data *heartbeat_data = + led_trigger_get_drvdata(dev); unsigned long state; int ret; @@ -121,22 +121,22 @@ static ssize_t led_invert_store(struct device *dev, static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); +static struct attribute *heartbeat_trig_attrs[] = { + &dev_attr_invert.attr, + NULL +}; +ATTRIBUTE_GROUPS(heartbeat_trig); + static int heartbeat_trig_activate(struct led_classdev *led_cdev) { struct heartbeat_trig_data *heartbeat_data; - int rc; heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); if (!heartbeat_data) - return 0; + return -ENOMEM; - led_cdev->trigger_data = heartbeat_data; + led_set_trigger_data(led_cdev, heartbeat_data); heartbeat_data->led_cdev = led_cdev; - rc = device_create_file(led_cdev->dev, &dev_attr_invert); - if (rc) { - kfree(led_cdev->trigger_data); - return 0; - } timer_setup(&heartbeat_data->timer, led_heartbeat_function, 0); heartbeat_data->phase = 0; @@ -144,28 +144,25 @@ static int heartbeat_trig_activate(struct led_classdev *led_cdev) led_cdev->blink_brightness = led_cdev->max_brightness; led_heartbeat_function(&heartbeat_data->timer); set_bit(LED_BLINK_SW, &led_cdev->work_flags); - led_cdev->activated = true; return 0; } static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) { - struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; - - if (led_cdev->activated) { - del_timer_sync(&heartbeat_data->timer); - device_remove_file(led_cdev->dev, &dev_attr_invert); - kfree(heartbeat_data); - clear_bit(LED_BLINK_SW, &led_cdev->work_flags); - led_cdev->activated = false; - } + struct heartbeat_trig_data *heartbeat_data = + led_get_trigger_data(led_cdev); + + del_timer_sync(&heartbeat_data->timer); + kfree(heartbeat_data); + clear_bit(LED_BLINK_SW, &led_cdev->work_flags); } static struct led_trigger heartbeat_led_trigger = { .name = "heartbeat", .activate = heartbeat_trig_activate, .deactivate = heartbeat_trig_deactivate, + .groups = heartbeat_trig_groups, }; static int heartbeat_reboot_notifier(struct notifier_block *nb, -- cgit v1.2.3-59-g8ed1b From 5cccc555108b602f92101a939143925095ff9b1d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:31 +0200 Subject: leds: default-on trigger: make use of module_led_trigger() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes some boilerplate from the driver. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-default-on.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-default-on.c b/drivers/leds/trigger/ledtrig-default-on.c index 2996fe672198..7f6d9219711e 100644 --- a/drivers/leds/trigger/ledtrig-default-on.c +++ b/drivers/leds/trigger/ledtrig-default-on.c @@ -26,19 +26,7 @@ static struct led_trigger defon_led_trigger = { .name = "default-on", .activate = defon_trig_activate, }; - -static int __init defon_trig_init(void) -{ - return led_trigger_register(&defon_led_trigger); -} - -static void __exit defon_trig_exit(void) -{ - led_trigger_unregister(&defon_led_trigger); -} - -module_init(defon_trig_init); -module_exit(defon_trig_exit); +module_led_trigger(defon_led_trigger); MODULE_AUTHOR("Nick Forbes "); MODULE_DESCRIPTION("Default-ON LED trigger"); -- cgit v1.2.3-59-g8ed1b From 13d698cbd99ce90f1d6b4fb0ff11ab90eb55f55e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:32 +0200 Subject: leds: activity trigger: simplifications from core changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trigger core learned error handling for the activate callback and can handle device attributes now. This allows simplifying the driver considerably. Note that .deactivate() is only called when .activate() succeeded, so the check for .activated can go away in .deactivate(). Also make use of module_led_trigger() and the accessor function to get and set trigger_data. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-activity.c | 38 ++++++++++++++------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-activity.c b/drivers/leds/trigger/ledtrig-activity.c index 2fc065fb1754..bcbf41c90c30 100644 --- a/drivers/leds/trigger/ledtrig-activity.c +++ b/drivers/leds/trigger/ledtrig-activity.c @@ -152,8 +152,7 @@ static void led_activity_function(struct timer_list *t) static ssize_t led_invert_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct activity_data *activity_data = led_cdev->trigger_data; + struct activity_data *activity_data = led_trigger_get_drvdata(dev); return sprintf(buf, "%u\n", activity_data->invert); } @@ -162,8 +161,7 @@ static ssize_t led_invert_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct activity_data *activity_data = led_cdev->trigger_data; + struct activity_data *activity_data = led_trigger_get_drvdata(dev); unsigned long state; int ret; @@ -178,21 +176,21 @@ static ssize_t led_invert_store(struct device *dev, static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); +static struct attribute *activity_led_attrs[] = { + &dev_attr_invert.attr, + NULL +}; +ATTRIBUTE_GROUPS(activity_led); + static int activity_activate(struct led_classdev *led_cdev) { struct activity_data *activity_data; - int rc; activity_data = kzalloc(sizeof(*activity_data), GFP_KERNEL); if (!activity_data) - return 0; + return -ENOMEM; - led_cdev->trigger_data = activity_data; - rc = device_create_file(led_cdev->dev, &dev_attr_invert); - if (rc) { - kfree(led_cdev->trigger_data); - return 0; - } + led_set_trigger_data(led_cdev, activity_data); activity_data->led_cdev = led_cdev; timer_setup(&activity_data->timer, led_activity_function, 0); @@ -200,28 +198,24 @@ static int activity_activate(struct led_classdev *led_cdev) led_cdev->blink_brightness = led_cdev->max_brightness; led_activity_function(&activity_data->timer); set_bit(LED_BLINK_SW, &led_cdev->work_flags); - led_cdev->activated = true; return 0; } static void activity_deactivate(struct led_classdev *led_cdev) { - struct activity_data *activity_data = led_cdev->trigger_data; - - if (led_cdev->activated) { - del_timer_sync(&activity_data->timer); - device_remove_file(led_cdev->dev, &dev_attr_invert); - kfree(activity_data); - clear_bit(LED_BLINK_SW, &led_cdev->work_flags); - led_cdev->activated = false; - } + struct activity_data *activity_data = led_get_trigger_data(led_cdev); + + del_timer_sync(&activity_data->timer); + kfree(activity_data); + clear_bit(LED_BLINK_SW, &led_cdev->work_flags); } static struct led_trigger activity_led_trigger = { .name = "activity", .activate = activity_activate, .deactivate = activity_deactivate, + .groups = activity_led_groups, }; static int activity_reboot_notifier(struct notifier_block *nb, -- cgit v1.2.3-59-g8ed1b From e4786ba0db7b1163403c29c429f5ef61906a84c0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:33 +0200 Subject: leds: backlight trigger: simplifications from core changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new module_led_trigger() helper. Also use attribute support from the trigger core. Drop error message on allocation failure as kzalloc() already screams loudly when failing. Use wrappers to get and set trigger data. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-backlight.c | 62 ++++++++++---------------------- 1 file changed, 19 insertions(+), 43 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-backlight.c b/drivers/leds/trigger/ledtrig-backlight.c index 84512960d630..c2b57beef718 100644 --- a/drivers/leds/trigger/ledtrig-backlight.c +++ b/drivers/leds/trigger/ledtrig-backlight.c @@ -64,8 +64,7 @@ static int fb_notifier_callback(struct notifier_block *p, static ssize_t bl_trig_invert_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led = dev_get_drvdata(dev); - struct bl_trig_notifier *n = led->trigger_data; + struct bl_trig_notifier *n = led_trigger_get_drvdata(dev); return sprintf(buf, "%u\n", n->invert); } @@ -73,8 +72,8 @@ static ssize_t bl_trig_invert_show(struct device *dev, static ssize_t bl_trig_invert_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t num) { - struct led_classdev *led = dev_get_drvdata(dev); - struct bl_trig_notifier *n = led->trigger_data; + struct led_classdev *led = led_trigger_get_led(dev); + struct bl_trig_notifier *n = led_trigger_get_drvdata(dev); unsigned long invert; int ret; @@ -97,6 +96,12 @@ static ssize_t bl_trig_invert_store(struct device *dev, } static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store); +static struct attribute *bl_trig_attrs[] = { + &dev_attr_inverted.attr, + NULL, +}; +ATTRIBUTE_GROUPS(bl_trig); + static int bl_trig_activate(struct led_classdev *led) { int ret; @@ -104,15 +109,9 @@ static int bl_trig_activate(struct led_classdev *led) struct bl_trig_notifier *n; n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL); - led->trigger_data = n; - if (!n) { - dev_err(led->dev, "unable to allocate backlight trigger\n"); - return 0; - } - - ret = device_create_file(led->dev, &dev_attr_inverted); - if (ret) - goto err_invert; + if (!n) + return -ENOMEM; + led_set_trigger_data(led, n); n->led = led; n->brightness = led->brightness; @@ -122,48 +121,25 @@ static int bl_trig_activate(struct led_classdev *led) ret = fb_register_client(&n->notifier); if (ret) dev_err(led->dev, "unable to register backlight trigger\n"); - led->activated = true; - - return 0; - -err_invert: - led->trigger_data = NULL; - kfree(n); return 0; } static void bl_trig_deactivate(struct led_classdev *led) { - struct bl_trig_notifier *n = - (struct bl_trig_notifier *) led->trigger_data; - - if (led->activated) { - device_remove_file(led->dev, &dev_attr_inverted); - fb_unregister_client(&n->notifier); - kfree(n); - led->activated = false; - } + struct bl_trig_notifier *n = led_get_trigger_data(led); + + fb_unregister_client(&n->notifier); + kfree(n); } static struct led_trigger bl_led_trigger = { .name = "backlight", .activate = bl_trig_activate, - .deactivate = bl_trig_deactivate + .deactivate = bl_trig_deactivate, + .groups = bl_trig_groups, }; - -static int __init bl_trig_init(void) -{ - return led_trigger_register(&bl_led_trigger); -} - -static void __exit bl_trig_exit(void) -{ - led_trigger_unregister(&bl_led_trigger); -} - -module_init(bl_trig_init); -module_exit(bl_trig_exit); +module_led_trigger(bl_led_trigger); MODULE_AUTHOR("Rodolfo Giometti "); MODULE_DESCRIPTION("Backlight emulation LED trigger"); -- cgit v1.2.3-59-g8ed1b From 9bfd7d9e5d63532da2d2d55a6bec5bb377761d37 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:34 +0200 Subject: leds: gpio trigger: simplifications from core changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The trigger core learned error handling for the activate callback and to handle device attributes. Also make use of the module_led_trigger() helper to simplify trigger registration. Signed-off-by: Uwe Kleine-König Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-gpio.c | 87 +++++++++++-------------------------- 1 file changed, 25 insertions(+), 62 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c index f5358c40d03f..ed0db8ed825f 100644 --- a/drivers/leds/trigger/ledtrig-gpio.c +++ b/drivers/leds/trigger/ledtrig-gpio.c @@ -28,7 +28,7 @@ struct gpio_trig_data { static irqreturn_t gpio_trig_irq(int irq, void *_led) { struct led_classdev *led = _led; - struct gpio_trig_data *gpio_data = led->trigger_data; + struct gpio_trig_data *gpio_data = led_get_trigger_data(led); int tmp; tmp = gpio_get_value_cansleep(gpio_data->gpio); @@ -51,8 +51,7 @@ static irqreturn_t gpio_trig_irq(int irq, void *_led) static ssize_t gpio_trig_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led = dev_get_drvdata(dev); - struct gpio_trig_data *gpio_data = led->trigger_data; + struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev); return sprintf(buf, "%u\n", gpio_data->desired_brightness); } @@ -60,8 +59,7 @@ static ssize_t gpio_trig_brightness_show(struct device *dev, static ssize_t gpio_trig_brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { - struct led_classdev *led = dev_get_drvdata(dev); - struct gpio_trig_data *gpio_data = led->trigger_data; + struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev); unsigned desired_brightness; int ret; @@ -81,8 +79,7 @@ static DEVICE_ATTR(desired_brightness, 0644, gpio_trig_brightness_show, static ssize_t gpio_trig_inverted_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led = dev_get_drvdata(dev); - struct gpio_trig_data *gpio_data = led->trigger_data; + struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev); return sprintf(buf, "%u\n", gpio_data->inverted); } @@ -90,8 +87,8 @@ static ssize_t gpio_trig_inverted_show(struct device *dev, static ssize_t gpio_trig_inverted_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { - struct led_classdev *led = dev_get_drvdata(dev); - struct gpio_trig_data *gpio_data = led->trigger_data; + struct led_classdev *led = led_trigger_get_led(dev); + struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev); unsigned long inverted; int ret; @@ -115,8 +112,7 @@ static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show, static ssize_t gpio_trig_gpio_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led = dev_get_drvdata(dev); - struct gpio_trig_data *gpio_data = led->trigger_data; + struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev); return sprintf(buf, "%u\n", gpio_data->gpio); } @@ -124,8 +120,8 @@ static ssize_t gpio_trig_gpio_show(struct device *dev, static ssize_t gpio_trig_gpio_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { - struct led_classdev *led = dev_get_drvdata(dev); - struct gpio_trig_data *gpio_data = led->trigger_data; + struct led_classdev *led = led_trigger_get_led(dev); + struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev); unsigned gpio; int ret; @@ -162,77 +158,44 @@ static ssize_t gpio_trig_gpio_store(struct device *dev, } static DEVICE_ATTR(gpio, 0644, gpio_trig_gpio_show, gpio_trig_gpio_store); +static struct attribute *gpio_trig_attrs[] = { + &dev_attr_desired_brightness.attr, + &dev_attr_inverted.attr, + &dev_attr_gpio.attr, + NULL +}; +ATTRIBUTE_GROUPS(gpio_trig); + static int gpio_trig_activate(struct led_classdev *led) { struct gpio_trig_data *gpio_data; - int ret; gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL); if (!gpio_data) - return 0; - - ret = device_create_file(led->dev, &dev_attr_gpio); - if (ret) - goto err_gpio; - - ret = device_create_file(led->dev, &dev_attr_inverted); - if (ret) - goto err_inverted; - - ret = device_create_file(led->dev, &dev_attr_desired_brightness); - if (ret) - goto err_brightness; + return -ENOMEM; gpio_data->led = led; - led->trigger_data = gpio_data; - led->activated = true; - - return 0; - -err_brightness: - device_remove_file(led->dev, &dev_attr_inverted); - -err_inverted: - device_remove_file(led->dev, &dev_attr_gpio); - -err_gpio: - kfree(gpio_data); + led_set_trigger_data(led, gpio_data); return 0; } static void gpio_trig_deactivate(struct led_classdev *led) { - struct gpio_trig_data *gpio_data = led->trigger_data; + struct gpio_trig_data *gpio_data = led_get_trigger_data(led); - if (led->activated) { - device_remove_file(led->dev, &dev_attr_gpio); - device_remove_file(led->dev, &dev_attr_inverted); - device_remove_file(led->dev, &dev_attr_desired_brightness); - if (gpio_data->gpio != 0) - free_irq(gpio_to_irq(gpio_data->gpio), led); - kfree(gpio_data); - led->activated = false; - } + if (gpio_data->gpio != 0) + free_irq(gpio_to_irq(gpio_data->gpio), led); + kfree(gpio_data); } static struct led_trigger gpio_led_trigger = { .name = "gpio", .activate = gpio_trig_activate, .deactivate = gpio_trig_deactivate, + .groups = gpio_trig_groups, }; - -static int __init gpio_trig_init(void) -{ - return led_trigger_register(&gpio_led_trigger); -} -module_init(gpio_trig_init); - -static void __exit gpio_trig_exit(void) -{ - led_trigger_unregister(&gpio_led_trigger); -} -module_exit(gpio_trig_exit); +module_led_trigger(gpio_led_trigger); MODULE_AUTHOR("Felipe Balbi "); MODULE_DESCRIPTION("GPIO LED trigger"); -- cgit v1.2.3-59-g8ed1b From 6f7b0bad88397ad5d7901ce63696163ac8b481ce Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 2 Jul 2018 22:05:35 +0200 Subject: usb: simplify usbport trigger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The led trigger core learned a few things that allow to simplify the trigger drivers. Make use of automated trigger attributes and error checking of the activate callback. Also use the wrappers to set and get trigger_data. Acked-by: Pavel Machek Acked-by: Greg Kroah-Hartman Signed-off-by: Uwe Kleine-König Signed-off-by: Jacek Anaszewski --- drivers/usb/core/ledtrig-usbport.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c index aa1d51458da7..dc7f7fd71684 100644 --- a/drivers/usb/core/ledtrig-usbport.c +++ b/drivers/usb/core/ledtrig-usbport.c @@ -113,11 +113,17 @@ static ssize_t usbport_trig_port_store(struct device *dev, static struct attribute *ports_attrs[] = { NULL, }; + static const struct attribute_group ports_group = { .name = "ports", .attrs = ports_attrs, }; +static const struct attribute_group *ports_groups[] = { + &ports_group, + NULL +}; + /*************************************** * Adding & removing ports ***************************************/ @@ -301,59 +307,44 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action, static int usbport_trig_activate(struct led_classdev *led_cdev) { struct usbport_trig_data *usbport_data; - int err; usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL); if (!usbport_data) - return 0; + return -ENOMEM; usbport_data->led_cdev = led_cdev; /* List of ports */ INIT_LIST_HEAD(&usbport_data->ports); - err = sysfs_create_group(&led_cdev->dev->kobj, &ports_group); - if (err) - goto err_free; usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports); usbport_trig_update_count(usbport_data); /* Notifications */ - usbport_data->nb.notifier_call = usbport_trig_notify, - led_cdev->trigger_data = usbport_data; + usbport_data->nb.notifier_call = usbport_trig_notify; + led_set_trigger_data(led_cdev, usbport_data); usb_register_notify(&usbport_data->nb); - led_cdev->activated = true; - return 0; - -err_free: - kfree(usbport_data); return 0; } static void usbport_trig_deactivate(struct led_classdev *led_cdev) { - struct usbport_trig_data *usbport_data = led_cdev->trigger_data; + struct usbport_trig_data *usbport_data = led_get_trigger_data(led_cdev); struct usbport_trig_port *port, *tmp; - if (!led_cdev->activated) - return; - list_for_each_entry_safe(port, tmp, &usbport_data->ports, list) { usbport_trig_remove_port(usbport_data, port); } usb_unregister_notify(&usbport_data->nb); - sysfs_remove_group(&led_cdev->dev->kobj, &ports_group); - kfree(usbport_data); - - led_cdev->activated = false; } static struct led_trigger usbport_led_trigger = { .name = "usbport", .activate = usbport_trig_activate, .deactivate = usbport_trig_deactivate, + .groups = ports_groups, }; static int __init usbport_trig_init(void) -- cgit v1.2.3-59-g8ed1b From 2224f2ff9670b899983ff1b42d85530e889cfea1 Mon Sep 17 00:00:00 2001 From: Kitone Elvis Peter Date: Mon, 6 Aug 2018 20:27:59 +0300 Subject: leds: ns2: Change unsigned to unsigned int Use unsigned int, because it's preferred to unsigned. Signed-off-by: Kitone Elvis Peter Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-ns2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 14fe5cd43232..a0a7dc2ef87c 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -42,8 +42,8 @@ struct ns2_led_data { struct led_classdev cdev; - unsigned cmd; - unsigned slow; + unsigned int cmd; + unsigned int slow; bool can_sleep; unsigned char sata; /* True when SATA mode active. */ rwlock_t rw_lock; /* Lock GPIOs. */ -- cgit v1.2.3-59-g8ed1b