Added file /sys/devices/.../tty/ttySX/uartclk to allow reading uartclk value in struct uart_port in serial_core via sysfs. tty_register_device() has been generalized and refactored in order to add support for setting drvdata and attribute_group to the device. Signed-off-by: Tomas Hlavacek <tmshlvck@xxxxxxxxx> --- Documentation/ABI/testing/sysfs-tty | 9 ++++++ drivers/tty/serial/serial_core.c | 36 ++++++++++++++++++++- drivers/tty/tty_io.c | 59 +++++++++++++++++++++++++++++++++-- include/linux/tty.h | 4 +++ 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty index b138b66..2f10855 100644 --- a/Documentation/ABI/testing/sysfs-tty +++ b/Documentation/ABI/testing/sysfs-tty @@ -17,3 +17,12 @@ Description: device, like 'tty1'. The file supports poll() to detect virtual console switches. + +What: /sys/class/tty/ttyS0/uartclk +Date: Sep 2012 +Contact: Tomas Hlavacek <tmshlvck@xxxxxxxxx> +Description: + Shows the current uartclk value associated with the + UART port in serial_core, that is bound to TTY like ttyS0. + uartclk = 16 * baud_base + diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index a21dc8e..ca64a93 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2293,6 +2293,37 @@ struct tty_driver *uart_console_device(struct console *co, int *index) return p->tty_driver; } +static ssize_t uart_get_attr_uartclk(struct device *dev, + struct device_attribute *attr, char *buf) +{ +int ret; + +struct tty_port *port = dev_get_drvdata(dev); +struct uart_state *state = container_of(port, struct uart_state, port); +mutex_lock(&state->port.mutex); +ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk); +mutex_unlock(&state->port.mutex); + +return ret; +} + +static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, + NULL); + +static struct attribute *tty_dev_attrs[] = { + &dev_attr_uartclk.attr, + NULL, + }; + +static struct attribute_group tty_dev_attr_group = { + .attrs = tty_dev_attrs, +}; + +static const struct attribute_group *tty_dev_attr_groups[] = { + &tty_dev_attr_group, + NULL + }; + /** * uart_add_one_port - attach a driver-defined port structure * @drv: pointer to the uart low level driver structure for this port @@ -2345,8 +2376,11 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) /* * Register the port whether it's detected or not. This allows * setserial to be used to alter this ports parameters. + * Use driverdata of the tty device for referencing the UART port. + * Set default device attributes to the new device. */ - tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev); + tty_dev = tty_register_device_attr(drv->tty_driver, uport->line, + uport->dev, port, tty_dev_attr_groups); if (likely(!IS_ERR(tty_dev))) { device_set_wakeup_capable(tty_dev, 1); } else { diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b425c79..befa99c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3013,8 +3013,39 @@ struct class *tty_class; struct device *tty_register_device(struct tty_driver *driver, unsigned index, struct device *device) { + return tty_register_device_attr(driver, index, device, NULL, NULL); +} +EXPORT_SYMBOL(tty_register_device); + +/** + * tty_register_device_attr - register a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device + * @device: a struct device that is associated with this tty device. + * This field is optional, if there is no known struct device + * for this tty device it can be set to NULL safely. + * @drvdata: Driver data to be set to device. + * @attr_grp: Attribute group to be set on device. + * + * Returns a pointer to the struct device for this tty device + * (or ERR_PTR(-EFOO) on error). + * + * This call is required to be made to register an individual tty device + * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If + * that bit is not set, this function should not be called by a tty + * driver. + * + * Locking: ?? + */ +struct device *tty_register_device_attr(struct tty_driver *driver, + unsigned index, struct device *device, + void *drvdata, + const struct attribute_group **attr_grp) +{ char name[64]; - dev_t dev = MKDEV(driver->major, driver->minor_start) + index; + struct device *dev = NULL; + int retval = -ENODEV; + dev_t devt = MKDEV(driver->major, driver->minor_start) + index; if (index >= driver->num) { printk(KERN_ERR "Attempt to register invalid tty line number " @@ -3027,9 +3058,31 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index, else tty_line_name(driver, index, name); - return device_create(tty_class, device, dev, NULL, name); + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + retval = -ENOMEM; + goto error; + } + + dev->devt = devt; + dev->class = tty_class; + dev->parent = device; + dev_set_name(dev, "%s", name); + dev->groups = attr_grp; + dev_set_drvdata(dev, drvdata); + + retval = device_register(dev); + if (retval) + goto error; + + return dev; + +error: + put_device(dev); + return ERR_PTR(retval); } -EXPORT_SYMBOL(tty_register_device); +EXPORT_SYMBOL_GPL(tty_register_device_attr); /** * tty_unregister_device - unregister a tty device diff --git a/include/linux/tty.h b/include/linux/tty.h index 9f47ab5..664252b 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -410,6 +410,10 @@ extern int tty_register_driver(struct tty_driver *driver); extern int tty_unregister_driver(struct tty_driver *driver); extern struct device *tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev); +extern struct device *tty_register_device_attr(struct tty_driver *driver, + unsigned index, struct device *device, + void *drvdata, + const struct attribute_group **attr_grp); extern void tty_unregister_device(struct tty_driver *driver, unsigned index); extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, int buflen); -- 1.7.10.4 -- 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