Commit c07b3682 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'leds-for-4.19-rc1' of...

Merge tag 'leds-for-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds

Pull LED updates from Jacek Anaszewski:
 "LED triggers improvements make the biggest part of this pull request.
  The most striking ones, that allowed for nice cleanups in the triggers
  are:

   - centralized handling of creation and removal of trigger sysfs
     attributes via attribute group

   - addition of module_led_trigger() helper

  The other things that need to be mentioned:

  New features and improvements to existing LED class drivers:

   - lt3593: add DT support, switch to gpiod interface

   - lm3692x: support LED sync configuration, change OF calls to fwnode
     calls

   - apu: modify PC Engines apu/apu2 driver to support apu3

  Change in the drivers/net/can/led.c:

   - mark led trigger as broken since it's in the way for the further
     cleanups. It implements a subset of the netdev trigger and an Ack
     is needed from someone who can actually test and confirm that the
     netdev trigger works for can devices"

* tag 'leds-for-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds: (32 commits)
  leds: ns2: Change unsigned to unsigned int
  usb: simplify usbport trigger
  leds: gpio trigger: simplifications from core changes
  leds: backlight trigger: simplifications from core changes
  leds: activity trigger: simplifications from core changes
  leds: default-on trigger: make use of module_led_trigger()
  leds: heartbeat trigger: simplifications from core changes
  leds: oneshot trigger: simplifications from core changes
  leds: transient trigger: simplifications from core changes
  leds: timer trigger: simplifications from core changes
  leds: netdev trigger: simplifications from core changes
  leds: triggers: new function led_set_trigger_data()
  leds: triggers: define module_led_trigger helper
  leds: triggers: handle .trigger_data and .activated() in the core
  leds: triggers: add device attribute support
  leds: triggers: let struct led_trigger::activate() return an error code
  leds: triggers: make the MODULE_LICENSE string match the actual license
  leds: lm3692x: Support LED sync configuration
  dt: bindings: lm3692x: Update binding for LED sync control
  leds: lm3692x: Change DT calls to fwnode calls
  ...
parents 4d88e3d2 2224f2ff
...@@ -31,7 +31,7 @@ Optional properties for child nodes: ...@@ -31,7 +31,7 @@ Optional properties for child nodes:
"backlight" - LED will act as a back-light, controlled by the framebuffer "backlight" - LED will act as a back-light, controlled by the framebuffer
system system
"default-on" - LED will turn on (but for leds-gpio see "default-state" "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 "heartbeat" - LED "double" flashes at a load average based rate
"disk-activity" - LED indicates disk activity "disk-activity" - LED indicates disk activity
"ide-disk" - LED indicates IDE disk activity (deprecated), "ide-disk" - LED indicates IDE disk activity (deprecated),
......
...@@ -20,7 +20,10 @@ Optional properties: ...@@ -20,7 +20,10 @@ Optional properties:
- vled-supply : LED supply - vled-supply : LED supply
Required child properties: 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: Optional child properties:
- label : see Documentation/devicetree/bindings/leds/common.txt - label : see Documentation/devicetree/bindings/leds/common.txt
......
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";
};
};
...@@ -57,12 +57,13 @@ config LEDS_AAT1290 ...@@ -57,12 +57,13 @@ config LEDS_AAT1290
depends on PINCTRL depends on PINCTRL
help help
This option enables support for the LEDs on the AAT1290. This option enables support for the LEDs on the AAT1290.
config LEDS_APU 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 LEDS_CLASS
depends on X86 && DMI depends on X86 && DMI
help 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. accessible from userspace programs through the LED subsystem.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
......
...@@ -103,15 +103,16 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, ...@@ -103,15 +103,16 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
EXPORT_SYMBOL_GPL(led_trigger_show); EXPORT_SYMBOL_GPL(led_trigger_show);
/* Caller must ensure led_cdev->trigger_lock held */ /* 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; unsigned long flags;
char *event = NULL; char *event = NULL;
char *envp[2]; char *envp[2];
const char *name; const char *name;
int ret;
if (!led_cdev->trigger && !trig) if (!led_cdev->trigger && !trig)
return; return 0;
name = trig ? trig->name : "none"; name = trig ? trig->name : "none";
event = kasprintf(GFP_KERNEL, "TRIGGER=%s", name); event = kasprintf(GFP_KERNEL, "TRIGGER=%s", name);
...@@ -126,7 +127,10 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) ...@@ -126,7 +127,10 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
led_stop_software_blink(led_cdev); led_stop_software_blink(led_cdev);
if (led_cdev->trigger->deactivate) if (led_cdev->trigger->deactivate)
led_cdev->trigger->deactivate(led_cdev); led_cdev->trigger->deactivate(led_cdev);
device_remove_groups(led_cdev->dev, led_cdev->trigger->groups);
led_cdev->trigger = NULL; led_cdev->trigger = NULL;
led_cdev->trigger_data = NULL;
led_cdev->activated = false;
led_set_brightness(led_cdev, LED_OFF); led_set_brightness(led_cdev, LED_OFF);
} }
if (trig) { if (trig) {
...@@ -134,8 +138,20 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) ...@@ -134,8 +138,20 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
list_add_tail(&led_cdev->trig_list, &trig->led_cdevs); list_add_tail(&led_cdev->trig_list, &trig->led_cdevs);
write_unlock_irqrestore(&trig->leddev_list_lock, flags); write_unlock_irqrestore(&trig->leddev_list_lock, flags);
led_cdev->trigger = trig; led_cdev->trigger = trig;
if (trig->activate) if (trig->activate)
trig->activate(led_cdev); ret = trig->activate(led_cdev);
else
ret = 0;
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) { if (event) {
...@@ -146,6 +162,23 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) ...@@ -146,6 +162,23 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
"%s: Error sending uevent\n", __func__); "%s: Error sending uevent\n", __func__);
kfree(event); kfree(event);
} }
return 0;
err_add_groups:
if (trig->deactivate)
trig->deactivate(led_cdev);
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);
led_set_brightness(led_cdev, LED_OFF);
return ret;
} }
EXPORT_SYMBOL_GPL(led_trigger_set); EXPORT_SYMBOL_GPL(led_trigger_set);
......
...@@ -102,6 +102,13 @@ static const struct apu_led_profile apu2_led_profile[] = { ...@@ -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 }, { "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 = { static const struct dmi_system_id apu_led_dmi_table[] __initconst = {
{ {
.ident = "apu", .ident = "apu",
...@@ -134,6 +141,30 @@ static const struct dmi_system_id apu_led_dmi_table[] __initconst = { ...@@ -134,6 +141,30 @@ static const struct dmi_system_id apu_led_dmi_table[] __initconst = {
DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu2") 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); MODULE_DEVICE_TABLE(dmi, apu_led_dmi_table);
...@@ -235,6 +266,14 @@ static int __init apu_led_probe(struct platform_device *pdev) ...@@ -235,6 +266,14 @@ static int __init apu_led_probe(struct platform_device *pdev)
apu_led->platform = APU2_LED_PLATFORM; apu_led->platform = APU2_LED_PLATFORM;
apu_led->num_led_instances = ARRAY_SIZE(apu2_led_profile); apu_led->num_led_instances = ARRAY_SIZE(apu2_led_profile);
apu_led->iosize = APU2_IOSIZE; 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); spin_lock_init(&apu_led->lock);
...@@ -259,7 +298,10 @@ static int __init apu_led_init(void) ...@@ -259,7 +298,10 @@ static int __init apu_led_init(void)
if (!(dmi_match(DMI_PRODUCT_NAME, "APU") || if (!(dmi_match(DMI_PRODUCT_NAME, "APU") ||
dmi_match(DMI_PRODUCT_NAME, "APU2") || dmi_match(DMI_PRODUCT_NAME, "APU2") ||
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", pr_err("Unknown PC Engines board: %s\n",
dmi_get_system_info(DMI_PRODUCT_NAME)); dmi_get_system_info(DMI_PRODUCT_NAME));
return -ENODEV; return -ENODEV;
......
/* // SPDX-License-Identifier: GPL-2.0
* TI lm3692x LED Driver // TI LM3692x LED chip family driver
* // Copyright (C) 2017-18 Texas Instruments Incorporated - http://www.ti.com/
* Copyright (C) 2017 Texas Instruments
*
* Author: Dan Murphy <dmurphy@ti.com>
*
* 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
*/
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -26,6 +15,9 @@ ...@@ -26,6 +15,9 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <uapi/linux/uleds.h> #include <uapi/linux/uleds.h>
#define LM36922_MODEL 0
#define LM36923_MODEL 1
#define LM3692X_REV 0x0 #define LM3692X_REV 0x0
#define LM3692X_RESET 0x1 #define LM3692X_RESET 0x1
#define LM3692X_EN 0x10 #define LM3692X_EN 0x10
...@@ -44,6 +36,9 @@ ...@@ -44,6 +36,9 @@
#define LM3692X_DEVICE_EN BIT(0) #define LM3692X_DEVICE_EN BIT(0)
#define LM3692X_LED1_EN BIT(1) #define LM3692X_LED1_EN BIT(1)
#define LM3692X_LED2_EN BIT(2) #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 */ /* Brightness Control Bits */
#define LM3692X_BL_ADJ_POL BIT(0) #define LM3692X_BL_ADJ_POL BIT(0)
...@@ -109,6 +104,8 @@ ...@@ -109,6 +104,8 @@
* @enable_gpio - VDDIO/EN gpio to enable communication interface * @enable_gpio - VDDIO/EN gpio to enable communication interface
* @regulator - LED supply regulator pointer * @regulator - LED supply regulator pointer
* @label - LED label * @label - LED label
* @led_enable - LED sync to be enabled
* @model_id - Current device model ID enumerated
*/ */
struct lm3692x_led { struct lm3692x_led {
struct mutex lock; struct mutex lock;
...@@ -118,6 +115,8 @@ struct lm3692x_led { ...@@ -118,6 +115,8 @@ struct lm3692x_led {
struct gpio_desc *enable_gpio; struct gpio_desc *enable_gpio;
struct regulator *regulator; struct regulator *regulator;
char label[LED_MAX_NAME_SIZE]; char label[LED_MAX_NAME_SIZE];
int led_enable;
int model_id;
}; };
static const struct reg_default lm3692x_reg_defs[] = { static const struct reg_default lm3692x_reg_defs[] = {
...@@ -200,6 +199,7 @@ static int lm3692x_brightness_set(struct led_classdev *led_cdev, ...@@ -200,6 +199,7 @@ static int lm3692x_brightness_set(struct led_classdev *led_cdev,
static int lm3692x_init(struct lm3692x_led *led) static int lm3692x_init(struct lm3692x_led *led)
{ {
int enable_state;
int ret; int ret;
if (led->regulator) { if (led->regulator) {
...@@ -226,9 +226,25 @@ static int lm3692x_init(struct lm3692x_led *led) ...@@ -226,9 +226,25 @@ static int lm3692x_init(struct lm3692x_led *led)
/* /*
* For glitch free operation, the following data should * 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 * 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, ret = regmap_write(led->regmap, LM3692X_PWM_CTRL,
LM3692X_PWM_FILTER_100 | LM3692X_PWM_SAMP_24MHZ); LM3692X_PWM_FILTER_100 | LM3692X_PWM_SAMP_24MHZ);
if (ret) if (ret)
...@@ -258,6 +274,38 @@ static int lm3692x_init(struct lm3692x_led *led) ...@@ -258,6 +274,38 @@ static int lm3692x_init(struct lm3692x_led *led)
if (ret) if (ret)
goto out; 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; return ret;
out: out:
dev_err(&led->client->dev, "Fail writing initialization values\n"); dev_err(&led->client->dev, "Fail writing initialization values\n");
...@@ -274,52 +322,75 @@ static int lm3692x_init(struct lm3692x_led *led) ...@@ -274,52 +322,75 @@ static int lm3692x_init(struct lm3692x_led *led)
return ret; return ret;
} }
static int lm3692x_probe_dt(struct lm3692x_led *led)
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; const char *name;
int ret;
led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); led->enable_gpio = devm_gpiod_get_optional(&led->client->dev,
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); "enable", GPIOD_OUT_LOW);
if (IS_ERR(led->enable_gpio)) { if (IS_ERR(led->enable_gpio)) {
ret = PTR_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; return ret;
} }
led->regulator = devm_regulator_get(&client->dev, "vled"); led->regulator = devm_regulator_get(&led->client->dev, "vled");
if (IS_ERR(led->regulator)) if (IS_ERR(led->regulator))
led->regulator = NULL; led->regulator = NULL;
led->client = client; child = device_get_next_child_node(&led->client->dev, child);
if (!child) {
dev_err(&led->client->dev, "No LED Child node\n");
return -ENODEV;
}
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);
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; led->led_dev.name = led->label;
led->led_dev.brightness_set_blocking = lm3692x_brightness_set;
mutex_init(&led->lock); ret = devm_led_classdev_register(&led->client->dev, &led->led_dev);
if (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); i2c_set_clientdata(client, led);
led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config); led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config);
...@@ -330,15 +401,13 @@ static int lm3692x_probe(struct i2c_client *client, ...@@ -330,15 +401,13 @@ static int lm3692x_probe(struct i2c_client *client,
return ret; return ret;
} }
ret = lm3692x_init(led); ret = lm3692x_probe_dt(led);
if (ret) if (ret)
return ret; return ret;
ret = devm_led_classdev_register(&client->dev, &led->led_dev); ret = lm3692x_init(led);
if (ret) { if (ret)
dev_err(&client->dev, "led register err: %d\n", ret);
return ret; return ret;
}
return 0; return 0;
} }
...@@ -348,6 +417,12 @@ static int lm3692x_remove(struct i2c_client *client) ...@@ -348,6 +417,12 @@ static int lm3692x_remove(struct i2c_client *client)
struct lm3692x_led *led = i2c_get_clientdata(client); struct lm3692x_led *led = i2c_get_clientdata(client);
int ret; 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) if (led->enable_gpio)
gpiod_direction_output(led->enable_gpio, 0); gpiod_direction_output(led->enable_gpio, 0);
...@@ -364,8 +439,8 @@ static int lm3692x_remove(struct i2c_client *client) ...@@ -364,8 +439,8 @@ static int lm3692x_remove(struct i2c_client *client)
} }
static const struct i2c_device_id lm3692x_id[] = { static const struct i2c_device_id lm3692x_id[] = {
{ "lm36922", 0 }, { "lm36922", LM36922_MODEL },
{ "lm36923", 1 }, { "lm36923", LM36923_MODEL },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, lm3692x_id); MODULE_DEVICE_TABLE(i2c, lm3692x_id);
......
/* // SPDX-License-Identifier: GPL-2.0
* LEDs driver for LT3593 controllers // Copyright (c) 2009,2018 Daniel Mack <daniel@zonque.org>
*
* See the datasheet at http://cds.linear.com/docs/Datasheet/3593f.pdf
*
* Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
*
* Based on leds-gpio.c,
*
* Copyright (C) 2007 8D Technologies inc.
* Raphael Assenat <raph@8d.com>
* 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.
*/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <uapi/linux/uleds.h>
struct lt3593_led_data { struct lt3593_led_data {
char name[LED_MAX_NAME_SIZE];
struct led_classdev cdev; struct led_classdev cdev;
unsigned gpio; struct gpio_desc *gpiod;
}; };
static int lt3593_led_set(struct led_classdev *led_cdev, static int lt3593_led_set(struct led_classdev *led_cdev,
...@@ -46,137 +35,168 @@ static int lt3593_led_set(struct led_classdev *led_cdev, ...@@ -46,137 +35,168 @@ static int lt3593_led_set(struct led_classdev *led_cdev,
*/ */
if (value == 0) { if (value == 0) {
gpio_set_value_cansleep(led_dat->gpio, 0); gpiod_set_value_cansleep(led_dat->gpiod, 0);
return 0; return 0;
} }
pulses = 32 - (value * 32) / 255; pulses = 32 - (value * 32) / 255;
if (pulses == 0) { if (pulses == 0) {
gpio_set_value_cansleep(led_dat->gpio, 0); gpiod_set_value_cansleep(led_dat->gpiod, 0);
mdelay(1); mdelay(1);
gpio_set_value_cansleep(led_dat->gpio, 1); gpiod_set_value_cansleep(led_dat->gpiod, 1);
return 0; return 0;
} }
gpio_set_value_cansleep(led_dat->gpio, 1); gpiod_set_value_cansleep(led_dat->gpiod, 1);
while (pulses--) { while (pulses--) {
gpio_set_value_cansleep(led_dat->gpio, 0); gpiod_set_value_cansleep(led_dat->gpiod, 0);
udelay(1); udelay(1);
gpio_set_value_cansleep(led_dat->gpio, 1); gpiod_set_value_cansleep(led_dat->gpiod, 1);
udelay(1); udelay(1);
} }
return 0; return 0;
} }
static int create_lt3593_led(const struct gpio_led *template, static struct lt3593_led_data *lt3593_led_probe_pdata(struct device *dev)
struct lt3593_led_data *led_dat, struct device *parent)
{ {
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; int ret, state;
/* skip leds on GPIOs that aren't available */ if (pdata->num_leds != 1)
if (!gpio_is_valid(template->gpio)) { return ERR_PTR(-EINVAL);
dev_info(parent, "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n",
KBUILD_MODNAME, template->gpio, template->name);
return 0;
}
led_dat->cdev.name = template->name; led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL);
led_dat->cdev.default_trigger = template->default_trigger; if (!led_data)
led_dat->gpio = template->gpio; return ERR_PTR(-ENOMEM);
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->cdev.brightness_set_blocking = lt3593_led_set;
state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); 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) 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, GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
template->name); template->name);
if (ret < 0) if (ret < 0)
return ret; return ERR_PTR(ret);
ret = led_classdev_register(parent, &led_dat->cdev);
if (ret < 0)
return ret;
dev_info(parent, "%s: registered LT3593 LED '%s' at GPIO %d\n", led_data->gpiod = gpio_to_desc(template->gpio);
KBUILD_MODNAME, template->name, template->gpio); if (!led_data->gpiod)
return ERR_PTR(-EPROBE_DEFER);
return 0; ret = devm_led_classdev_register(dev, &led_data->cdev);
} if (ret < 0)
return ERR_PTR(ret);
static void delete_lt3593_led(struct lt3593_led_data *led) dev_info(dev, "registered LT3593 LED '%s' at GPIO %d\n",
{ template->name, template->gpio);
if (!gpio_is_valid(led->gpio))
return;
led_classdev_unregister(&led->cdev); return led_data;
} }
static int lt3593_led_probe(struct platform_device *pdev) static int lt3593_led_probe(struct platform_device *pdev)
{ {
struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev;
struct lt3593_led_data *leds_data; struct lt3593_led_data *led_data;
int i, ret = 0; 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 (!pdata) if (!dev->of_node)
return -EBUSY; return -ENODEV;
leds_data = devm_kcalloc(&pdev->dev, led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL);
pdata->num_leds, sizeof(struct lt3593_led_data), if (!led_data)
GFP_KERNEL);
if (!leds_data)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < pdata->num_leds; i++) { if (device_get_child_node_count(dev) != 1) {
ret = create_lt3593_led(&pdata->leds[i], &leds_data[i], dev_err(dev, "Device must have exactly one LED sub-node.");
&pdev->dev); return -EINVAL;
if (ret < 0)
goto err;
} }
platform_set_drvdata(pdev, leds_data); led_data->gpiod = devm_gpiod_get(dev, "lltc,ctrl", 0);
if (IS_ERR(led_data->gpiod))
return PTR_ERR(led_data->gpiod);
return 0; child = device_get_next_child_node(dev, NULL);
err: ret = fwnode_property_read_string(child, "label", &tmp);
for (i = i - 1; i >= 0; i--) if (ret < 0)
delete_lt3593_led(&leds_data[i]); 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;
}
}
return ret; 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;
static int lt3593_led_remove(struct platform_device *pdev) ret = devm_led_classdev_register(dev, &led_data->cdev);
{ if (ret < 0) {
int i; fwnode_handle_put(child);
struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); return ret;
struct lt3593_led_data *leds_data; }
leds_data = platform_get_drvdata(pdev); led_data->cdev.dev->of_node = dev->of_node;
for (i = 0; i < pdata->num_leds; i++) out:
delete_lt3593_led(&leds_data[i]); platform_set_drvdata(pdev, led_data);
return 0; 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 = { static struct platform_driver lt3593_led_driver = {
.probe = lt3593_led_probe, .probe = lt3593_led_probe,
.remove = lt3593_led_remove,
.driver = { .driver = {
.name = "leds-lt3593", .name = "leds-lt3593",
.of_match_table = of_match_ptr(of_lt3593_leds_match),
}, },
}; };
module_platform_driver(lt3593_led_driver); module_platform_driver(lt3593_led_driver);
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); MODULE_AUTHOR("Daniel Mack <daniel@zonque.org>");
MODULE_DESCRIPTION("LED driver for LT3593 controllers"); MODULE_DESCRIPTION("LED driver for LT3593 controllers");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:leds-lt3593"); MODULE_ALIAS("platform:leds-lt3593");
...@@ -268,7 +268,7 @@ static int max8997_led_probe(struct platform_device *pdev) ...@@ -268,7 +268,7 @@ static int max8997_led_probe(struct platform_device *pdev)
mode = pdata->led_pdata->mode[led->id]; mode = pdata->led_pdata->mode[led->id];
brightness = pdata->led_pdata->brightness[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) if (brightness > led->cdev.max_brightness)
brightness = led->cdev.max_brightness; brightness = led->cdev.max_brightness;
......
...@@ -42,8 +42,8 @@ ...@@ -42,8 +42,8 @@
struct ns2_led_data { struct ns2_led_data {
struct led_classdev cdev; struct led_classdev cdev;
unsigned cmd; unsigned int cmd;
unsigned slow; unsigned int slow;
bool can_sleep; bool can_sleep;
unsigned char sata; /* True when SATA mode active. */ unsigned char sata; /* True when SATA mode active. */
rwlock_t rw_lock; /* Lock GPIOs. */ rwlock_t rw_lock; /* Lock GPIOs. */
......
...@@ -10,7 +10,6 @@ if LEDS_TRIGGERS ...@@ -10,7 +10,6 @@ if LEDS_TRIGGERS
config LEDS_TRIGGER_TIMER config LEDS_TRIGGER_TIMER
tristate "LED Timer Trigger" tristate "LED Timer Trigger"
depends on LEDS_TRIGGERS
help help
This allows LEDs to be controlled by a programmable timer This allows LEDs to be controlled by a programmable timer
via sysfs. Some LED hardware can be programmed to start via sysfs. Some LED hardware can be programmed to start
...@@ -21,7 +20,6 @@ config LEDS_TRIGGER_TIMER ...@@ -21,7 +20,6 @@ config LEDS_TRIGGER_TIMER
config LEDS_TRIGGER_ONESHOT config LEDS_TRIGGER_ONESHOT
tristate "LED One-shot Trigger" tristate "LED One-shot Trigger"
depends on LEDS_TRIGGERS
help help
This allows LEDs to blink in one-shot pulses with parameters This allows LEDs to blink in one-shot pulses with parameters
controlled via sysfs. It's useful to notify the user on controlled via sysfs. It's useful to notify the user on
...@@ -36,7 +34,6 @@ config LEDS_TRIGGER_ONESHOT ...@@ -36,7 +34,6 @@ config LEDS_TRIGGER_ONESHOT
config LEDS_TRIGGER_DISK config LEDS_TRIGGER_DISK
bool "LED Disk Trigger" bool "LED Disk Trigger"
depends on IDE_GD_ATA || ATA depends on IDE_GD_ATA || ATA
depends on LEDS_TRIGGERS
help help
This allows LEDs to be controlled by disk activity. This allows LEDs to be controlled by disk activity.
If unsure, say Y. If unsure, say Y.
...@@ -44,14 +41,12 @@ config LEDS_TRIGGER_DISK ...@@ -44,14 +41,12 @@ config LEDS_TRIGGER_DISK
config LEDS_TRIGGER_MTD config LEDS_TRIGGER_MTD
bool "LED MTD (NAND/NOR) Trigger" bool "LED MTD (NAND/NOR) Trigger"
depends on MTD depends on MTD
depends on LEDS_TRIGGERS
help help
This allows LEDs to be controlled by MTD activity. This allows LEDs to be controlled by MTD activity.
If unsure, say N. If unsure, say N.
config LEDS_TRIGGER_HEARTBEAT config LEDS_TRIGGER_HEARTBEAT
tristate "LED Heartbeat Trigger" tristate "LED Heartbeat Trigger"
depends on LEDS_TRIGGERS
help help
This allows LEDs to be controlled by a CPU load average. This allows LEDs to be controlled by a CPU load average.
The flash frequency is a hyperbolic function of the 1-minute The flash frequency is a hyperbolic function of the 1-minute
...@@ -60,7 +55,6 @@ config LEDS_TRIGGER_HEARTBEAT ...@@ -60,7 +55,6 @@ config LEDS_TRIGGER_HEARTBEAT
config LEDS_TRIGGER_BACKLIGHT config LEDS_TRIGGER_BACKLIGHT
tristate "LED backlight Trigger" tristate "LED backlight Trigger"
depends on LEDS_TRIGGERS
help help
This allows LEDs to be controlled as a backlight device: they This allows LEDs to be controlled as a backlight device: they
turn off and on when the display is blanked and unblanked. turn off and on when the display is blanked and unblanked.
...@@ -69,7 +63,6 @@ config LEDS_TRIGGER_BACKLIGHT ...@@ -69,7 +63,6 @@ config LEDS_TRIGGER_BACKLIGHT
config LEDS_TRIGGER_CPU config LEDS_TRIGGER_CPU
bool "LED CPU Trigger" bool "LED CPU Trigger"
depends on LEDS_TRIGGERS
help help
This allows LEDs to be controlled by active CPUs. This shows This allows LEDs to be controlled by active CPUs. This shows
the active CPUs across an array of LEDs so you can see which the active CPUs across an array of LEDs so you can see which
...@@ -79,7 +72,6 @@ config LEDS_TRIGGER_CPU ...@@ -79,7 +72,6 @@ config LEDS_TRIGGER_CPU
config LEDS_TRIGGER_ACTIVITY config LEDS_TRIGGER_ACTIVITY
tristate "LED activity Trigger" tristate "LED activity Trigger"
depends on LEDS_TRIGGERS
help help
This allows LEDs to be controlled by an immediate CPU usage. This allows LEDs to be controlled by an immediate CPU usage.
The flash frequency and duty cycle varies from faint flashes to The flash frequency and duty cycle varies from faint flashes to
...@@ -88,7 +80,6 @@ config LEDS_TRIGGER_ACTIVITY ...@@ -88,7 +80,6 @@ config LEDS_TRIGGER_ACTIVITY
config LEDS_TRIGGER_GPIO config LEDS_TRIGGER_GPIO
tristate "LED GPIO Trigger" tristate "LED GPIO Trigger"
depends on LEDS_TRIGGERS
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
help help
This allows LEDs to be controlled by gpio events. It's good This allows LEDs to be controlled by gpio events. It's good
...@@ -101,7 +92,6 @@ config LEDS_TRIGGER_GPIO ...@@ -101,7 +92,6 @@ config LEDS_TRIGGER_GPIO
config LEDS_TRIGGER_DEFAULT_ON config LEDS_TRIGGER_DEFAULT_ON
tristate "LED Default ON Trigger" tristate "LED Default ON Trigger"
depends on LEDS_TRIGGERS
help help
This allows LEDs to be initialised in the ON state. This allows LEDs to be initialised in the ON state.
If unsure, say Y. If unsure, say Y.
...@@ -111,7 +101,6 @@ comment "iptables trigger is under Netfilter config (LED target)" ...@@ -111,7 +101,6 @@ comment "iptables trigger is under Netfilter config (LED target)"
config LEDS_TRIGGER_TRANSIENT config LEDS_TRIGGER_TRANSIENT
tristate "LED Transient Trigger" tristate "LED Transient Trigger"
depends on LEDS_TRIGGERS
help help
This allows one time activation of a transient state on This allows one time activation of a transient state on
GPIO/PWM based hardware. GPIO/PWM based hardware.
...@@ -119,7 +108,6 @@ config LEDS_TRIGGER_TRANSIENT ...@@ -119,7 +108,6 @@ config LEDS_TRIGGER_TRANSIENT
config LEDS_TRIGGER_CAMERA config LEDS_TRIGGER_CAMERA
tristate "LED Camera Flash/Torch Trigger" tristate "LED Camera Flash/Torch Trigger"
depends on LEDS_TRIGGERS
help help
This allows LEDs to be controlled as a camera flash/torch device. This allows LEDs to be controlled as a camera flash/torch device.
This enables direct flash/torch on/off by the driver, kernel space. This enables direct flash/torch on/off by the driver, kernel space.
...@@ -127,7 +115,6 @@ config LEDS_TRIGGER_CAMERA ...@@ -127,7 +115,6 @@ config LEDS_TRIGGER_CAMERA
config LEDS_TRIGGER_PANIC config LEDS_TRIGGER_PANIC
bool "LED Panic Trigger" bool "LED Panic Trigger"
depends on LEDS_TRIGGERS
help help
This allows LEDs to be configured to blink on a kernel panic. This allows LEDs to be configured to blink on a kernel panic.
Enabling this option will allow to mark certain LEDs as panic indicators, Enabling this option will allow to mark certain LEDs as panic indicators,
...@@ -137,7 +124,7 @@ config LEDS_TRIGGER_PANIC ...@@ -137,7 +124,7 @@ config LEDS_TRIGGER_PANIC
config LEDS_TRIGGER_NETDEV config LEDS_TRIGGER_NETDEV
tristate "LED Netdev Trigger" tristate "LED Netdev Trigger"
depends on NET && LEDS_TRIGGERS depends on NET
help help
This allows LEDs to be controlled by network device activity. This allows LEDs to be controlled by network device activity.
If unsure, say Y. If unsure, say Y.
......
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
...@@ -37,7 +37,6 @@ static void led_activity_function(struct timer_list *t) ...@@ -37,7 +37,6 @@ static void led_activity_function(struct timer_list *t)
struct activity_data *activity_data = from_timer(activity_data, t, struct activity_data *activity_data = from_timer(activity_data, t,
timer); timer);
struct led_classdev *led_cdev = activity_data->led_cdev; struct led_classdev *led_cdev = activity_data->led_cdev;
struct timespec boot_time;
unsigned int target; unsigned int target;
unsigned int usage; unsigned int usage;
int delay; int delay;
...@@ -57,8 +56,6 @@ static void led_activity_function(struct timer_list *t) ...@@ -57,8 +56,6 @@ static void led_activity_function(struct timer_list *t)
return; return;
} }
get_monotonic_boottime(&boot_time);
cpus = 0; cpus = 0;
curr_used = 0; curr_used = 0;
...@@ -76,7 +73,7 @@ static void led_activity_function(struct timer_list *t) ...@@ -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 * down to 16us, ensuring we won't overflow 32-bit computations below
* even up to 3k CPUs, while keeping divides cheap on smaller systems. * 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_boot = (curr_boot - activity_data->last_boot) >> 16;
diff_used = (curr_used - activity_data->last_used) >> 16; diff_used = (curr_used - activity_data->last_used) >> 16;
activity_data->last_boot = curr_boot; activity_data->last_boot = curr_boot;
...@@ -155,8 +152,7 @@ static void led_activity_function(struct timer_list *t) ...@@ -155,8 +152,7 @@ static void led_activity_function(struct timer_list *t)
static ssize_t led_invert_show(struct device *dev, static ssize_t led_invert_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct activity_data *activity_data = led_trigger_get_drvdata(dev);
struct activity_data *activity_data = led_cdev->trigger_data;
return sprintf(buf, "%u\n", activity_data->invert); return sprintf(buf, "%u\n", activity_data->invert);
} }
...@@ -165,8 +161,7 @@ static ssize_t led_invert_store(struct device *dev, ...@@ -165,8 +161,7 @@ static ssize_t led_invert_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t size) const char *buf, size_t size)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct activity_data *activity_data = led_trigger_get_drvdata(dev);
struct activity_data *activity_data = led_cdev->trigger_data;
unsigned long state; unsigned long state;
int ret; int ret;
...@@ -181,21 +176,21 @@ static ssize_t led_invert_store(struct device *dev, ...@@ -181,21 +176,21 @@ static ssize_t led_invert_store(struct device *dev,
static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store); static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
static void activity_activate(struct led_classdev *led_cdev) 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; struct activity_data *activity_data;
int rc;
activity_data = kzalloc(sizeof(*activity_data), GFP_KERNEL); activity_data = kzalloc(sizeof(*activity_data), GFP_KERNEL);
if (!activity_data) if (!activity_data)
return; return -ENOMEM;
led_cdev->trigger_data = activity_data; led_set_trigger_data(led_cdev, activity_data);
rc = device_create_file(led_cdev->dev, &dev_attr_invert);
if (rc) {
kfree(led_cdev->trigger_data);
return;
}
activity_data->led_cdev = led_cdev; activity_data->led_cdev = led_cdev;
timer_setup(&activity_data->timer, led_activity_function, 0); timer_setup(&activity_data->timer, led_activity_function, 0);
...@@ -203,26 +198,24 @@ static void activity_activate(struct led_classdev *led_cdev) ...@@ -203,26 +198,24 @@ static void activity_activate(struct led_classdev *led_cdev)
led_cdev->blink_brightness = led_cdev->max_brightness; led_cdev->blink_brightness = led_cdev->max_brightness;
led_activity_function(&activity_data->timer); led_activity_function(&activity_data->timer);
set_bit(LED_BLINK_SW, &led_cdev->work_flags); set_bit(LED_BLINK_SW, &led_cdev->work_flags);
led_cdev->activated = true;
return 0;
} }
static void activity_deactivate(struct led_classdev *led_cdev) static void activity_deactivate(struct led_classdev *led_cdev)
{ {
struct activity_data *activity_data = led_cdev->trigger_data; struct activity_data *activity_data = led_get_trigger_data(led_cdev);
if (led_cdev->activated) { del_timer_sync(&activity_data->timer);
del_timer_sync(&activity_data->timer); kfree(activity_data);
device_remove_file(led_cdev->dev, &dev_attr_invert); clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
kfree(activity_data);
clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
led_cdev->activated = false;
}
} }
static struct led_trigger activity_led_trigger = { static struct led_trigger activity_led_trigger = {
.name = "activity", .name = "activity",
.activate = activity_activate, .activate = activity_activate,
.deactivate = activity_deactivate, .deactivate = activity_deactivate,
.groups = activity_led_groups,
}; };
static int activity_reboot_notifier(struct notifier_block *nb, static int activity_reboot_notifier(struct notifier_block *nb,
...@@ -272,4 +265,4 @@ module_exit(activity_exit); ...@@ -272,4 +265,4 @@ module_exit(activity_exit);
MODULE_AUTHOR("Willy Tarreau <w@1wt.eu>"); MODULE_AUTHOR("Willy Tarreau <w@1wt.eu>");
MODULE_DESCRIPTION("Activity LED trigger"); MODULE_DESCRIPTION("Activity LED trigger");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
...@@ -64,8 +64,7 @@ static int fb_notifier_callback(struct notifier_block *p, ...@@ -64,8 +64,7 @@ static int fb_notifier_callback(struct notifier_block *p,
static ssize_t bl_trig_invert_show(struct device *dev, static ssize_t bl_trig_invert_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led = dev_get_drvdata(dev); struct bl_trig_notifier *n = led_trigger_get_drvdata(dev);
struct bl_trig_notifier *n = led->trigger_data;
return sprintf(buf, "%u\n", n->invert); return sprintf(buf, "%u\n", n->invert);
} }
...@@ -73,8 +72,8 @@ static ssize_t bl_trig_invert_show(struct device *dev, ...@@ -73,8 +72,8 @@ static ssize_t bl_trig_invert_show(struct device *dev,
static ssize_t bl_trig_invert_store(struct device *dev, static ssize_t bl_trig_invert_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t num) struct device_attribute *attr, const char *buf, size_t num)
{ {
struct led_classdev *led = dev_get_drvdata(dev); struct led_classdev *led = led_trigger_get_led(dev);
struct bl_trig_notifier *n = led->trigger_data; struct bl_trig_notifier *n = led_trigger_get_drvdata(dev);
unsigned long invert; unsigned long invert;
int ret; int ret;
...@@ -97,22 +96,22 @@ static ssize_t bl_trig_invert_store(struct device *dev, ...@@ -97,22 +96,22 @@ static ssize_t bl_trig_invert_store(struct device *dev,
} }
static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store); static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store);
static void bl_trig_activate(struct led_classdev *led) 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; int ret;
struct bl_trig_notifier *n; struct bl_trig_notifier *n;
n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL); n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL);
led->trigger_data = n; if (!n)
if (!n) { return -ENOMEM;
dev_err(led->dev, "unable to allocate backlight trigger\n"); led_set_trigger_data(led, n);
return;
}
ret = device_create_file(led->dev, &dev_attr_inverted);
if (ret)
goto err_invert;
n->led = led; n->led = led;
n->brightness = led->brightness; n->brightness = led->brightness;
...@@ -122,46 +121,25 @@ static void bl_trig_activate(struct led_classdev *led) ...@@ -122,46 +121,25 @@ static void bl_trig_activate(struct led_classdev *led)
ret = fb_register_client(&n->notifier); ret = fb_register_client(&n->notifier);
if (ret) if (ret)
dev_err(led->dev, "unable to register backlight trigger\n"); dev_err(led->dev, "unable to register backlight trigger\n");
led->activated = true;
return; return 0;
err_invert:
led->trigger_data = NULL;
kfree(n);
} }
static void bl_trig_deactivate(struct led_classdev *led) static void bl_trig_deactivate(struct led_classdev *led)
{ {
struct bl_trig_notifier *n = struct bl_trig_notifier *n = led_get_trigger_data(led);
(struct bl_trig_notifier *) led->trigger_data;
fb_unregister_client(&n->notifier);
if (led->activated) { kfree(n);
device_remove_file(led->dev, &dev_attr_inverted);
fb_unregister_client(&n->notifier);
kfree(n);
led->activated = false;
}
} }
static struct led_trigger bl_led_trigger = { static struct led_trigger bl_led_trigger = {
.name = "backlight", .name = "backlight",
.activate = bl_trig_activate, .activate = bl_trig_activate,
.deactivate = bl_trig_deactivate .deactivate = bl_trig_deactivate,
.groups = bl_trig_groups,
}; };
module_led_trigger(bl_led_trigger);
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_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
MODULE_DESCRIPTION("Backlight emulation LED trigger"); MODULE_DESCRIPTION("Backlight emulation LED trigger");
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -54,4 +53,4 @@ module_exit(ledtrig_camera_exit); ...@@ -54,4 +53,4 @@ module_exit(ledtrig_camera_exit);
MODULE_DESCRIPTION("LED Trigger for Camera Flash/Torch Control"); MODULE_DESCRIPTION("LED Trigger for Camera Flash/Torch Control");
MODULE_AUTHOR("Milo Kim"); MODULE_AUTHOR("Milo Kim");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -17,29 +16,18 @@ ...@@ -17,29 +16,18 @@
#include <linux/leds.h> #include <linux/leds.h>
#include "../leds.h" #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); led_set_brightness_nosleep(led_cdev, led_cdev->max_brightness);
return 0;
} }
static struct led_trigger defon_led_trigger = { static struct led_trigger defon_led_trigger = {
.name = "default-on", .name = "default-on",
.activate = defon_trig_activate, .activate = defon_trig_activate,
}; };
module_led_trigger(defon_led_trigger);
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_AUTHOR("Nick Forbes <nick.forbes@incepta.com>"); MODULE_AUTHOR("Nick Forbes <nick.forbes@incepta.com>");
MODULE_DESCRIPTION("Default-ON LED trigger"); MODULE_DESCRIPTION("Default-ON LED trigger");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -29,7 +28,7 @@ struct gpio_trig_data { ...@@ -29,7 +28,7 @@ struct gpio_trig_data {
static irqreturn_t gpio_trig_irq(int irq, void *_led) static irqreturn_t gpio_trig_irq(int irq, void *_led)
{ {
struct led_classdev *led = _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; int tmp;
tmp = gpio_get_value_cansleep(gpio_data->gpio); tmp = gpio_get_value_cansleep(gpio_data->gpio);
...@@ -52,8 +51,7 @@ static irqreturn_t gpio_trig_irq(int irq, void *_led) ...@@ -52,8 +51,7 @@ static irqreturn_t gpio_trig_irq(int irq, void *_led)
static ssize_t gpio_trig_brightness_show(struct device *dev, static ssize_t gpio_trig_brightness_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led = dev_get_drvdata(dev); struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);
struct gpio_trig_data *gpio_data = led->trigger_data;
return sprintf(buf, "%u\n", gpio_data->desired_brightness); return sprintf(buf, "%u\n", gpio_data->desired_brightness);
} }
...@@ -61,8 +59,7 @@ static ssize_t gpio_trig_brightness_show(struct device *dev, ...@@ -61,8 +59,7 @@ static ssize_t gpio_trig_brightness_show(struct device *dev,
static ssize_t gpio_trig_brightness_store(struct device *dev, static ssize_t gpio_trig_brightness_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t n) 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_get_drvdata(dev);
struct gpio_trig_data *gpio_data = led->trigger_data;
unsigned desired_brightness; unsigned desired_brightness;
int ret; int ret;
...@@ -82,8 +79,7 @@ static DEVICE_ATTR(desired_brightness, 0644, gpio_trig_brightness_show, ...@@ -82,8 +79,7 @@ static DEVICE_ATTR(desired_brightness, 0644, gpio_trig_brightness_show,
static ssize_t gpio_trig_inverted_show(struct device *dev, static ssize_t gpio_trig_inverted_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led = dev_get_drvdata(dev); struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);
struct gpio_trig_data *gpio_data = led->trigger_data;
return sprintf(buf, "%u\n", gpio_data->inverted); return sprintf(buf, "%u\n", gpio_data->inverted);
} }
...@@ -91,8 +87,8 @@ static ssize_t gpio_trig_inverted_show(struct device *dev, ...@@ -91,8 +87,8 @@ static ssize_t gpio_trig_inverted_show(struct device *dev,
static ssize_t gpio_trig_inverted_store(struct device *dev, static ssize_t gpio_trig_inverted_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t n) struct device_attribute *attr, const char *buf, size_t n)
{ {
struct led_classdev *led = dev_get_drvdata(dev); struct led_classdev *led = led_trigger_get_led(dev);
struct gpio_trig_data *gpio_data = led->trigger_data; struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);
unsigned long inverted; unsigned long inverted;
int ret; int ret;
...@@ -116,8 +112,7 @@ static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show, ...@@ -116,8 +112,7 @@ static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show,
static ssize_t gpio_trig_gpio_show(struct device *dev, static ssize_t gpio_trig_gpio_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led = dev_get_drvdata(dev); struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);
struct gpio_trig_data *gpio_data = led->trigger_data;
return sprintf(buf, "%u\n", gpio_data->gpio); return sprintf(buf, "%u\n", gpio_data->gpio);
} }
...@@ -125,8 +120,8 @@ static ssize_t gpio_trig_gpio_show(struct device *dev, ...@@ -125,8 +120,8 @@ static ssize_t gpio_trig_gpio_show(struct device *dev,
static ssize_t gpio_trig_gpio_store(struct device *dev, static ssize_t gpio_trig_gpio_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t n) struct device_attribute *attr, const char *buf, size_t n)
{ {
struct led_classdev *led = dev_get_drvdata(dev); struct led_classdev *led = led_trigger_get_led(dev);
struct gpio_trig_data *gpio_data = led->trigger_data; struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);
unsigned gpio; unsigned gpio;
int ret; int ret;
...@@ -163,76 +158,45 @@ static ssize_t gpio_trig_gpio_store(struct device *dev, ...@@ -163,76 +158,45 @@ static ssize_t gpio_trig_gpio_store(struct device *dev,
} }
static DEVICE_ATTR(gpio, 0644, gpio_trig_gpio_show, gpio_trig_gpio_store); static DEVICE_ATTR(gpio, 0644, gpio_trig_gpio_show, gpio_trig_gpio_store);
static void gpio_trig_activate(struct led_classdev *led) 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; struct gpio_trig_data *gpio_data;
int ret;
gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL); gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL);
if (!gpio_data) if (!gpio_data)
return; return -ENOMEM;
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;
gpio_data->led = led; gpio_data->led = led;
led->trigger_data = gpio_data; led_set_trigger_data(led, gpio_data);
led->activated = true;
return;
err_brightness:
device_remove_file(led->dev, &dev_attr_inverted);
err_inverted: return 0;
device_remove_file(led->dev, &dev_attr_gpio);
err_gpio:
kfree(gpio_data);
} }
static void gpio_trig_deactivate(struct led_classdev *led) 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) { if (gpio_data->gpio != 0)
device_remove_file(led->dev, &dev_attr_gpio); free_irq(gpio_to_irq(gpio_data->gpio), led);
device_remove_file(led->dev, &dev_attr_inverted); kfree(gpio_data);
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;
}
} }
static struct led_trigger gpio_led_trigger = { static struct led_trigger gpio_led_trigger = {
.name = "gpio", .name = "gpio",
.activate = gpio_trig_activate, .activate = gpio_trig_activate,
.deactivate = gpio_trig_deactivate, .deactivate = gpio_trig_deactivate,
.groups = gpio_trig_groups,
}; };
module_led_trigger(gpio_led_trigger);
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_AUTHOR("Felipe Balbi <me@felipebalbi.com>"); MODULE_AUTHOR("Felipe Balbi <me@felipebalbi.com>");
MODULE_DESCRIPTION("GPIO LED trigger"); MODULE_DESCRIPTION("GPIO LED trigger");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -96,8 +96,8 @@ static void led_heartbeat_function(struct timer_list *t) ...@@ -96,8 +96,8 @@ static void led_heartbeat_function(struct timer_list *t)
static ssize_t led_invert_show(struct device *dev, static ssize_t led_invert_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct heartbeat_trig_data *heartbeat_data =
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; led_trigger_get_drvdata(dev);
return sprintf(buf, "%u\n", heartbeat_data->invert); return sprintf(buf, "%u\n", heartbeat_data->invert);
} }
...@@ -105,8 +105,8 @@ static ssize_t led_invert_show(struct device *dev, ...@@ -105,8 +105,8 @@ static ssize_t led_invert_show(struct device *dev,
static ssize_t led_invert_store(struct device *dev, static ssize_t led_invert_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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 =
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; led_trigger_get_drvdata(dev);
unsigned long state; unsigned long state;
int ret; int ret;
...@@ -121,22 +121,22 @@ static ssize_t led_invert_store(struct device *dev, ...@@ -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 DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
static void heartbeat_trig_activate(struct led_classdev *led_cdev) 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; struct heartbeat_trig_data *heartbeat_data;
int rc;
heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
if (!heartbeat_data) if (!heartbeat_data)
return; return -ENOMEM;
led_cdev->trigger_data = heartbeat_data; led_set_trigger_data(led_cdev, heartbeat_data);
heartbeat_data->led_cdev = led_cdev; heartbeat_data->led_cdev = led_cdev;
rc = device_create_file(led_cdev->dev, &dev_attr_invert);
if (rc) {
kfree(led_cdev->trigger_data);
return;
}
timer_setup(&heartbeat_data->timer, led_heartbeat_function, 0); timer_setup(&heartbeat_data->timer, led_heartbeat_function, 0);
heartbeat_data->phase = 0; heartbeat_data->phase = 0;
...@@ -144,26 +144,25 @@ static void heartbeat_trig_activate(struct led_classdev *led_cdev) ...@@ -144,26 +144,25 @@ static void heartbeat_trig_activate(struct led_classdev *led_cdev)
led_cdev->blink_brightness = led_cdev->max_brightness; led_cdev->blink_brightness = led_cdev->max_brightness;
led_heartbeat_function(&heartbeat_data->timer); led_heartbeat_function(&heartbeat_data->timer);
set_bit(LED_BLINK_SW, &led_cdev->work_flags); 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) static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
{ {
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; struct heartbeat_trig_data *heartbeat_data =
led_get_trigger_data(led_cdev);
if (led_cdev->activated) {
del_timer_sync(&heartbeat_data->timer); del_timer_sync(&heartbeat_data->timer);
device_remove_file(led_cdev->dev, &dev_attr_invert); kfree(heartbeat_data);
kfree(heartbeat_data); clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
led_cdev->activated = false;
}
} }
static struct led_trigger heartbeat_led_trigger = { static struct led_trigger heartbeat_led_trigger = {
.name = "heartbeat", .name = "heartbeat",
.activate = heartbeat_trig_activate, .activate = heartbeat_trig_activate,
.deactivate = heartbeat_trig_deactivate, .deactivate = heartbeat_trig_deactivate,
.groups = heartbeat_trig_groups,
}; };
static int heartbeat_reboot_notifier(struct notifier_block *nb, static int heartbeat_reboot_notifier(struct notifier_block *nb,
...@@ -213,4 +212,4 @@ module_exit(heartbeat_trig_exit); ...@@ -213,4 +212,4 @@ module_exit(heartbeat_trig_exit);
MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
MODULE_DESCRIPTION("Heartbeat LED trigger"); MODULE_DESCRIPTION("Heartbeat LED trigger");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
...@@ -94,8 +94,7 @@ static void set_baseline_state(struct led_netdev_data *trigger_data) ...@@ -94,8 +94,7 @@ static void set_baseline_state(struct led_netdev_data *trigger_data)
static ssize_t device_name_show(struct device *dev, static ssize_t device_name_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
ssize_t len; ssize_t len;
spin_lock_bh(&trigger_data->lock); spin_lock_bh(&trigger_data->lock);
...@@ -109,8 +108,7 @@ static ssize_t device_name_store(struct device *dev, ...@@ -109,8 +108,7 @@ static ssize_t device_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, struct device_attribute *attr, const char *buf,
size_t size) size_t size)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
if (size >= IFNAMSIZ) if (size >= IFNAMSIZ)
return -EINVAL; return -EINVAL;
...@@ -150,8 +148,7 @@ static DEVICE_ATTR_RW(device_name); ...@@ -150,8 +148,7 @@ static DEVICE_ATTR_RW(device_name);
static ssize_t netdev_led_attr_show(struct device *dev, char *buf, static ssize_t netdev_led_attr_show(struct device *dev, char *buf,
enum netdev_led_attr attr) enum netdev_led_attr attr)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
int bit; int bit;
switch (attr) { switch (attr) {
...@@ -174,8 +171,7 @@ static ssize_t netdev_led_attr_show(struct device *dev, char *buf, ...@@ -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, static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
size_t size, enum netdev_led_attr attr) size_t size, enum netdev_led_attr attr)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
unsigned long state; unsigned long state;
int ret; int ret;
int bit; int bit;
...@@ -255,8 +251,7 @@ static DEVICE_ATTR_RW(rx); ...@@ -255,8 +251,7 @@ static DEVICE_ATTR_RW(rx);
static ssize_t interval_show(struct device *dev, static ssize_t interval_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
return sprintf(buf, "%u\n", return sprintf(buf, "%u\n",
jiffies_to_msecs(atomic_read(&trigger_data->interval))); jiffies_to_msecs(atomic_read(&trigger_data->interval)));
...@@ -266,8 +261,7 @@ static ssize_t interval_store(struct device *dev, ...@@ -266,8 +261,7 @@ static ssize_t interval_store(struct device *dev,
struct device_attribute *attr, const char *buf, struct device_attribute *attr, const char *buf,
size_t size) size_t size)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
unsigned long value; unsigned long value;
int ret; int ret;
...@@ -288,15 +282,23 @@ static ssize_t interval_store(struct device *dev, ...@@ -288,15 +282,23 @@ static ssize_t interval_store(struct device *dev,
static DEVICE_ATTR_RW(interval); 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, static int netdev_trig_notify(struct notifier_block *nb,
unsigned long evt, void *dv) unsigned long evt, void *dv)
{ {
struct net_device *dev = struct net_device *dev =
netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv); netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv);
struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data *trigger_data =
struct container_of(nb, struct led_netdev_data, notifier);
led_netdev_data,
notifier);
if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
&& evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER
...@@ -342,10 +344,8 @@ static int netdev_trig_notify(struct notifier_block *nb, ...@@ -342,10 +344,8 @@ static int netdev_trig_notify(struct notifier_block *nb,
/* here's the real work! */ /* here's the real work! */
static void netdev_trig_work(struct work_struct *work) static void netdev_trig_work(struct work_struct *work)
{ {
struct led_netdev_data *trigger_data = container_of(work, struct led_netdev_data *trigger_data =
struct container_of(work, struct led_netdev_data, work.work);
led_netdev_data,
work.work);
struct rtnl_link_stats64 *dev_stats; struct rtnl_link_stats64 *dev_stats;
unsigned int new_activity; unsigned int new_activity;
struct rtnl_link_stats64 temp; struct rtnl_link_stats64 temp;
...@@ -388,14 +388,14 @@ static void netdev_trig_work(struct work_struct *work) ...@@ -388,14 +388,14 @@ static void netdev_trig_work(struct work_struct *work)
(atomic_read(&trigger_data->interval)*2)); (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; struct led_netdev_data *trigger_data;
int rc; int rc;
trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
if (!trigger_data) if (!trigger_data)
return; return -ENOMEM;
spin_lock_init(&trigger_data->lock); spin_lock_init(&trigger_data->lock);
...@@ -412,69 +412,34 @@ static void netdev_trig_activate(struct led_classdev *led_cdev) ...@@ -412,69 +412,34 @@ static void netdev_trig_activate(struct led_classdev *led_cdev)
atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); atomic_set(&trigger_data->interval, msecs_to_jiffies(50));
trigger_data->last_activity = 0; 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); rc = register_netdevice_notifier(&trigger_data->notifier);
if (rc) if (rc)
goto err_out_interval; kfree(trigger_data);
return;
return rc;
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);
} }
static void netdev_trig_deactivate(struct led_classdev *led_cdev) 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);
device_remove_file(led_cdev->dev, &dev_attr_device_name); unregister_netdevice_notifier(&trigger_data->notifier);
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) if (trigger_data->net_dev)
dev_put(trigger_data->net_dev); dev_put(trigger_data->net_dev);
kfree(trigger_data); kfree(trigger_data);
}
} }
static struct led_trigger netdev_led_trigger = { static struct led_trigger netdev_led_trigger = {
.name = "netdev", .name = "netdev",
.activate = netdev_trig_activate, .activate = netdev_trig_activate,
.deactivate = netdev_trig_deactivate, .deactivate = netdev_trig_deactivate,
.groups = netdev_trig_groups,
}; };
static int __init netdev_trig_init(void) static int __init netdev_trig_init(void)
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -29,8 +28,8 @@ struct oneshot_trig_data { ...@@ -29,8 +28,8 @@ struct oneshot_trig_data {
static ssize_t led_shot(struct device *dev, static ssize_t led_shot(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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);
struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev);
led_blink_set_oneshot(led_cdev, led_blink_set_oneshot(led_cdev,
&led_cdev->blink_delay_on, &led_cdev->blink_delay_off, &led_cdev->blink_delay_on, &led_cdev->blink_delay_off,
...@@ -42,8 +41,7 @@ static ssize_t led_shot(struct device *dev, ...@@ -42,8 +41,7 @@ static ssize_t led_shot(struct device *dev,
static ssize_t led_invert_show(struct device *dev, static ssize_t led_invert_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev);
struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
return sprintf(buf, "%u\n", oneshot_data->invert); return sprintf(buf, "%u\n", oneshot_data->invert);
} }
...@@ -51,8 +49,8 @@ static ssize_t led_invert_show(struct device *dev, ...@@ -51,8 +49,8 @@ static ssize_t led_invert_show(struct device *dev,
static ssize_t led_invert_store(struct device *dev, static ssize_t led_invert_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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);
struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev);
unsigned long state; unsigned long state;
int ret; int ret;
...@@ -73,7 +71,7 @@ static ssize_t led_invert_store(struct device *dev, ...@@ -73,7 +71,7 @@ static ssize_t led_invert_store(struct device *dev,
static ssize_t led_delay_on_show(struct device *dev, static ssize_t led_delay_on_show(struct device *dev,
struct device_attribute *attr, char *buf) 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); return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
} }
...@@ -81,7 +79,7 @@ static ssize_t led_delay_on_show(struct device *dev, ...@@ -81,7 +79,7 @@ static ssize_t led_delay_on_show(struct device *dev,
static ssize_t led_delay_on_store(struct device *dev, static ssize_t led_delay_on_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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; unsigned long state;
int ret; int ret;
...@@ -93,10 +91,11 @@ static ssize_t led_delay_on_store(struct device *dev, ...@@ -93,10 +91,11 @@ static ssize_t led_delay_on_store(struct device *dev,
return size; return size;
} }
static ssize_t led_delay_off_show(struct device *dev, static ssize_t led_delay_off_show(struct device *dev,
struct device_attribute *attr, char *buf) 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); return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
} }
...@@ -104,7 +103,7 @@ static ssize_t led_delay_off_show(struct device *dev, ...@@ -104,7 +103,7 @@ static ssize_t led_delay_off_show(struct device *dev,
static ssize_t led_delay_off_store(struct device *dev, static ssize_t led_delay_off_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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; unsigned long state;
int ret; int ret;
...@@ -122,59 +121,36 @@ static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); ...@@ -122,59 +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(invert, 0644, led_invert_show, led_invert_store);
static DEVICE_ATTR(shot, 0200, NULL, led_shot); static DEVICE_ATTR(shot, 0200, NULL, led_shot);
static void oneshot_trig_activate(struct led_classdev *led_cdev) 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; struct oneshot_trig_data *oneshot_data;
int rc;
oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL); oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL);
if (!oneshot_data) if (!oneshot_data)
return; return -ENOMEM;
led_cdev->trigger_data = oneshot_data; led_set_trigger_data(led_cdev, 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;
led_cdev->blink_delay_on = DEFAULT_DELAY; led_cdev->blink_delay_on = DEFAULT_DELAY;
led_cdev->blink_delay_off = DEFAULT_DELAY; led_cdev->blink_delay_off = DEFAULT_DELAY;
led_cdev->activated = true; return 0;
return;
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);
} }
static void oneshot_trig_deactivate(struct led_classdev *led_cdev) 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) { kfree(oneshot_data);
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;
}
/* Stop blinking */ /* Stop blinking */
led_set_brightness(led_cdev, LED_OFF); led_set_brightness(led_cdev, LED_OFF);
...@@ -184,20 +160,9 @@ static struct led_trigger oneshot_led_trigger = { ...@@ -184,20 +160,9 @@ static struct led_trigger oneshot_led_trigger = {
.name = "oneshot", .name = "oneshot",
.activate = oneshot_trig_activate, .activate = oneshot_trig_activate,
.deactivate = oneshot_trig_deactivate, .deactivate = oneshot_trig_deactivate,
.groups = oneshot_trig_groups,
}; };
module_led_trigger(oneshot_led_trigger);
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_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>"); MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>");
MODULE_DESCRIPTION("One-shot LED trigger"); MODULE_DESCRIPTION("One-shot LED trigger");
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -21,7 +20,7 @@ ...@@ -21,7 +20,7 @@
static ssize_t led_delay_on_show(struct device *dev, static ssize_t led_delay_on_show(struct device *dev,
struct device_attribute *attr, char *buf) 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); return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
} }
...@@ -29,7 +28,7 @@ static ssize_t led_delay_on_show(struct device *dev, ...@@ -29,7 +28,7 @@ static ssize_t led_delay_on_show(struct device *dev,
static ssize_t led_delay_on_store(struct device *dev, static ssize_t led_delay_on_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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; unsigned long state;
ssize_t ret = -EINVAL; ssize_t ret = -EINVAL;
...@@ -46,7 +45,7 @@ static ssize_t led_delay_on_store(struct device *dev, ...@@ -46,7 +45,7 @@ static ssize_t led_delay_on_store(struct device *dev,
static ssize_t led_delay_off_show(struct device *dev, static ssize_t led_delay_off_show(struct device *dev,
struct device_attribute *attr, char *buf) 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); return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
} }
...@@ -54,7 +53,7 @@ static ssize_t led_delay_off_show(struct device *dev, ...@@ -54,7 +53,7 @@ static ssize_t led_delay_off_show(struct device *dev,
static ssize_t led_delay_off_store(struct device *dev, static ssize_t led_delay_off_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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; unsigned long state;
ssize_t ret = -EINVAL; ssize_t ret = -EINVAL;
...@@ -71,37 +70,23 @@ static ssize_t led_delay_off_store(struct device *dev, ...@@ -71,37 +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_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 DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
static void timer_trig_activate(struct led_classdev *led_cdev) static struct attribute *timer_trig_attrs[] = {
{ &dev_attr_delay_on.attr,
int rc; &dev_attr_delay_off.attr,
NULL
led_cdev->trigger_data = NULL; };
ATTRIBUTE_GROUPS(timer_trig);
rc = device_create_file(led_cdev->dev, &dev_attr_delay_on);
if (rc)
return;
rc = device_create_file(led_cdev->dev, &dev_attr_delay_off);
if (rc)
goto err_out_delayon;
static int timer_trig_activate(struct led_classdev *led_cdev)
{
led_blink_set(led_cdev, &led_cdev->blink_delay_on, led_blink_set(led_cdev, &led_cdev->blink_delay_on,
&led_cdev->blink_delay_off); &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);
} }
static void timer_trig_deactivate(struct led_classdev *led_cdev) 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 */ /* Stop blinking */
led_set_brightness(led_cdev, LED_OFF); led_set_brightness(led_cdev, LED_OFF);
} }
...@@ -110,21 +95,10 @@ static struct led_trigger timer_led_trigger = { ...@@ -110,21 +95,10 @@ static struct led_trigger timer_led_trigger = {
.name = "timer", .name = "timer",
.activate = timer_trig_activate, .activate = timer_trig_activate,
.deactivate = timer_trig_deactivate, .deactivate = timer_trig_deactivate,
.groups = timer_trig_groups,
}; };
module_led_trigger(timer_led_trigger);
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_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
MODULE_DESCRIPTION("Timer LED trigger"); MODULE_DESCRIPTION("Timer LED trigger");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
...@@ -42,8 +42,8 @@ static void transient_timer_function(struct timer_list *t) ...@@ -42,8 +42,8 @@ static void transient_timer_function(struct timer_list *t)
static ssize_t transient_activate_show(struct device *dev, static ssize_t transient_activate_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct transient_trig_data *transient_data =
struct transient_trig_data *transient_data = led_cdev->trigger_data; led_trigger_get_drvdata(dev);
return sprintf(buf, "%d\n", transient_data->activate); return sprintf(buf, "%d\n", transient_data->activate);
} }
...@@ -51,8 +51,9 @@ static ssize_t transient_activate_show(struct device *dev, ...@@ -51,8 +51,9 @@ static ssize_t transient_activate_show(struct device *dev,
static ssize_t transient_activate_store(struct device *dev, static ssize_t transient_activate_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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);
struct transient_trig_data *transient_data = led_cdev->trigger_data; struct transient_trig_data *transient_data =
led_trigger_get_drvdata(dev);
unsigned long state; unsigned long state;
ssize_t ret; ssize_t ret;
...@@ -94,8 +95,7 @@ static ssize_t transient_activate_store(struct device *dev, ...@@ -94,8 +95,7 @@ static ssize_t transient_activate_store(struct device *dev,
static ssize_t transient_duration_show(struct device *dev, static ssize_t transient_duration_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct transient_trig_data *transient_data = led_trigger_get_drvdata(dev);
struct transient_trig_data *transient_data = led_cdev->trigger_data;
return sprintf(buf, "%lu\n", transient_data->duration); return sprintf(buf, "%lu\n", transient_data->duration);
} }
...@@ -103,8 +103,8 @@ static ssize_t transient_duration_show(struct device *dev, ...@@ -103,8 +103,8 @@ static ssize_t transient_duration_show(struct device *dev,
static ssize_t transient_duration_store(struct device *dev, static ssize_t transient_duration_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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 =
struct transient_trig_data *transient_data = led_cdev->trigger_data; led_trigger_get_drvdata(dev);
unsigned long state; unsigned long state;
ssize_t ret; ssize_t ret;
...@@ -119,8 +119,8 @@ static ssize_t transient_duration_store(struct device *dev, ...@@ -119,8 +119,8 @@ static ssize_t transient_duration_store(struct device *dev,
static ssize_t transient_state_show(struct device *dev, static ssize_t transient_state_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct transient_trig_data *transient_data =
struct transient_trig_data *transient_data = led_cdev->trigger_data; led_trigger_get_drvdata(dev);
int state; int state;
state = (transient_data->state == LED_FULL) ? 1 : 0; state = (transient_data->state == LED_FULL) ? 1 : 0;
...@@ -130,8 +130,8 @@ static ssize_t transient_state_show(struct device *dev, ...@@ -130,8 +130,8 @@ static ssize_t transient_state_show(struct device *dev,
static ssize_t transient_state_store(struct device *dev, static ssize_t transient_state_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size) 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 =
struct transient_trig_data *transient_data = led_cdev->trigger_data; led_trigger_get_drvdata(dev);
unsigned long state; unsigned long state;
ssize_t ret; ssize_t ret;
...@@ -152,82 +152,46 @@ static DEVICE_ATTR(duration, 0644, transient_duration_show, ...@@ -152,82 +152,46 @@ static DEVICE_ATTR(duration, 0644, transient_duration_show,
transient_duration_store); transient_duration_store);
static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store); static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store);
static void transient_trig_activate(struct led_classdev *led_cdev) 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; struct transient_trig_data *tdata;
tdata = kzalloc(sizeof(struct transient_trig_data), GFP_KERNEL); tdata = kzalloc(sizeof(struct transient_trig_data), GFP_KERNEL);
if (!tdata) { if (!tdata)
dev_err(led_cdev->dev, return -ENOMEM;
"unable to allocate transient trigger\n");
return;
}
led_cdev->trigger_data = tdata;
tdata->led_cdev = led_cdev;
rc = device_create_file(led_cdev->dev, &dev_attr_activate); led_set_trigger_data(led_cdev, tdata);
if (rc) tdata->led_cdev = led_cdev;
goto err_out;
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;
timer_setup(&tdata->timer, transient_timer_function, 0); timer_setup(&tdata->timer, transient_timer_function, 0);
led_cdev->activated = true;
return 0;
return;
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);
} }
static void transient_trig_deactivate(struct led_classdev *led_cdev) 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);
del_timer_sync(&transient_data->timer); led_set_brightness_nosleep(led_cdev, transient_data->restore_state);
led_set_brightness_nosleep(led_cdev, kfree(transient_data);
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);
}
} }
static struct led_trigger transient_trigger = { static struct led_trigger transient_trigger = {
.name = "transient", .name = "transient",
.activate = transient_trig_activate, .activate = transient_trig_activate,
.deactivate = transient_trig_deactivate, .deactivate = transient_trig_deactivate,
.groups = transient_trig_groups,
}; };
module_led_trigger(transient_trigger);
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_AUTHOR("Shuah Khan <shuahkhan@gmail.com>"); MODULE_AUTHOR("Shuah Khan <shuahkhan@gmail.com>");
MODULE_DESCRIPTION("Transient LED trigger"); MODULE_DESCRIPTION("Transient LED trigger");
......
...@@ -73,6 +73,12 @@ config CAN_CALC_BITTIMING ...@@ -73,6 +73,12 @@ config CAN_CALC_BITTIMING
config CAN_LEDS config CAN_LEDS
bool "Enable LED triggers for Netlink based drivers" bool "Enable LED triggers for Netlink based drivers"
depends on LEDS_CLASS 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 select LEDS_TRIGGERS
---help--- ---help---
This option adds two LED triggers for packet receive and transmit This option adds two LED triggers for packet receive and transmit
......
...@@ -959,7 +959,7 @@ struct kbd_led_trigger { ...@@ -959,7 +959,7 @@ struct kbd_led_trigger {
unsigned int mask; 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 = struct kbd_led_trigger *trigger =
container_of(cdev->trigger, 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) ...@@ -970,6 +970,8 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev)
ledstate & trigger->mask ? ledstate & trigger->mask ?
LED_FULL : LED_OFF); LED_FULL : LED_OFF);
tasklet_enable(&keyboard_tasklet); tasklet_enable(&keyboard_tasklet);
return 0;
} }
#define KBD_LED_TRIGGER(_led_bit, _name) { \ #define KBD_LED_TRIGGER(_led_bit, _name) { \
......
...@@ -113,11 +113,17 @@ static ssize_t usbport_trig_port_store(struct device *dev, ...@@ -113,11 +113,17 @@ static ssize_t usbport_trig_port_store(struct device *dev,
static struct attribute *ports_attrs[] = { static struct attribute *ports_attrs[] = {
NULL, NULL,
}; };
static const struct attribute_group ports_group = { static const struct attribute_group ports_group = {
.name = "ports", .name = "ports",
.attrs = ports_attrs, .attrs = ports_attrs,
}; };
static const struct attribute_group *ports_groups[] = {
&ports_group,
NULL
};
/*************************************** /***************************************
* Adding & removing ports * Adding & removing ports
***************************************/ ***************************************/
...@@ -298,61 +304,47 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action, ...@@ -298,61 +304,47 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action,
return NOTIFY_DONE; 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; struct usbport_trig_data *usbport_data;
int err;
usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL); usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL);
if (!usbport_data) if (!usbport_data)
return; return -ENOMEM;
usbport_data->led_cdev = led_cdev; usbport_data->led_cdev = led_cdev;
/* List of ports */ /* List of ports */
INIT_LIST_HEAD(&usbport_data->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); usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
usbport_trig_update_count(usbport_data); usbport_trig_update_count(usbport_data);
/* Notifications */ /* Notifications */
usbport_data->nb.notifier_call = usbport_trig_notify, usbport_data->nb.notifier_call = usbport_trig_notify;
led_cdev->trigger_data = usbport_data; led_set_trigger_data(led_cdev, usbport_data);
usb_register_notify(&usbport_data->nb); usb_register_notify(&usbport_data->nb);
led_cdev->activated = true; return 0;
return;
err_free:
kfree(usbport_data);
} }
static void usbport_trig_deactivate(struct led_classdev *led_cdev) 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; struct usbport_trig_port *port, *tmp;
if (!led_cdev->activated)
return;
list_for_each_entry_safe(port, tmp, &usbport_data->ports, list) { list_for_each_entry_safe(port, tmp, &usbport_data->ports, list) {
usbport_trig_remove_port(usbport_data, port); usbport_trig_remove_port(usbport_data, port);
} }
usb_unregister_notify(&usbport_data->nb); usb_unregister_notify(&usbport_data->nb);
sysfs_remove_group(&led_cdev->dev->kobj, &ports_group);
kfree(usbport_data); kfree(usbport_data);
led_cdev->activated = false;
} }
static struct led_trigger usbport_led_trigger = { static struct led_trigger usbport_led_trigger = {
.name = "usbport", .name = "usbport",
.activate = usbport_trig_activate, .activate = usbport_trig_activate,
.deactivate = usbport_trig_deactivate, .deactivate = usbport_trig_deactivate,
.groups = ports_groups,
}; };
static int __init usbport_trig_init(void) static int __init usbport_trig_init(void)
......
...@@ -253,7 +253,7 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) ...@@ -253,7 +253,7 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev)
struct led_trigger { struct led_trigger {
/* Trigger Properties */ /* Trigger Properties */
const char *name; const char *name;
void (*activate)(struct led_classdev *led_cdev); int (*activate)(struct led_classdev *led_cdev);
void (*deactivate)(struct led_classdev *led_cdev); void (*deactivate)(struct led_classdev *led_cdev);
/* LEDs under control by this trigger (for simple triggers) */ /* LEDs under control by this trigger (for simple triggers) */
...@@ -262,8 +262,19 @@ struct led_trigger { ...@@ -262,8 +262,19 @@ struct led_trigger {
/* Link to next registered trigger */ /* Link to next registered trigger */
struct list_head next_trig; 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, ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count); const char *buf, size_t count);
ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
...@@ -288,10 +299,16 @@ extern void led_trigger_blink_oneshot(struct led_trigger *trigger, ...@@ -288,10 +299,16 @@ extern void led_trigger_blink_oneshot(struct led_trigger *trigger,
unsigned long *delay_off, unsigned long *delay_off,
int invert); int invert);
extern void led_trigger_set_default(struct led_classdev *led_cdev); extern void led_trigger_set_default(struct led_classdev *led_cdev);
extern void led_trigger_set(struct led_classdev *led_cdev, extern int led_trigger_set(struct led_classdev *led_cdev,
struct led_trigger *trigger); struct led_trigger *trigger);
extern void led_trigger_remove(struct led_classdev *led_cdev); 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) static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
{ {
return led_cdev->trigger_data; return led_cdev->trigger_data;
...@@ -315,6 +332,10 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev) ...@@ -315,6 +332,10 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
extern void led_trigger_rename_static(const char *name, extern void led_trigger_rename_static(const char *name,
struct led_trigger *trig); struct led_trigger *trig);
#define module_led_trigger(__led_trigger) \
module_driver(__led_trigger, led_trigger_register, \
led_trigger_unregister)
#else #else
/* Trigger has no members */ /* Trigger has no members */
...@@ -334,9 +355,14 @@ static inline void led_trigger_blink_oneshot(struct led_trigger *trigger, ...@@ -334,9 +355,14 @@ static inline void led_trigger_blink_oneshot(struct led_trigger *trigger,
unsigned long *delay_off, unsigned long *delay_off,
int invert) {} int invert) {}
static inline void led_trigger_set_default(struct led_classdev *led_cdev) {} static inline void led_trigger_set_default(struct led_classdev *led_cdev) {}
static inline void led_trigger_set(struct led_classdev *led_cdev, static inline int led_trigger_set(struct led_classdev *led_cdev,
struct led_trigger *trigger) {} struct led_trigger *trigger)
{
return 0;
}
static inline void led_trigger_remove(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) static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
{ {
return NULL; return NULL;
......
...@@ -43,7 +43,7 @@ void hci_leds_update_powered(struct hci_dev *hdev, bool enabled) ...@@ -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); 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; struct hci_basic_led_trigger *htrig;
bool powered; bool powered;
...@@ -52,10 +52,12 @@ static void power_activate(struct led_classdev *led_cdev) ...@@ -52,10 +52,12 @@ static void power_activate(struct led_classdev *led_cdev)
powered = test_bit(HCI_UP, &htrig->hdev->flags); powered = test_bit(HCI_UP, &htrig->hdev->flags);
led_trigger_event(led_cdev->trigger, powered ? LED_FULL : LED_OFF); led_trigger_event(led_cdev->trigger, powered ? LED_FULL : LED_OFF);
return 0;
} }
static struct led_trigger *led_allocate_basic(struct hci_dev *hdev, 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) const char *name)
{ {
struct hci_basic_led_trigger *htrig; struct hci_basic_led_trigger *htrig;
......
...@@ -52,13 +52,15 @@ void ieee80211_free_led_names(struct ieee80211_local *local) ...@@ -52,13 +52,15 @@ void ieee80211_free_led_names(struct ieee80211_local *local)
kfree(local->radio_led.name); 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 *local = container_of(led_cdev->trigger,
struct ieee80211_local, struct ieee80211_local,
tx_led); tx_led);
atomic_inc(&local->tx_led_active); atomic_inc(&local->tx_led_active);
return 0;
} }
static void ieee80211_tx_led_deactivate(struct led_classdev *led_cdev) 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) ...@@ -70,13 +72,15 @@ static void ieee80211_tx_led_deactivate(struct led_classdev *led_cdev)
atomic_dec(&local->tx_led_active); 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 *local = container_of(led_cdev->trigger,
struct ieee80211_local, struct ieee80211_local,
rx_led); rx_led);
atomic_inc(&local->rx_led_active); atomic_inc(&local->rx_led_active);
return 0;
} }
static void ieee80211_rx_led_deactivate(struct led_classdev *led_cdev) 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) ...@@ -88,13 +92,15 @@ static void ieee80211_rx_led_deactivate(struct led_classdev *led_cdev)
atomic_dec(&local->rx_led_active); 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 *local = container_of(led_cdev->trigger,
struct ieee80211_local, struct ieee80211_local,
assoc_led); assoc_led);
atomic_inc(&local->assoc_led_active); atomic_inc(&local->assoc_led_active);
return 0;
} }
static void ieee80211_assoc_led_deactivate(struct led_classdev *led_cdev) 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) ...@@ -106,13 +112,15 @@ static void ieee80211_assoc_led_deactivate(struct led_classdev *led_cdev)
atomic_dec(&local->assoc_led_active); 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 *local = container_of(led_cdev->trigger,
struct ieee80211_local, struct ieee80211_local,
radio_led); radio_led);
atomic_inc(&local->radio_led_active); atomic_inc(&local->radio_led_active);
return 0;
} }
static void ieee80211_radio_led_deactivate(struct led_classdev *led_cdev) 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) ...@@ -124,13 +132,15 @@ static void ieee80211_radio_led_deactivate(struct led_classdev *led_cdev)
atomic_dec(&local->radio_led_active); 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 *local = container_of(led_cdev->trigger,
struct ieee80211_local, struct ieee80211_local,
tpt_led); tpt_led);
atomic_inc(&local->tpt_led_active); atomic_inc(&local->tpt_led_active);
return 0;
} }
static void ieee80211_tpt_led_deactivate(struct led_classdev *led_cdev) static void ieee80211_tpt_led_deactivate(struct led_classdev *led_cdev)
......
...@@ -141,13 +141,15 @@ static void rfkill_led_trigger_event(struct rfkill *rfkill) ...@@ -141,13 +141,15 @@ static void rfkill_led_trigger_event(struct rfkill *rfkill)
led_trigger_event(trigger, LED_FULL); 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; struct rfkill *rfkill;
rfkill = container_of(led->trigger, struct rfkill, led_trigger); rfkill = container_of(led->trigger, struct rfkill, led_trigger);
rfkill_led_trigger_event(rfkill); rfkill_led_trigger_event(rfkill);
return 0;
} }
const char *rfkill_get_led_trigger_name(struct rfkill *rfkill) const char *rfkill_get_led_trigger_name(struct rfkill *rfkill)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment