Not all triggers use LED_INIT_DEFAULT_TRIGGER, which means that it
will not get cleared when the default trigger is a trigger which
does not use it such as "default-on".
If the default trigger then later gets replaced by a trigger which
does check LED_INIT_DEFAULT_TRIGGER, such as "timer" then that trigger
will behave as if it is the default trigger which it should not do.
To fix this clear the LED_INIT_DEFAULT_TRIGGER flag when clearing
the current trigger, so that it will not be set for any subsequently
set (non default) triggers.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Tested-by: Yauhen Kharuzhy <jekhor@gmail.com>
Link: https://lore.kernel.org/r/20230510162234.291439-5-hdegoede@redhat.com
Signed-off-by: Lee Jones <lee@kernel.org>
led_trigger_blink() calls led_blink_set() from a RCU read-side critical
section so led_blink_set() must not sleep. Note sleeping was not allowed
before the switch to RCU either because a spinlock was held before.
led_blink_set() does not sleep when sw-blinking is used, but
many LED controller drivers with hw blink support have a blink_set
function which may sleep, leading to an oops like this one:
[ 832.605062] ------------[ cut here ]------------
[ 832.605085] Voluntary context switch within RCU read-side critical section!
[ 832.605119] WARNING: CPU: 2 PID: 370 at kernel/rcu/tree_plugin.h:318 rcu_note_context_switch+0x4ee/0x690
<snip>
[ 832.606453] Call Trace:
[ 832.606466] <TASK>
[ 832.606487] __schedule+0x9f/0x1480
[ 832.606527] schedule+0x5d/0xe0
[ 832.606549] schedule_timeout+0x79/0x140
[ 832.606572] ? __pfx_process_timeout+0x10/0x10
[ 832.606599] wait_for_completion_timeout+0x6f/0x140
[ 832.606627] i2c_dw_xfer+0x101/0x460
[ 832.606659] ? psi_group_change+0x168/0x400
[ 832.606680] __i2c_transfer+0x172/0x6d0
[ 832.606709] i2c_smbus_xfer_emulated+0x27d/0x9c0
[ 832.606732] ? __schedule+0x430/0x1480
[ 832.606753] ? preempt_count_add+0x6a/0xa0
[ 832.606778] ? get_nohz_timer_target+0x18/0x190
[ 832.606796] ? lock_timer_base+0x61/0x80
[ 832.606817] ? preempt_count_add+0x6a/0xa0
[ 832.606842] __i2c_smbus_xfer+0xa2/0x3f0
[ 832.606862] i2c_smbus_xfer+0x66/0xf0
[ 832.606882] i2c_smbus_read_byte_data+0x41/0x70
[ 832.606901] ? _raw_spin_unlock_irqrestore+0x23/0x40
[ 832.606922] ? __pm_runtime_suspend+0x46/0xc0
[ 832.606946] cht_wc_byte_reg_read+0x2e/0x60
[ 832.606972] _regmap_read+0x5c/0x120
[ 832.606997] _regmap_update_bits+0x96/0xc0
[ 832.607023] regmap_update_bits_base+0x5b/0x90
[ 832.607053] cht_wc_leds_brightness_get+0x412/0x910 [leds_cht_wcove]
[ 832.607094] led_blink_setup+0x28/0x100
[ 832.607119] led_trigger_blink+0x40/0x70
[ 832.607145] power_supply_update_leds+0x1b7/0x1c0
[ 832.607174] power_supply_changed_work+0x67/0xe0
[ 832.607198] process_one_work+0x1c8/0x3c0
[ 832.607222] worker_thread+0x4d/0x380
[ 832.607243] ? __pfx_worker_thread+0x10/0x10
[ 832.607258] kthread+0xe9/0x110
[ 832.607279] ? __pfx_kthread+0x10/0x10
[ 832.607300] ret_from_fork+0x2c/0x50
[ 832.607337] </TASK>
[ 832.607344] ---[ end trace 0000000000000000 ]---
Add a new led_blink_set_nosleep() function which defers the actual
led_blink_set() call to a workqueue when necessary to fix this.
This also fixes an existing race where a pending led_set_brightness() has
been deferred to set_brightness_work and might then race with a later
led_cdev->blink_set() call. Note this race is only an issue with triggers
mixing led_trigger_event() and led_trigger_blink() calls, sysfs API
calls and led_trigger_blink_oneshot() are not affected.
Note rather then adding a separate blink_set_blocking callback this uses
the presence of the already existing brightness_set_blocking callback to
detect if the blinking call should be deferred to set_brightness_work.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Tested-by: Yauhen Kharuzhy <jekhor@gmail.com>
Link: https://lore.kernel.org/r/20230510162234.291439-4-hdegoede@redhat.com
Signed-off-by: Lee Jones <lee@kernel.org>
When a trigger wants to switch from blinking to LED on it needs to call:
led_set_brightness(LED_OFF);
led_set_brightness(LED_FULL);
To first call disables blinking and the second then turns the LED on
(the power-supply charging-blink-full-solid triggers do this).
These calls happen immediately after each other, so it is possible
that set_brightness_delayed() from the first call has not run yet
when the led_set_brightness(LED_FULL) call finishes.
If this race hits then this is causing problems for both
sw- and hw-blinking:
For sw-blinking set_brightness_delayed() clears delayed_set_value
when LED_BLINK_DISABLE is set causing the led_set_brightness(LED_FULL)
call effects to get lost when hitting the race, resulting in the LED
turning off instead of on.
For hw-blinking if the race hits delayed_set_value has been
set to LED_FULL by the time set_brightness_delayed() runs.
So led_cdev->brightness_set_blocking() is never called with
LED_OFF as argument and the hw-blinking is never disabled leaving
the LED blinking instead of on.
Fix both issues by adding LED_SET_BRIGHTNESS and LED_SET_BRIGHTNESS_OFF
work_flags making this 2 separate actions to be run by
set_brightness_delayed().
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Tested-by: Yauhen Kharuzhy <jekhor@gmail.com>
Link: https://lore.kernel.org/r/20230510162234.291439-3-hdegoede@redhat.com
Signed-off-by: Lee Jones <lee@kernel.org>
led_blink_set[_oneshot]()'s delay_on and delay_off function parameters
are pass by reference, so that hw-blink implementations can report
back the actual achieved delays when the values have been rounded
to something the hw supports.
This is really only interesting for the sysfs API / the timer trigger.
Other triggers don't really care about this and none of the callers of
led_trigger_blink[_oneshot]() do anything with the returned delay values.
Change the led_trigger_blink[_oneshot]() delay parameters to pass-by-value,
there are 2 reasons for this:
1. led_cdev->blink_set() may sleep, while led_trigger_blink() may not.
So on hw where led_cdev->blink_set() sleeps the call needs to be deferred
to a workqueue, in which case the actual achieved delays are unknown
(this is a preparation patch for the deferring).
2. Since the callers don't care about the actual achieved delays, allowing
callers to directly pass a value leads to simpler code for most callers.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Tested-by: Yauhen Kharuzhy <jekhor@gmail.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Acked-by: Florian Westphal <fw@strlen.de>
Link: https://lore.kernel.org/r/20230510162234.291439-2-hdegoede@redhat.com
Signed-off-by: Lee Jones <lee@kernel.org>
Currently, LEDS_LM3697 and LEDS_LM36274 depend on LEDS_TI_LMU_COMMON,
which contains the common code to support TI LMU devices. This means
the user is asked about the common code first, followed by the
individual drivers, if their dependencies are met.
Simplify this, and reduce the number of questions by making
LEDS_TI_LMU_COMMON invisible, and letting it be selected when needed.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Pavel Machek <pavel@ucw.cz>
Link: https://lore.kernel.org/r/91f6efaa48c36320e58b6a312025ae9b39ee206b.1683644796.git.geert+renesas@glider.be
Signed-off-by: Lee Jones <lee@kernel.org>
The desired default behavior of LED1 / the charge LED is breathing
while charging and on/solid when full. Since triggers cannot select
breathing, blink_set() gets called when charging. Use breathing
when the default "charging-blink-full-solid" trigger is used to
achieve the desired default behavior.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20230430195952.862527-6-hdegoede@redhat.com
Signed-off-by: Lee Jones <lee@kernel.org>
The hw-blinking of the LED controller in the Whiskey Cove PMIC can also
be used for a hw-breathing effect.
As discussed during review of v2 of the submission of the new
leds-cht-wcove driver, the LED subsystem already supports breathing mode
on several other LED controllers using the hw_pattern interface.
Implement a pattern_set callback to implement breathing mode modelled
after the breathing mode supported by the SC27xx breathing light and
Crane EL15203000 LED drivers. The Whiskey Cove PMIC's breathing mode
is closer to the EL15203000 one then to the SC27xx one since it does
not support staying high / low for a specific time, it only supports
rise and fall times.
As such the supported hw_pattern and the documentation for this is almost
a 1:1 copy of the pattern/docs for the EL15203000 breathing mode.
Suggested-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Link: https://lore.kernel.org/all/6beed61c-1fc6-6525-e873-a8978f5fbffb@gmail.com/
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20230430195952.862527-4-hdegoede@redhat.com
Signed-off-by: Lee Jones <lee@kernel.org>
When LED1 is showing the tablet is charging and then the device gets
suspended followed by unplugging the charger, then it will incorrectly
still show it is charging.
To avoid this turn both LEDs off on suspend, just like the PMIC always
turns them off when the tablet is powered off (even if the tablet is
charging). If hw-control is supported for LED1, then restore the
initial hw-control settings to let the hw control LED1 while suspended.
To restore the state the LEDs had before suspending, save it before
turning the LEDs off and restore it on resume.
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20230430195952.862527-3-hdegoede@redhat.com
Signed-off-by: Lee Jones <lee@kernel.org>
Add support for LEDs connected to the Intel Cherry Trail Whiskey Cove
PMIC. Charger and general-purpose LEDs are supported. Hardware blinking
is implemented, breathing is not.
This driver was tested with Lenovo Yoga Book notebook.
Changes by Hans de Goede (in response to review of v2):
- Since the PMIC is connected to the battery any changes we make to
the LED settings are permanent, even surviving reboot / poweroff.
Save LED1 register settings on probe() and if auto-/hw-control was
enabled on probe() restore the settings on remove() and shutdown().
- Delay switching LED1 to software control mode to first brightness write.
- Use dynamically allocated drvdata instead of a global drvdata variable.
- Ensure the LED is on when activating blinking.
- Fix CHT_WC_LED_EFF_BREATHING val ((3 << 1) rather then BIT(3)).
Link: https://lore.kernel.org/r/20190212205901.13037-2-jekhor@gmail.com
Signed-off-by: Yauhen Kharuzhy <jekhor@gmail.com>
Co-developed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20230430195952.862527-2-hdegoede@redhat.com
Signed-off-by: Lee Jones <lee@kernel.org>
Commit e91a4d5deb ("dt-bindings: leds: Document commonly used
LED triggers") introduced a enum match for cpu, while a pattern
'^cpu[0-9]*$' already exists.
This causes linux,default-trigger = "cpu" to have more than one match
and generates the following dtbs_check warning:
arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dtb: leds: led-2:linux,default-trigger: More than one condition true in oneOf schema:
{'$ref': '/schemas/types.yaml#/definitions/string',
'oneOf': [{'items': [{'enum': ['backlight',
'default-on',
'heartbeat',
'disk-activity',
'disk-read',
'disk-write',
'timer',
'pattern',
'audio-micmute',
'audio-mute',
'bluetooth-power',
'cpu',
'flash',
'kbd-capslock',
'mtd',
'nand-disk',
'none',
'torch',
'usb-gadget',
'usb-host',
'usbport']}],
'maxItems': 1,
'minItems': 1,
'type': 'array'},
{'items': [{'pattern': '^cpu[0-9]*$'}],
'maxItems': 1,
'minItems': 1,
'type': 'array'},
{'items': [{'pattern': '^hci[0-9]+-power$'}],
'maxItems': 1,
'minItems': 1,
'type': 'array'},
{'items': [{'pattern': '^mmc[0-9]+$'}],
'maxItems': 1,
'minItems': 1,
'type': 'array'},
{'items': [{'pattern': '^phy[0-9]+tx$'}],
'maxItems': 1,
'minItems': 1,
'type': 'array'}]}
Drop the explicit match against cpu since the pattern match already
covers the same.
Fixes: e91a4d5deb ("dt-bindings: leds: Document commonly used LED triggers")
Signed-off-by: Nishanth Menon <nm@ti.com>
Acked-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Lee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20230424151437.256073-1-nm@ti.com
The LP55xx range of devices have an internal charge pump which
can (automatically) increase the output voltage towards the
LED's, boosting the output voltage to 4.5V.
Implement this option from the devicetree. When the setting
is not present it will operate in automatic mode as before.
Tested on LP55231. Datasheet analysis shows that LP5521, LP5523
and LP8501 are identical in topology and are modified in the
same way.
Signed-off-by: Maarten Zanders <maarten.zanders@mind.be>
Signed-off-by: Lee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20230421075305.37597-3-maarten.zanders@mind.be
Some LEDs may require to sleep while doing some operation like setting
brightness and other cleanup.
For this reason, using a spinlock will cause a sleep under spinlock
warning.
It should be safe to convert this to a sleepable lock since:
- sysfs read/write can sleep
- netdev_trig_work is a work queue and can sleep
- netdev _trig_notify can sleep
The spinlock was used when brightness didn't support sleeping, but this
changed and now it supported with brightness_set_blocking().
Convert to mutex lock to permit sleeping using brightness_set_blocking().
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Lee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20230419210743.3594-6-ansuelsmth@gmail.com
Putting NETDEV_LED_MODE_LINKUP in the same list of the netdev trigger
modes is wrong as it's used to set the link state of the device and not
to set a blink mode as it's done by NETDEV_LED_LINK, NETDEV_LED_TX and
NETDEV_LED_RX. It's also wrong to put this state in the same bitmap of the
netdev trigger mode and should be external to it.
Drop NETDEV_LED_MODE_LINKUP from mode list and convert to a simple bool
that will be true or false based on the carrier link. No functional
change intended.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Lee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20230419210743.3594-3-ansuelsmth@gmail.com