diff options
author | Andrey Smirnov <andrew.smirnov@gmail.com> | 2018-04-12 14:33:17 -0700 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2018-04-17 09:21:10 +0200 |
commit | 0f73d8fb36ec9b51cea9f78aa66a138b4a361cd0 (patch) | |
tree | 141a0a34cf15915200acce596663f49fc720b5c7 | |
parent | 25cb29b1357d5005de3e149744a2ebee03a743bf (diff) | |
download | barebox-0f73d8fb36ec9b51cea9f78aa66a138b4a361cd0.tar.gz barebox-0f73d8fb36ec9b51cea9f78aa66a138b4a361cd0.tar.xz |
serdev: Allow polling interval to be adjusted at runtime
Due to blocking, synchronous, polling driven nature of Barebox's
serial communication handling trying to use two or more serial ports
at high (1Mbaud+) baudrates results in data loss and noticeable
perofmance degradation. This happens as soon as individual message
being sent around start exceeding HW Rx FIFO in size.
A good example of such a usecase would be using a system that has a
serdev driver (operating @ 1Mbaud+) and trying to do a X/YMODEM
transfer via serial console at comparable baudrates.
To at least partially ameliorate the problem, add code that will
expose "polling_interval" as a parameter, so that the user would have
an option of temporarily disabling (or significatly decreasing the
rate) of a given serdev's polling.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | common/serdev.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/common/serdev.c b/common/serdev.c index 50eadc8040..4a6dbefe61 100644 --- a/common/serdev.c +++ b/common/serdev.c @@ -34,12 +34,26 @@ static void serdev_device_poller(void *context) serdev->polling_interval, serdev_device_poller, serdev); + } else { + poller_async_cancel(&serdev->poller); } } +static int serdev_device_set_polling_interval(struct param_d *param, void *serdev) +{ + /* + * We execute poller ever time polling_interval changes to get + * any unprocessed immediate Rx data as well as to propagate + * polling_interval chagnes to outstanging async pollers. + */ + serdev_device_poller(serdev); + return 0; +} + int serdev_device_open(struct serdev_device *serdev) { struct console_device *cdev = to_console_device(serdev); + struct param_d *p; int ret; if (!cdev->putc || !cdev->getc) @@ -57,7 +71,17 @@ int serdev_device_open(struct serdev_device *serdev) if (ret) return ret; - return console_open(cdev); + ret = console_open(cdev); + if (ret) + return ret; + + p = dev_add_param_uint64(serdev->dev, "polling_interval", + serdev_device_set_polling_interval, NULL, + &serdev->polling_interval, "%llu", serdev); + if (IS_ERR(p)) + return PTR_ERR(p); + + return 0; } unsigned int serdev_device_set_baudrate(struct serdev_device *serdev, |