On Wed, Sep 19, 2018 at 07:16:12AM -1000, Steve Sakoman wrote: > Add a "pps_4wire" file to serial ports in sysfs in case the kernel is > configured with CONFIG_PPS_CLIENT_LDISC. Writing 1 to the file enables > the use of CTS instead of DCD for PPS signal input. This is necessary > in case a serial port is not completely wired. > Though this affects PPS processing the patch is against the serial core > as the source of the serial port PPS event dispatching has to be > modified. Furthermore it should be possible to modify the source of > serial port PPS event dispatching before changing the line discipline. > > Signed-off-by: Andreas Steinmetz <ast@xxxxxxxx> > Signed-off-by: Steve Sakoman <steve@xxxxxxxxxxx> > Tested-by: Steve Sakoman <steve@xxxxxxxxxxx> > --- > Documentation/ABI/testing/sysfs-tty | 9 +++++ > drivers/tty/serial/serial_core.c | 71 ++++++++++++++++++++++++++++++++++++- > include/linux/serial_core.h | 3 +- > 3 files changed, 81 insertions(+), 2 deletions(-) > > diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty > index 9eb3c2b..441105a 100644 > --- a/Documentation/ABI/testing/sysfs-tty > +++ b/Documentation/ABI/testing/sysfs-tty > @@ -154,3 +154,12 @@ 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/pps_4wire > +Date: September 2018 > +Contact: Steve Sakoman <steve@xxxxxxxxxxx> > +Description: > + Shows/sets "4 wire" mode for the PPS input to the serial driver. > + For fully implemented serial ports PPS is normally provided > + on the DCD line. For partial "4 wire" implementations CTS is > + used instead of DCD. > diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c > index 80bb56f..5839bed 100644 > --- a/drivers/tty/serial/serial_core.c > +++ b/drivers/tty/serial/serial_core.c > @@ -2664,6 +2664,56 @@ static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev, > return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift); > } > > +static ssize_t uart_get_attr_pps_4wire(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; > + int mode = 0; > + > + mutex_lock(&port->mutex); > + uport = uart_port_check(state); > + if (!uport) > + goto out; > + > + mode = uport->pps_4wire; > + > +out: > + mutex_unlock(&port->mutex); > + return snprintf(buf, PAGE_SIZE, mode ? "yes" : "no"); No need to care about the size of the buffer when only dealing with a single page. sprintf() is fine here. > +} > + > +static ssize_t uart_set_attr_pps_4wire(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; > + bool mode; > + int ret; > + > + if (!count) > + return -EINVAL; > + > + ret = kstrtobool(buf, &mode); > + if (ret < 0) > + return ret; > + > + mutex_lock(&port->mutex); > + uport = uart_port_check(state); > + if (!uport) > + goto out; > + > + spin_lock_irq(&uport->lock); > + uport->pps_4wire = mode; > + spin_unlock_irq(&uport->lock); > + > +out: > + mutex_unlock(&port->mutex); > + return count; > +} > + > static DEVICE_ATTR(type, S_IRUSR | S_IRGRP, uart_get_attr_type, NULL); > static DEVICE_ATTR(line, S_IRUSR | S_IRGRP, uart_get_attr_line, NULL); > static DEVICE_ATTR(port, S_IRUSR | S_IRGRP, uart_get_attr_port, NULL); > @@ -2677,6 +2727,8 @@ static DEVICE_ATTR(custom_divisor, S_IRUSR | S_IRGRP, uart_get_attr_custom_divis > static DEVICE_ATTR(io_type, S_IRUSR | S_IRGRP, uart_get_attr_io_type, NULL); > static DEVICE_ATTR(iomem_base, S_IRUSR | S_IRGRP, uart_get_attr_iomem_base, NULL); > static DEVICE_ATTR(iomem_reg_shift, S_IRUSR | S_IRGRP, uart_get_attr_iomem_reg_shift, NULL); > +static DEVICE_ATTR(pps_4wire, S_IRUSR | S_IWUSR | S_IRGRP, > + uart_get_attr_pps_4wire, uart_set_attr_pps_4wire); DEVICE_ATTR_RW()? All of these should get fixed up eventually as well, but let's not add to the bad style if possible :) Also, it's good to use the output of scripts/get_maintainer.pl to figure out who to cc: for patch review. thanks, greg k-h