summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Smirnov <andrew.smirnov@gmail.com>2018-04-12 14:33:17 -0700
committerSascha Hauer <s.hauer@pengutronix.de>2018-04-17 09:21:10 +0200
commit0f73d8fb36ec9b51cea9f78aa66a138b4a361cd0 (patch)
tree141a0a34cf15915200acce596663f49fc720b5c7
parent25cb29b1357d5005de3e149744a2ebee03a743bf (diff)
downloadbarebox-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.c26
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,