leds: wago-m4: eliminate boot delay by polling rproc with short interval
The previous approach tried to peek at the rproc state in probe() to decide whether to use delay=0 (SPL path) or 5000ms (Linux-boot path). This did not work because the remoteproc subsystem registers the rproc device ~140ms after the LED driver probes, so rproc_get_by_phandle() always returned NULL at probe() time and the 5000ms delay was always used. New approach: - Schedule boot_work with delay=0 unconditionally from probe(). - Reduce WAGO_BOOT_RETRY_MS from 2000ms to 200ms so the rproc handle is found within one retry after it becomes available (~200ms total). - Increase WAGO_BOOT_MAX_RETRIES from 30 to 150 to keep the same total worst-case timeout (150 x 200ms = 30s for rproc polling). - For the Linux-boot path (-ENOENT, firmware file not found), switch directly to WAGO_BOOT_INITIAL_DELAY_MS (5000ms) per retry instead of the short rproc-poll interval to avoid hammering the filesystem. Expected boot timeline (SPL path): [0.797] probe() -> boot_work scheduled, delay=0 [0.797] boot_work #1 -> rproc not yet available, retry in 200ms [0.997] boot_work #2 -> rproc DETACHED, attach immediately [~1.0 ] RPMsg channel up -> LED strip active Signed-off-by: Heinrich Toews <ht@twx-software.de>
This commit is contained in:
@@ -108,12 +108,14 @@
|
||||
/* Maximum ASCII command length for sysfs passthrough */
|
||||
#define WAGO_CMD_MAX_LEN 32
|
||||
|
||||
/* First boot attempt this many ms after probe() */
|
||||
/* First boot attempt this many ms after probe() — Linux-boot path only,
|
||||
* gives the rootfs time to mount before loading firmware from /lib/firmware.
|
||||
* Not used in the SPL path (M4 already running). */
|
||||
#define WAGO_BOOT_INITIAL_DELAY_MS 5000
|
||||
/* Retry interval when filesystem is not yet available */
|
||||
#define WAGO_BOOT_RETRY_MS 2000
|
||||
/* Retry interval when rproc is not yet registered or firmware not found */
|
||||
#define WAGO_BOOT_RETRY_MS 200
|
||||
/* Maximum number of boot attempts before giving up */
|
||||
#define WAGO_BOOT_MAX_RETRIES 30
|
||||
#define WAGO_BOOT_MAX_RETRIES 150
|
||||
|
||||
/*
|
||||
* vring TX ring retry policy for rpmsg_trysend().
|
||||
@@ -716,12 +718,14 @@ static void wago_boot_work(struct work_struct *work)
|
||||
|
||||
/*
|
||||
* -ENOENT: firmware file not found — rootfs not yet mounted.
|
||||
* Retry after a short delay.
|
||||
* Switch to the longer retry interval for filesystem polling.
|
||||
*/
|
||||
if (ret == -ENOENT) {
|
||||
dev_dbg(dev, "Firmware not found yet, retrying in %d ms\n",
|
||||
WAGO_BOOT_RETRY_MS);
|
||||
goto retry;
|
||||
WAGO_BOOT_INITIAL_DELAY_MS);
|
||||
schedule_delayed_work(&priv->boot_work,
|
||||
msecs_to_jiffies(WAGO_BOOT_INITIAL_DELAY_MS));
|
||||
return;
|
||||
}
|
||||
|
||||
dev_err(dev, "rproc_boot failed: %d\n", ret);
|
||||
@@ -768,9 +772,7 @@ static void wago_rproc_stop(struct wago_m4_led_priv *priv)
|
||||
static int wago_m4_led_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wago_m4_led_priv *priv;
|
||||
struct device_node *rproc_np;
|
||||
const char *fw_name;
|
||||
unsigned long boot_delay_ms;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
@@ -822,41 +824,21 @@ static int wago_m4_led_probe(struct platform_device *pdev)
|
||||
#endif /* CONFIG_LEDS_WAGO_M4_WRAPPER_SYSFS_PASSTHROUGH */
|
||||
|
||||
/*
|
||||
* Determine boot delay:
|
||||
* Schedule boot_work immediately (delay=0).
|
||||
*
|
||||
* If the rproc is already available and in RPROC_DETACHED state
|
||||
* (U-Boot / SPL loaded the firmware), schedule boot_work immediately
|
||||
* so the RPMsg channel comes up as fast as possible.
|
||||
*
|
||||
* Otherwise use WAGO_BOOT_INITIAL_DELAY_MS to give the rootfs time
|
||||
* to mount before we try to load the firmware file.
|
||||
* boot_work polls for the rproc handle with WAGO_BOOT_RETRY_MS
|
||||
* intervals (200 ms). Once the rproc is registered by the remoteproc
|
||||
* subsystem it checks the state:
|
||||
* RPROC_DETACHED -> attach right away (SPL path, ~1 retry needed)
|
||||
* otherwise -> load firmware from /lib/firmware (Linux-boot path,
|
||||
* retries until rootfs is mounted)
|
||||
*/
|
||||
boot_delay_ms = WAGO_BOOT_INITIAL_DELAY_MS;
|
||||
rproc_np = of_parse_phandle(pdev->dev.of_node, "remoteproc", 0);
|
||||
if (rproc_np) {
|
||||
struct rproc *rp = rproc_get_by_phandle(rproc_np->phandle);
|
||||
|
||||
of_node_put(rproc_np);
|
||||
if (!IS_ERR_OR_NULL(rp)) {
|
||||
if (rp->state == RPROC_DETACHED) {
|
||||
boot_delay_ms = 0;
|
||||
dev_info(&pdev->dev,
|
||||
"M4 already running (SPL path), "
|
||||
"attaching immediately\n");
|
||||
}
|
||||
/* rproc_boot_work will re-acquire it lazily */
|
||||
rproc_put(rp);
|
||||
}
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&priv->boot_work, wago_boot_work);
|
||||
schedule_delayed_work(&priv->boot_work,
|
||||
msecs_to_jiffies(boot_delay_ms));
|
||||
schedule_delayed_work(&priv->boot_work, 0);
|
||||
|
||||
dev_info(&pdev->dev,
|
||||
"WAGO M4 LED wrapper probed, %d LEDs active, "
|
||||
"RPMsg attach in %lu ms\n",
|
||||
WAGO_LED_NUM_LEDS, boot_delay_ms);
|
||||
"WAGO M4 LED wrapper probed, %d LEDs active\n",
|
||||
WAGO_LED_NUM_LEDS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user