Re: [PATCH 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-16 Thread Alan Cox

> + /*
> +  * Check value: baud_base has to be more than 9600
> +  * and uartclock = baud_base * 16 .
> +  */
> + if (val >= 153600)
> + state->uart_port->uartclk = val;
> +
> + mutex_unlock(>port.mutex);
> +
> + return count;

This breaks if for example the port is in use. Fixing that looks pretty
horrible as you need a valid tty pointer to stop and restart the pot.

It's also not calling the verfy method of the port as is expected.

At minimum I think you need to be able to do the same work
uart_get_info/uart_set_info perform and with the same checks on ->verify
etc.

I'm not 100% sure the drvdata on the tty_dev is clear to use. It does
seem to be in all the drivers I looked at. I'd rather however it pointed
to the tty_port that each tty device has (or very soon will be required
to have). You can still find the uart_foo structs from that but it means
we can do the dev_set_drvdata() in a consistent manner for all tty
devices in the kernel. That in turn means we can make some of the sysfs
valid the same way.

I want to have think about the setting side of it. Can you submit a
revised version that just allows the user to read the value this way but
does the drvdata setting etc and sysfs node create/delete.

I'll merge that and we can throw it over the parapet and see if anything
explodes.

To make the setting part work properly I think I need to sort out
uart_get_info/set_info so the core part of it can be called with kernel
space structures and the caller handling locks.

Alan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-16 Thread Alan Cox

 + /*
 +  * Check value: baud_base has to be more than 9600
 +  * and uartclock = baud_base * 16 .
 +  */
 + if (val = 153600)
 + state-uart_port-uartclk = val;
 +
 + mutex_unlock(state-port.mutex);
 +
 + return count;

This breaks if for example the port is in use. Fixing that looks pretty
horrible as you need a valid tty pointer to stop and restart the pot.

It's also not calling the verfy method of the port as is expected.

At minimum I think you need to be able to do the same work
uart_get_info/uart_set_info perform and with the same checks on -verify
etc.

I'm not 100% sure the drvdata on the tty_dev is clear to use. It does
seem to be in all the drivers I looked at. I'd rather however it pointed
to the tty_port that each tty device has (or very soon will be required
to have). You can still find the uart_foo structs from that but it means
we can do the dev_set_drvdata() in a consistent manner for all tty
devices in the kernel. That in turn means we can make some of the sysfs
valid the same way.

I want to have think about the setting side of it. Can you submit a
revised version that just allows the user to read the value this way but
does the drvdata setting etc and sysfs node create/delete.

I'll merge that and we can throw it over the parapet and see if anything
explodes.

To make the setting part work properly I think I need to sort out
uart_get_info/set_info so the core part of it can be called with kernel
space structures and the caller handling locks.

Alan
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-15 Thread Tomas Hlavacek
Hello Marek,

On Tue, Aug 14, 2012 at 2:50 PM, Marek Vasut  wrote:
> Dear Tomas Hlavacek,
>
>> +static ssize_t get_attr_uartclk(struct device *dev,
>> + struct device_attribute *attr, char *buf)
>> +{
>> + int ret;
>> +
>> + struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));
>
> You don't need this cast here.

Yes, you are right. Thanks.

>
>> + mutex_lock(>port.mutex);
>> + ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
>
> Do you really need such a large buffer (PAGE_SIZE) ?

Well no, but I believe that I get the buffer of length equal to
PAGE_SIZE anyway. Documentation/filesystems/sysfs.txt says so on line
179.

>
>> + mutex_unlock(>port.mutex);
>> + return ret;
>> +}
>> +
>> +static ssize_t set_attr_uartclk(struct device *dev,
>> + struct device_attribute *attr, const char *buf, size_t count)
>> +{
>> + struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));
>> + unsigned int val;
>> + int ret;
>> +
>> + ret = kstrtouint(buf, 10, );
>> + if (ret)
>> + return ret;
>> +
>> + mutex_lock(>port.mutex);
>> +
>> + /*
>> +  * Check value: baud_base has to be more than 9600
>> +  * and uartclock = baud_base * 16 .
>> +  */
>> + if (val >= 153600)
>> + state->uart_port->uartclk = val;
>
> This magic value here would use some documentation.

OK. Do you think this would be sufficient comment?:

/*
 * Check value: baud_base does not make sense to be set below 9600
 * and since uartclock = (baud_base * 16) it has to be equal or greater than
 * 9600 * 16 = 153600.
 */

PATCHv2 follows.

Tomas


-- 
Tomáš Hlaváček 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-15 Thread Tomas Hlavacek
Hello Marek,

On Tue, Aug 14, 2012 at 2:50 PM, Marek Vasut marek.va...@gmail.com wrote:
 Dear Tomas Hlavacek,

 +static ssize_t get_attr_uartclk(struct device *dev,
 + struct device_attribute *attr, char *buf)
 +{
 + int ret;
 +
 + struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));

 You don't need this cast here.

Yes, you are right. Thanks.


 + mutex_lock(state-port.mutex);
 + ret = snprintf(buf, PAGE_SIZE, %d\n, state-uart_port-uartclk);

 Do you really need such a large buffer (PAGE_SIZE) ?

Well no, but I believe that I get the buffer of length equal to
PAGE_SIZE anyway. Documentation/filesystems/sysfs.txt says so on line
179.


 + mutex_unlock(state-port.mutex);
 + return ret;
 +}
 +
 +static ssize_t set_attr_uartclk(struct device *dev,
 + struct device_attribute *attr, const char *buf, size_t count)
 +{
 + struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));
 + unsigned int val;
 + int ret;
 +
 + ret = kstrtouint(buf, 10, val);
 + if (ret)
 + return ret;
 +
 + mutex_lock(state-port.mutex);
 +
 + /*
 +  * Check value: baud_base has to be more than 9600
 +  * and uartclock = baud_base * 16 .
 +  */
 + if (val = 153600)
 + state-uart_port-uartclk = val;

 This magic value here would use some documentation.

OK. Do you think this would be sufficient comment?:

/*
 * Check value: baud_base does not make sense to be set below 9600
 * and since uartclock = (baud_base * 16) it has to be equal or greater than
 * 9600 * 16 = 153600.
 */

PATCHv2 follows.

Tomas


-- 
Tomáš Hlaváček tmshl...@gmail.com
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-14 Thread Marek Vasut
Dear Tomas Hlavacek,

> Support for read/modify of uartclk via sysfs added.
> It may prove useful with some no-name cards that
> has different oscillator speeds and no distinguishing
> PCI IDs to allow autodetection. It allows better integration
> with udev and/or init scripts.
> 
> Signed-off-by: Tomas Hlavacek 
> ---
>  drivers/tty/serial/serial_core.c |   54
> ++ drivers/tty/tty_io.c | 
>  17 
>  include/linux/tty.h  |2 ++
>  3 files changed, 73 insertions(+)
> 
> diff --git a/drivers/tty/serial/serial_core.c
> b/drivers/tty/serial/serial_core.c index a21dc8e..059b438 100644
> --- a/drivers/tty/serial/serial_core.c
> +++ b/drivers/tty/serial/serial_core.c
> @@ -2293,6 +2293,46 @@ struct tty_driver *uart_console_device(struct
> console *co, int *index) return p->tty_driver;
>  }
> 
> +static ssize_t get_attr_uartclk(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + int ret;
> +
> + struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));

You don't need this cast here.

> + mutex_lock(>port.mutex);
> + ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);

Do you really need such a large buffer (PAGE_SIZE) ?

> + mutex_unlock(>port.mutex);
> + return ret;
> +}
> +
> +static ssize_t set_attr_uartclk(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t count)
> +{
> + struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));
> + unsigned int val;
> + int ret;
> +
> + ret = kstrtouint(buf, 10, );
> + if (ret)
> + return ret;
> +
> + mutex_lock(>port.mutex);
> +
> + /*
> +  * Check value: baud_base has to be more than 9600
> +  * and uartclock = baud_base * 16 .
> +  */
> + if (val >= 153600)
> + state->uart_port->uartclk = val;

This magic value here would use some documentation.

> + mutex_unlock(>port.mutex);
> +
> + return count;
> +}
> +
> +static DEVICE_ATTR(uartclk, S_IRUGO | S_IWUSR, get_attr_uartclk,
> + set_attr_uartclk);
> +
>  /**
>   *   uart_add_one_port - attach a driver-defined port structure
>   *   @drv: pointer to the uart low level driver structure for this port
> @@ -2355,6 +2395,14 @@ int uart_add_one_port(struct uart_driver *drv,
> struct uart_port *uport) }
> 
>   /*
> +  * Expose uartclk in sysfs. Use driverdata of the tty device for
> +  * referencing the UART port.
> +  */
> + dev_set_drvdata(tty_dev, state);
> + if (device_create_file(tty_dev, _attr_uartclk) < 0)
> + dev_err(tty_dev, "Failed to add uartclk attr\n");
> +
> + /*
>* Ensure UPF_DEAD is not set.
>*/
>   uport->flags &= ~UPF_DEAD;
> @@ -2397,6 +2445,12 @@ int uart_remove_one_port(struct uart_driver *drv,
> struct uart_port *uport) mutex_unlock(>mutex);
> 
>   /*
> +  * Remove uartclk file from sysfs.
> +  */
> + device_remove_file(tty_lookup_device(drv->tty_driver, uport->line),
> + _attr_uartclk);
> +
> + /*
>* Remove the devices from the tty layer
>*/
>   tty_unregister_device(drv->tty_driver, uport->line);
> diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
> index b425c79..8ea8622 100644
> --- a/drivers/tty/tty_io.c
> +++ b/drivers/tty/tty_io.c
> @@ -3049,6 +3049,23 @@ void tty_unregister_device(struct tty_driver
> *driver, unsigned index) }
>  EXPORT_SYMBOL(tty_unregister_device);
> 
> +/*
> + *   tty_lookup_device - lookup a tty device
> + *   @driver: the tty driver that describes the tty device
> + *   @index: the index in the tty driver for this tty device
> + *
> + *   This function returns a struct device pointer when device has
> + *   been found and NULL otherwise.
> + *
> + *   Locking: ??
> + */
> +struct device *tty_lookup_device(struct tty_driver *driver, unsigned
> index) +{
> + dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
> + return class_find_device(tty_class, NULL, , dev_match_devt);
> +}
> +EXPORT_SYMBOL(tty_lookup_device);
> +
>  struct tty_driver *__alloc_tty_driver(int lines, struct module *owner)
>  {
>   struct tty_driver *driver;
> diff --git a/include/linux/tty.h b/include/linux/tty.h
> index 9f47ab5..5d408a1 100644
> --- a/include/linux/tty.h
> +++ b/include/linux/tty.h
> @@ -410,6 +410,8 @@ 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_lookup_device(struct tty_driver *driver,
> + unsigned index);
>  extern void tty_unregister_device(struct tty_driver *driver, unsigned
> index); extern int tty_read_raw_data(struct tty_struct *tty, unsigned char
> 

[PATCH 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-14 Thread Tomas Hlavacek
Support for read/modify of uartclk via sysfs added.
It may prove useful with some no-name cards that
has different oscillator speeds and no distinguishing
PCI IDs to allow autodetection. It allows better integration
with udev and/or init scripts.

Signed-off-by: Tomas Hlavacek 
---
 drivers/tty/serial/serial_core.c |   54 ++
 drivers/tty/tty_io.c |   17 
 include/linux/tty.h  |2 ++
 3 files changed, 73 insertions(+)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a21dc8e..059b438 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2293,6 +2293,46 @@ struct tty_driver *uart_console_device(struct console 
*co, int *index)
return p->tty_driver;
 }
 
+static ssize_t get_attr_uartclk(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int ret;
+
+   struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));
+   mutex_lock(>port.mutex);
+   ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
+   mutex_unlock(>port.mutex);
+   return ret;
+}
+
+static ssize_t set_attr_uartclk(struct device *dev,
+   struct device_attribute *attr, const char *buf, size_t count)
+{
+   struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));
+   unsigned int val;
+   int ret;
+
+   ret = kstrtouint(buf, 10, );
+   if (ret)
+   return ret;
+
+   mutex_lock(>port.mutex);
+
+   /*
+* Check value: baud_base has to be more than 9600
+* and uartclock = baud_base * 16 .
+*/
+   if (val >= 153600)
+   state->uart_port->uartclk = val;
+
+   mutex_unlock(>port.mutex);
+
+   return count;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUGO | S_IWUSR, get_attr_uartclk,
+   set_attr_uartclk);
+
 /**
  * uart_add_one_port - attach a driver-defined port structure
  * @drv: pointer to the uart low level driver structure for this port
@@ -2355,6 +2395,14 @@ int uart_add_one_port(struct uart_driver *drv, struct 
uart_port *uport)
}
 
/*
+* Expose uartclk in sysfs. Use driverdata of the tty device for
+* referencing the UART port.
+*/
+   dev_set_drvdata(tty_dev, state);
+   if (device_create_file(tty_dev, _attr_uartclk) < 0)
+   dev_err(tty_dev, "Failed to add uartclk attr\n");
+
+   /*
 * Ensure UPF_DEAD is not set.
 */
uport->flags &= ~UPF_DEAD;
@@ -2397,6 +2445,12 @@ int uart_remove_one_port(struct uart_driver *drv, struct 
uart_port *uport)
mutex_unlock(>mutex);
 
/*
+* Remove uartclk file from sysfs.
+*/
+   device_remove_file(tty_lookup_device(drv->tty_driver, uport->line),
+   _attr_uartclk);
+
+   /*
 * Remove the devices from the tty layer
 */
tty_unregister_device(drv->tty_driver, uport->line);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index b425c79..8ea8622 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3049,6 +3049,23 @@ void tty_unregister_device(struct tty_driver *driver, 
unsigned index)
 }
 EXPORT_SYMBOL(tty_unregister_device);
 
+/*
+ * tty_lookup_device - lookup a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ *
+ * This function returns a struct device pointer when device has
+ * been found and NULL otherwise.
+ *
+ * Locking: ??
+ */
+struct device *tty_lookup_device(struct tty_driver *driver, unsigned index)
+{
+   dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
+   return class_find_device(tty_class, NULL, , dev_match_devt);
+}
+EXPORT_SYMBOL(tty_lookup_device);
+
 struct tty_driver *__alloc_tty_driver(int lines, struct module *owner)
 {
struct tty_driver *driver;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9f47ab5..5d408a1 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -410,6 +410,8 @@ 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_lookup_device(struct tty_driver *driver,
+   unsigned index);
 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-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ 

[PATCH 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-14 Thread Tomas Hlavacek
Support for read/modify of uartclk via sysfs added.
It may prove useful with some no-name cards that
has different oscillator speeds and no distinguishing
PCI IDs to allow autodetection. It allows better integration
with udev and/or init scripts.

Signed-off-by: Tomas Hlavacek tmshl...@gmail.com
---
 drivers/tty/serial/serial_core.c |   54 ++
 drivers/tty/tty_io.c |   17 
 include/linux/tty.h  |2 ++
 3 files changed, 73 insertions(+)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a21dc8e..059b438 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2293,6 +2293,46 @@ struct tty_driver *uart_console_device(struct console 
*co, int *index)
return p-tty_driver;
 }
 
+static ssize_t get_attr_uartclk(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int ret;
+
+   struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));
+   mutex_lock(state-port.mutex);
+   ret = snprintf(buf, PAGE_SIZE, %d\n, state-uart_port-uartclk);
+   mutex_unlock(state-port.mutex);
+   return ret;
+}
+
+static ssize_t set_attr_uartclk(struct device *dev,
+   struct device_attribute *attr, const char *buf, size_t count)
+{
+   struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));
+   unsigned int val;
+   int ret;
+
+   ret = kstrtouint(buf, 10, val);
+   if (ret)
+   return ret;
+
+   mutex_lock(state-port.mutex);
+
+   /*
+* Check value: baud_base has to be more than 9600
+* and uartclock = baud_base * 16 .
+*/
+   if (val = 153600)
+   state-uart_port-uartclk = val;
+
+   mutex_unlock(state-port.mutex);
+
+   return count;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUGO | S_IWUSR, get_attr_uartclk,
+   set_attr_uartclk);
+
 /**
  * uart_add_one_port - attach a driver-defined port structure
  * @drv: pointer to the uart low level driver structure for this port
@@ -2355,6 +2395,14 @@ int uart_add_one_port(struct uart_driver *drv, struct 
uart_port *uport)
}
 
/*
+* Expose uartclk in sysfs. Use driverdata of the tty device for
+* referencing the UART port.
+*/
+   dev_set_drvdata(tty_dev, state);
+   if (device_create_file(tty_dev, dev_attr_uartclk)  0)
+   dev_err(tty_dev, Failed to add uartclk attr\n);
+
+   /*
 * Ensure UPF_DEAD is not set.
 */
uport-flags = ~UPF_DEAD;
@@ -2397,6 +2445,12 @@ int uart_remove_one_port(struct uart_driver *drv, struct 
uart_port *uport)
mutex_unlock(port-mutex);
 
/*
+* Remove uartclk file from sysfs.
+*/
+   device_remove_file(tty_lookup_device(drv-tty_driver, uport-line),
+   dev_attr_uartclk);
+
+   /*
 * Remove the devices from the tty layer
 */
tty_unregister_device(drv-tty_driver, uport-line);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index b425c79..8ea8622 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3049,6 +3049,23 @@ void tty_unregister_device(struct tty_driver *driver, 
unsigned index)
 }
 EXPORT_SYMBOL(tty_unregister_device);
 
+/*
+ * tty_lookup_device - lookup a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ *
+ * This function returns a struct device pointer when device has
+ * been found and NULL otherwise.
+ *
+ * Locking: ??
+ */
+struct device *tty_lookup_device(struct tty_driver *driver, unsigned index)
+{
+   dev_t devt = MKDEV(driver-major, driver-minor_start) + index;
+   return class_find_device(tty_class, NULL, devt, dev_match_devt);
+}
+EXPORT_SYMBOL(tty_lookup_device);
+
 struct tty_driver *__alloc_tty_driver(int lines, struct module *owner)
 {
struct tty_driver *driver;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9f47ab5..5d408a1 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -410,6 +410,8 @@ 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_lookup_device(struct tty_driver *driver,
+   unsigned index);
 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-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  

Re: [PATCH 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-14 Thread Marek Vasut
Dear Tomas Hlavacek,

 Support for read/modify of uartclk via sysfs added.
 It may prove useful with some no-name cards that
 has different oscillator speeds and no distinguishing
 PCI IDs to allow autodetection. It allows better integration
 with udev and/or init scripts.
 
 Signed-off-by: Tomas Hlavacek tmshl...@gmail.com
 ---
  drivers/tty/serial/serial_core.c |   54
 ++ drivers/tty/tty_io.c | 
  17 
  include/linux/tty.h  |2 ++
  3 files changed, 73 insertions(+)
 
 diff --git a/drivers/tty/serial/serial_core.c
 b/drivers/tty/serial/serial_core.c index a21dc8e..059b438 100644
 --- a/drivers/tty/serial/serial_core.c
 +++ b/drivers/tty/serial/serial_core.c
 @@ -2293,6 +2293,46 @@ struct tty_driver *uart_console_device(struct
 console *co, int *index) return p-tty_driver;
  }
 
 +static ssize_t get_attr_uartclk(struct device *dev,
 + struct device_attribute *attr, char *buf)
 +{
 + int ret;
 +
 + struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));

You don't need this cast here.

 + mutex_lock(state-port.mutex);
 + ret = snprintf(buf, PAGE_SIZE, %d\n, state-uart_port-uartclk);

Do you really need such a large buffer (PAGE_SIZE) ?

 + mutex_unlock(state-port.mutex);
 + return ret;
 +}
 +
 +static ssize_t set_attr_uartclk(struct device *dev,
 + struct device_attribute *attr, const char *buf, size_t count)
 +{
 + struct uart_state *state = (struct uart_state *)(dev_get_drvdata(dev));
 + unsigned int val;
 + int ret;
 +
 + ret = kstrtouint(buf, 10, val);
 + if (ret)
 + return ret;
 +
 + mutex_lock(state-port.mutex);
 +
 + /*
 +  * Check value: baud_base has to be more than 9600
 +  * and uartclock = baud_base * 16 .
 +  */
 + if (val = 153600)
 + state-uart_port-uartclk = val;

This magic value here would use some documentation.

 + mutex_unlock(state-port.mutex);
 +
 + return count;
 +}
 +
 +static DEVICE_ATTR(uartclk, S_IRUGO | S_IWUSR, get_attr_uartclk,
 + set_attr_uartclk);
 +
  /**
   *   uart_add_one_port - attach a driver-defined port structure
   *   @drv: pointer to the uart low level driver structure for this port
 @@ -2355,6 +2395,14 @@ int uart_add_one_port(struct uart_driver *drv,
 struct uart_port *uport) }
 
   /*
 +  * Expose uartclk in sysfs. Use driverdata of the tty device for
 +  * referencing the UART port.
 +  */
 + dev_set_drvdata(tty_dev, state);
 + if (device_create_file(tty_dev, dev_attr_uartclk)  0)
 + dev_err(tty_dev, Failed to add uartclk attr\n);
 +
 + /*
* Ensure UPF_DEAD is not set.
*/
   uport-flags = ~UPF_DEAD;
 @@ -2397,6 +2445,12 @@ int uart_remove_one_port(struct uart_driver *drv,
 struct uart_port *uport) mutex_unlock(port-mutex);
 
   /*
 +  * Remove uartclk file from sysfs.
 +  */
 + device_remove_file(tty_lookup_device(drv-tty_driver, uport-line),
 + dev_attr_uartclk);
 +
 + /*
* Remove the devices from the tty layer
*/
   tty_unregister_device(drv-tty_driver, uport-line);
 diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
 index b425c79..8ea8622 100644
 --- a/drivers/tty/tty_io.c
 +++ b/drivers/tty/tty_io.c
 @@ -3049,6 +3049,23 @@ void tty_unregister_device(struct tty_driver
 *driver, unsigned index) }
  EXPORT_SYMBOL(tty_unregister_device);
 
 +/*
 + *   tty_lookup_device - lookup a tty device
 + *   @driver: the tty driver that describes the tty device
 + *   @index: the index in the tty driver for this tty device
 + *
 + *   This function returns a struct device pointer when device has
 + *   been found and NULL otherwise.
 + *
 + *   Locking: ??
 + */
 +struct device *tty_lookup_device(struct tty_driver *driver, unsigned
 index) +{
 + dev_t devt = MKDEV(driver-major, driver-minor_start) + index;
 + return class_find_device(tty_class, NULL, devt, dev_match_devt);
 +}
 +EXPORT_SYMBOL(tty_lookup_device);
 +
  struct tty_driver *__alloc_tty_driver(int lines, struct module *owner)
  {
   struct tty_driver *driver;
 diff --git a/include/linux/tty.h b/include/linux/tty.h
 index 9f47ab5..5d408a1 100644
 --- a/include/linux/tty.h
 +++ b/include/linux/tty.h
 @@ -410,6 +410,8 @@ 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_lookup_device(struct tty_driver *driver,
 + unsigned index);
  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);
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the