From 0f73d8fb36ec9b51cea9f78aa66a138b4a361cd0 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Thu, 12 Apr 2018 14:33:17 -0700 Subject: 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 Signed-off-by: Sascha Hauer --- common/serdev.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'common/serdev.c') 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, -- cgit v1.2.3