[rfc, rft, PATCH v1 3/3] serial: 8250_port: configure using of DMA channels runtime

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Provide an interface to 8250 driver to set DMA mode. It will be effective
for the transfers through the port next time it will be opened.

TBD: sysfs ABI documentation

Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
---
 Documentation/ABI/testing/sysfs-tty |  11 ++++
 drivers/tty/serial/8250/8250_port.c | 110 +++++++++++++++++++++++++++++++++++-
 2 files changed, 119 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index 9eb3c2b..1dd68c9 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -154,3 +154,14 @@ Description:
 		 device specification. For example, when user sets 7bytes on
 		 16550A, which has 1/4/8/14 bytes trigger, the RX trigger is
 		 automatically changed to 4 bytes.
+
+What:		/sys/class/tty/ttyS0/skip_rxdma
+What:		/sys/class/tty/ttyS0/skip_txdma
+Date:		September 2016
+Contact:	Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
+Description:
+		 Shows the current state of DMA use per channel or enforces PIO
+		 mode. Users can show this value regardless of opening the
+		 serial device file or not, though setting change is allowed
+		 only on closed device. The change will be effective as of next
+		 port opening.
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index a00f2c3..14bfd7b 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -2904,14 +2904,120 @@ static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
 		   serial8250_get_attr_rx_trig_bytes,
 		   serial8250_set_attr_rx_trig_bytes);
 
+static ssize_t serial8250_get_attr_skip_rxdma(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	struct tty_port *port = dev_get_drvdata(dev);
+	struct uart_state *state = container_of(port, struct uart_state, port);
+	struct uart_port *uport = state->uart_port;
+	bool skip_rxdma;
+
+	mutex_lock(&port->mutex);
+	skip_rxdma = !!(uport->quirks & UPQ_NO_DMA_RX);
+	mutex_unlock(&port->mutex);
+
+	return snprintf(buf, PAGE_SIZE, "%c\n", skip_rxdma ? 'Y' : 'N');
+}
+
+static ssize_t serial8250_set_attr_skip_rxdma(struct device *dev,
+					      struct device_attribute *attr,
+					      const char *buf, size_t count)
+{
+	struct tty_port *port = dev_get_drvdata(dev);
+	struct uart_state *state = container_of(port, struct uart_state, port);
+	struct uart_port *uport = state->uart_port;
+	struct uart_8250_port *up = up_to_u8250p(uport);
+	bool skip_rxdma;
+	int ret;
+
+	if (!up->dma)
+		return -ENODEV;
+
+	ret = kstrtobool(buf, &skip_rxdma);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&port->mutex);
+	if (up->dma->in_use)
+		count = -EBUSY;
+	else {
+		if (skip_rxdma)
+			uport->quirks |= UPQ_NO_DMA_RX;
+		else
+			uport->quirks &= ~UPQ_NO_DMA_RX;
+	}
+	mutex_unlock(&port->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(skip_rxdma, S_IRUSR | S_IWUSR | S_IRGRP,
+		   serial8250_get_attr_skip_rxdma,
+		   serial8250_set_attr_skip_rxdma);
+
+static ssize_t serial8250_get_attr_skip_txdma(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	struct tty_port *port = dev_get_drvdata(dev);
+	struct uart_state *state = container_of(port, struct uart_state, port);
+	struct uart_port *uport = state->uart_port;
+	bool skip_txdma;
+
+	mutex_lock(&port->mutex);
+	skip_txdma = !!(uport->quirks & UPQ_NO_DMA_TX);
+	mutex_unlock(&port->mutex);
+
+	return snprintf(buf, PAGE_SIZE, "%c\n", skip_txdma ? 'Y' : 'N');
+}
+
+static ssize_t serial8250_set_attr_skip_txdma(struct device *dev,
+					      struct device_attribute *attr,
+					      const char *buf, size_t count)
+{
+	struct tty_port *port = dev_get_drvdata(dev);
+	struct uart_state *state = container_of(port, struct uart_state, port);
+	struct uart_port *uport = state->uart_port;
+	struct uart_8250_port *up = up_to_u8250p(uport);
+	bool skip_txdma;
+	int ret;
+
+	if (!up->dma)
+		return -ENODEV;
+
+	ret = kstrtobool(buf, &skip_txdma);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&port->mutex);
+	if (up->dma->in_use)
+		count = -EBUSY;
+	else {
+		if (skip_txdma)
+			uport->quirks |= UPQ_NO_DMA_TX;
+		else
+			uport->quirks &= ~UPQ_NO_DMA_TX;
+	}
+	mutex_unlock(&port->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(skip_txdma, S_IRUSR | S_IWUSR | S_IRGRP,
+		   serial8250_get_attr_skip_txdma,
+		   serial8250_set_attr_skip_txdma);
+
 static struct attribute *serial8250_dev_attrs[] = {
 	&dev_attr_rx_trig_bytes.attr,
+	&dev_attr_skip_rxdma.attr,
+	&dev_attr_skip_txdma.attr,
 	NULL,
-	};
+};
 
 static struct attribute_group serial8250_dev_attr_group = {
 	.attrs = serial8250_dev_attrs,
-	};
+};
 
 static void register_dev_spec_attr_grp(struct uart_8250_port *up)
 {
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux