diff mbox

[1/3] TTY: add support for "tty slave" devices.

Message ID 20141211215943.4127.24792.stgit@notabene.brown
State Superseded, archived
Headers show

Commit Message

NeilBrown Dec. 11, 2014, 9:59 p.m. UTC
A "tty slave" is a device connected via UART.
It may need a driver to, for example, power the device on
when the tty is opened, and power it off when the tty
is released.

A "tty slave" is a platform device which is declared as a
child of the uart in device-tree:

&uart1 {
	bluetooth {
		compatible = "tty,regulator";
		vdd-supply = <&vaux4>;
	};
};

runtime power management is used to power-up the device
on tty_open() and  power-down on tty_release().

Signed-off-by: NeilBrown <neilb@suse.de>
---
 .../devicetree/bindings/serial/of-serial.txt       |    4 ++++
 drivers/tty/tty_io.c                               |   22 ++++++++++++++++++++
 2 files changed, 26 insertions(+)



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

Comments

Sebastian Reichel Dec. 11, 2014, 10:41 p.m. UTC | #1
Hi,

On Fri, Dec 12, 2014 at 08:59:44AM +1100, NeilBrown wrote:
> A "tty slave" is a device connected via UART.
> It may need a driver to, for example, power the device on
> when the tty is opened, and power it off when the tty
> is released.
> 
> A "tty slave" is a platform device which is declared as a
> child of the uart in device-tree:
> 
> &uart1 {
> 	bluetooth {
> 		compatible = "tty,regulator";
> 		vdd-supply = <&vaux4>;
> 	};
> };
> 
> runtime power management is used to power-up the device
> on tty_open() and  power-down on tty_release().
> 
> Signed-off-by: NeilBrown <neilb@suse.de>

FWIW:

Acked-By: Sebastian Reichel <sre@kernel.org>

-- Sebastian
Peter Hurley Dec. 11, 2014, 11:18 p.m. UTC | #2
On 12/11/2014 04:59 PM, NeilBrown wrote:
> A "tty slave" is a device connected via UART.
> It may need a driver to, for example, power the device on
> when the tty is opened, and power it off when the tty
> is released.
> 
> A "tty slave" is a platform device which is declared as a
> child of the uart in device-tree:
> 
> &uart1 {
> 	bluetooth {
> 		compatible = "tty,regulator";
> 		vdd-supply = <&vaux4>;
> 	};
> };
> 
> runtime power management is used to power-up the device
> on tty_open() and  power-down on tty_release().

I have a couple of issues with this:
1) why does a child device imply power management and a platform
   device? iow, what happens when someone else wants to have a
   child device that does something different?
2) why is this tied to the tty core and not the serial core
   if this is only for UART?

Regards,
Peter Hurley

> Signed-off-by: NeilBrown <neilb@suse.de>
> ---
>  .../devicetree/bindings/serial/of-serial.txt       |    4 ++++
>  drivers/tty/tty_io.c                               |   22 ++++++++++++++++++++
>  2 files changed, 26 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/serial/of-serial.txt b/Documentation/devicetree/bindings/serial/of-serial.txt
> index 8c4fd0332028..b59501ee2f21 100644
> --- a/Documentation/devicetree/bindings/serial/of-serial.txt
> +++ b/Documentation/devicetree/bindings/serial/of-serial.txt
> @@ -39,6 +39,10 @@ Optional properties:
>    driver is allowed to detect support for the capability even without this
>    property.
>  
> +Optional child node:
> +- a platform device listed as a child node will be probed and
> +  powered-on whenever the tty is in use (open).
> +
>  Example:
>  
>  	uart@80230000 {
> diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
> index 0508a1d8e4cd..7acdc6f093f4 100644
> --- a/drivers/tty/tty_io.c
> +++ b/drivers/tty/tty_io.c
> @@ -95,6 +95,8 @@
>  #include <linux/seq_file.h>
>  #include <linux/serial.h>
>  #include <linux/ratelimit.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/of_platform.h>
>  
>  #include <linux/uaccess.h>
>  
> @@ -1683,6 +1685,17 @@ static int tty_release_checks(struct tty_struct *tty, struct tty_struct *o_tty,
>  	return 0;
>  }
>  
> +static int open_child(struct device *dev, void *data)
> +{
> +	pm_runtime_get_sync(dev);
> +	return 0;
> +}
> +static int release_child(struct device *dev, void *data)
> +{
> +	pm_runtime_put_autosuspend(dev);
> +	return 0;
> +}
> +
>  /**
>   *	tty_release		-	vfs callback for close
>   *	@inode: inode of tty
> @@ -1712,6 +1725,8 @@ int tty_release(struct inode *inode, struct file *filp)
>  	long	timeout = 0;
>  	int	once = 1;
>  
> +	if (tty->dev)
> +		device_for_each_child(tty->dev, NULL, release_child);
>  	if (tty_paranoia_check(tty, inode, __func__))
>  		return 0;
>  
> @@ -2118,6 +2133,8 @@ retry_open:
>  		__proc_set_tty(current, tty);
>  	spin_unlock_irq(&current->sighand->siglock);
>  	tty_unlock(tty);
> +	if (tty->dev)
> +		device_for_each_child(tty->dev, NULL, open_child);
>  	mutex_unlock(&tty_mutex);
>  	return 0;
>  err_unlock:
> @@ -3207,6 +3224,11 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
>  	retval = device_register(dev);
>  	if (retval)
>  		goto error;
> +	if (device && device->of_node)
> +		/* Children are platform devices and will be
> +		 * runtime_pm managed by this tty.
> +		 */
> +		of_platform_populate(device->of_node, NULL, NULL, dev);
>  
>  	return dev;


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
NeilBrown Dec. 12, 2014, 5:23 a.m. UTC | #3
On Thu, 11 Dec 2014 18:18:37 -0500 Peter Hurley <peter@hurleysoftware.com>
wrote:

> On 12/11/2014 04:59 PM, NeilBrown wrote:
> > A "tty slave" is a device connected via UART.
> > It may need a driver to, for example, power the device on
> > when the tty is opened, and power it off when the tty
> > is released.
> > 
> > A "tty slave" is a platform device which is declared as a
> > child of the uart in device-tree:
> > 
> > &uart1 {
> > 	bluetooth {
> > 		compatible = "tty,regulator";
> > 		vdd-supply = <&vaux4>;
> > 	};
> > };
> > 
> > runtime power management is used to power-up the device
> > on tty_open() and  power-down on tty_release().
> 
> I have a couple of issues with this:
> 1) why does a child device imply power management and a platform
>    device? iow, what happens when someone else wants to have a
>    child device that does something different?

Why does it imply power management?
 Because it seems to make obvious sense to turn something on when the tty is
 open.  If the device has other reason to remain on when the tty is closed,
 it can arrange for extra references to be taken of course.
 Is it conceivable that you would want the device to remain off when the
 tty device is open?  In that case just make it a regular platform device.

Why a platform device?
 Things on an i2c bus are i2c devices.  Things on a usb bus are usb devices.
 Ideally a thing on a uart 'bus' would be a 'uart device', but no such thing
 exists.  I did contemplate the possibility of creating an explicit "uart" or
 "tty" bus type, but I could find no value in that.
 The door is certainly still open to that possibility if a meaning for the
 idea becomes apparent.  As far as device tree is concerned it is just a
 child device node.  The fact that it is implemented as a "platform" device
 could easily be changed later if needed without device tree noticing.

What could conceivably want to be different?  The only (purely hypothetical)
concept I can come up with which wouldn't fit is a device with both an UART
port and a USB port, or similar.  However device tree, and the device model
in general, just isn't geared towards devices being on multiple buses so
if that were real it would have much greater implications that just here.

But maybe I misunderstand...


> 2) why is this tied to the tty core and not the serial core
>    if this is only for UART?

Because the knowledge of "the device is being opened" or "the device is being
closed" seems to exist in the tty core but not in the serial core.

The "of_platform_populate()" call could certainly go in serial_core.c, in
uart_add_one_port() I think.  I did have it there originally.  I moved it for
a reason that I think is no longer relevant.  As the on/off code is (and I
think has to be) in tty_io.c, I left all of it there.

I'm happy to move it to serial_core.c if that is preferred.
I'll also move the open/close handling if you can point to where it should go.


Thanks,
NeilBrown


> 
> Regards,
> Peter Hurley
> 
> > Signed-off-by: NeilBrown <neilb@suse.de>
> > ---
> >  .../devicetree/bindings/serial/of-serial.txt       |    4 ++++
> >  drivers/tty/tty_io.c                               |   22 ++++++++++++++++++++
> >  2 files changed, 26 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/serial/of-serial.txt b/Documentation/devicetree/bindings/serial/of-serial.txt
> > index 8c4fd0332028..b59501ee2f21 100644
> > --- a/Documentation/devicetree/bindings/serial/of-serial.txt
> > +++ b/Documentation/devicetree/bindings/serial/of-serial.txt
> > @@ -39,6 +39,10 @@ Optional properties:
> >    driver is allowed to detect support for the capability even without this
> >    property.
> >  
> > +Optional child node:
> > +- a platform device listed as a child node will be probed and
> > +  powered-on whenever the tty is in use (open).
> > +
> >  Example:
> >  
> >  	uart@80230000 {
> > diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
> > index 0508a1d8e4cd..7acdc6f093f4 100644
> > --- a/drivers/tty/tty_io.c
> > +++ b/drivers/tty/tty_io.c
> > @@ -95,6 +95,8 @@
> >  #include <linux/seq_file.h>
> >  #include <linux/serial.h>
> >  #include <linux/ratelimit.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/of_platform.h>
> >  
> >  #include <linux/uaccess.h>
> >  
> > @@ -1683,6 +1685,17 @@ static int tty_release_checks(struct tty_struct *tty, struct tty_struct *o_tty,
> >  	return 0;
> >  }
> >  
> > +static int open_child(struct device *dev, void *data)
> > +{
> > +	pm_runtime_get_sync(dev);
> > +	return 0;
> > +}
> > +static int release_child(struct device *dev, void *data)
> > +{
> > +	pm_runtime_put_autosuspend(dev);
> > +	return 0;
> > +}
> > +
> >  /**
> >   *	tty_release		-	vfs callback for close
> >   *	@inode: inode of tty
> > @@ -1712,6 +1725,8 @@ int tty_release(struct inode *inode, struct file *filp)
> >  	long	timeout = 0;
> >  	int	once = 1;
> >  
> > +	if (tty->dev)
> > +		device_for_each_child(tty->dev, NULL, release_child);
> >  	if (tty_paranoia_check(tty, inode, __func__))
> >  		return 0;
> >  
> > @@ -2118,6 +2133,8 @@ retry_open:
> >  		__proc_set_tty(current, tty);
> >  	spin_unlock_irq(&current->sighand->siglock);
> >  	tty_unlock(tty);
> > +	if (tty->dev)
> > +		device_for_each_child(tty->dev, NULL, open_child);
> >  	mutex_unlock(&tty_mutex);
> >  	return 0;
> >  err_unlock:
> > @@ -3207,6 +3224,11 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
> >  	retval = device_register(dev);
> >  	if (retval)
> >  		goto error;
> > +	if (device && device->of_node)
> > +		/* Children are platform devices and will be
> > +		 * runtime_pm managed by this tty.
> > +		 */
> > +		of_platform_populate(device->of_node, NULL, NULL, dev);
> >  
> >  	return dev;
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Grant Likely Dec. 12, 2014, 11:59 a.m. UTC | #4
On Fri, 12 Dec 2014 08:59:44 +1100
, NeilBrown <neilb@suse.de>
 wrote:
> A "tty slave" is a device connected via UART.
> It may need a driver to, for example, power the device on
> when the tty is opened, and power it off when the tty
> is released.

Some nit picking below, mostly about avoiding nasty surprises on devices
that may already have child nodes below the tty node.

> 
> A "tty slave" is a platform device which is declared as a
> child of the uart in device-tree:

As far as the binding is concerned, talking about platform devices isn't
relevant. That's an implementation detail. They are just devices.

Using a platform device is somewhat problematic for the kernel because
the DT could specify pretty much *any* platform device compatible value
here and the kernel will happily bind a driver to it. I strongly
recommend a separate bus type so that the pool of drivers remains
separate. It would be a good time to look at platform_bus_type and see
if more of it can be generalized so that subsystems can have custom bus
types without very much code at all.

> 
> &uart1 {
> 	bluetooth {
> 		compatible = "tty,regulator";
> 		vdd-supply = <&vaux4>;
> 	};

The example here isn't great. The compatible value should specify the
specific device, not a generic "tty,regulator" type binding. The
expectation is the driver understands the attachment and understands how
to do PM on the device.

> };
> 
> runtime power management is used to power-up the device
> on tty_open() and  power-down on tty_release().

What about devices that need to stay powered up even if the tty is not
opened? The runtime PM model needs to be better described for tty slaves.

> 
> Signed-off-by: NeilBrown <neilb@suse.de>
> ---
>  .../devicetree/bindings/serial/of-serial.txt       |    4 ++++
>  drivers/tty/tty_io.c                               |   22 ++++++++++++++++++++
>  2 files changed, 26 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/serial/of-serial.txt b/Documentation/devicetree/bindings/serial/of-serial.txt
> index 8c4fd0332028..b59501ee2f21 100644
> --- a/Documentation/devicetree/bindings/serial/of-serial.txt
> +++ b/Documentation/devicetree/bindings/serial/of-serial.txt
> @@ -39,6 +39,10 @@ Optional properties:
>    driver is allowed to detect support for the capability even without this
>    property.
>  
> +Optional child node:
> +- a platform device listed as a child node will be probed and
> +  powered-on whenever the tty is in use (open).
> +

The biggest concern I have is what happens to nodes that already have
child devices that /don't/ match this use case? It is possible that some
UART nodes already have a child node used to store other data. There are
two ways to handle this; 1) add a new bool property that indicates the
child nodes are tty slave devices, or 2) Make each uart driver
explicitly enable the feature so that driver authors can check if it is
a problem for that device. I personally would suggest #1 because then it
can be enabled in generic code.

>  Example:
>  
>  	uart@80230000 {
> diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
> index 0508a1d8e4cd..7acdc6f093f4 100644
> --- a/drivers/tty/tty_io.c
> +++ b/drivers/tty/tty_io.c
> @@ -95,6 +95,8 @@
>  #include <linux/seq_file.h>
>  #include <linux/serial.h>
>  #include <linux/ratelimit.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/of_platform.h>
>  
>  #include <linux/uaccess.h>
>  
> @@ -1683,6 +1685,17 @@ static int tty_release_checks(struct tty_struct *tty, struct tty_struct *o_tty,
>  	return 0;
>  }
>  
> +static int open_child(struct device *dev, void *data)
> +{
> +	pm_runtime_get_sync(dev);
> +	return 0;
> +}
> +static int release_child(struct device *dev, void *data)
> +{
> +	pm_runtime_put_autosuspend(dev);
> +	return 0;
> +}
> +
>  /**
>   *	tty_release		-	vfs callback for close
>   *	@inode: inode of tty
> @@ -1712,6 +1725,8 @@ int tty_release(struct inode *inode, struct file *filp)
>  	long	timeout = 0;
>  	int	once = 1;
>  
> +	if (tty->dev)
> +		device_for_each_child(tty->dev, NULL, release_child);
>  	if (tty_paranoia_check(tty, inode, __func__))
>  		return 0;
>  
> @@ -2118,6 +2133,8 @@ retry_open:
>  		__proc_set_tty(current, tty);
>  	spin_unlock_irq(&current->sighand->siglock);
>  	tty_unlock(tty);
> +	if (tty->dev)
> +		device_for_each_child(tty->dev, NULL, open_child);
>  	mutex_unlock(&tty_mutex);
>  	return 0;
>  err_unlock:
> @@ -3207,6 +3224,11 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
>  	retval = device_register(dev);
>  	if (retval)
>  		goto error;
> +	if (device && device->of_node)
> +		/* Children are platform devices and will be
> +		 * runtime_pm managed by this tty.
> +		 */
> +		of_platform_populate(device->of_node, NULL, NULL, dev);

Also need to remove all the tty slaves on driver unbind.

>  
>  	return dev;
>  
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Peter Hurley Dec. 12, 2014, 1:02 p.m. UTC | #5
On 12/12/2014 12:23 AM, NeilBrown wrote:
> On Thu, 11 Dec 2014 18:18:37 -0500 Peter Hurley <peter@hurleysoftware.com>
> wrote:
> 
>> On 12/11/2014 04:59 PM, NeilBrown wrote:
>>> A "tty slave" is a device connected via UART.
>>> It may need a driver to, for example, power the device on
>>> when the tty is opened, and power it off when the tty
>>> is released.
>>>
>>> A "tty slave" is a platform device which is declared as a
>>> child of the uart in device-tree:
>>>
>>> &uart1 {
>>> 	bluetooth {
>>> 		compatible = "tty,regulator";
>>> 		vdd-supply = <&vaux4>;
>>> 	};
>>> };
>>>
>>> runtime power management is used to power-up the device
>>> on tty_open() and  power-down on tty_release().
>>
>> I have a couple of issues with this:
>> 1) why does a child device imply power management and a platform
>>    device? iow, what happens when someone else wants to have a
>>    child device that does something different?
> 
> Why does it imply power management?
>  Because it seems to make obvious sense to turn something on when the tty is
>  open.  If the device has other reason to remain on when the tty is closed,
>  it can arrange for extra references to be taken of course.
>  Is it conceivable that you would want the device to remain off when the
>  tty device is open?  In that case just make it a regular platform device.
> 
> Why a platform device?
>  Things on an i2c bus are i2c devices.  Things on a usb bus are usb devices.
>  Ideally a thing on a uart 'bus' would be a 'uart device', but no such thing
>  exists.  I did contemplate the possibility of creating an explicit "uart" or
>  "tty" bus type, but I could find no value in that.
>  The door is certainly still open to that possibility if a meaning for the
>  idea becomes apparent.  As far as device tree is concerned it is just a
>  child device node.  The fact that it is implemented as a "platform" device
>  could easily be changed later if needed without device tree noticing.
> 
> What could conceivably want to be different?  The only (purely hypothetical)
> concept I can come up with which wouldn't fit is a device with both an UART
> port and a USB port, or similar.  However device tree, and the device model
> in general, just isn't geared towards devices being on multiple buses so
> if that were real it would have much greater implications that just here.
> 
> But maybe I misunderstand...

Yeah, misunderstanding.

This patch is using a very generic abstraction (parent-child device association)
for a really specific purpose (power management for platform devices).
What about PCI, PNP, etc.?

Also, what happens for existing child device associations like bluetooth & serio?
Why not just provide a serial core interface for associating power-managed
child devices?

Which brings up another point: why not do this in the runtime power management;
ie, turn on the slave device when the master device is turned on? Sebastian
recently made the 8250 driver power-managed per access, which would enable
significant power savings over just leaving the slave device on the whole time.

>> 2) why is this tied to the tty core and not the serial core
>>    if this is only for UART?
> 
> Because the knowledge of "the device is being opened" or "the device is being
> closed" seems to exist in the tty core but not in the serial core.

uart_open() = device file is being opened
uart_close() = device file is being released

> The "of_platform_populate()" call could certainly go in serial_core.c, in
> uart_add_one_port() I think.  I did have it there originally.  I moved it for
> a reason that I think is no longer relevant.  As the on/off code is (and I
> think has to be) in tty_io.c, I left all of it there.
> 
> I'm happy to move it to serial_core.c if that is preferred.
> I'll also move the open/close handling if you can point to where it should go.

Yes, please.
The reverse dependency (tty core => of) is undesirable.

Regards,
Peter Hurley

>>> Signed-off-by: NeilBrown <neilb@suse.de>
>>> ---
>>>  .../devicetree/bindings/serial/of-serial.txt       |    4 ++++
>>>  drivers/tty/tty_io.c                               |   22 ++++++++++++++++++++
>>>  2 files changed, 26 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/serial/of-serial.txt b/Documentation/devicetree/bindings/serial/of-serial.txt
>>> index 8c4fd0332028..b59501ee2f21 100644
>>> --- a/Documentation/devicetree/bindings/serial/of-serial.txt
>>> +++ b/Documentation/devicetree/bindings/serial/of-serial.txt
>>> @@ -39,6 +39,10 @@ Optional properties:
>>>    driver is allowed to detect support for the capability even without this
>>>    property.
>>>  
>>> +Optional child node:
>>> +- a platform device listed as a child node will be probed and
>>> +  powered-on whenever the tty is in use (open).
>>> +
>>>  Example:
>>>  
>>>  	uart@80230000 {
>>> diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
>>> index 0508a1d8e4cd..7acdc6f093f4 100644
>>> --- a/drivers/tty/tty_io.c
>>> +++ b/drivers/tty/tty_io.c
>>> @@ -95,6 +95,8 @@
>>>  #include <linux/seq_file.h>
>>>  #include <linux/serial.h>
>>>  #include <linux/ratelimit.h>
>>> +#include <linux/pm_runtime.h>
>>> +#include <linux/of_platform.h>
>>>  
>>>  #include <linux/uaccess.h>
>>>  
>>> @@ -1683,6 +1685,17 @@ static int tty_release_checks(struct tty_struct *tty, struct tty_struct *o_tty,
>>>  	return 0;
>>>  }
>>>  
>>> +static int open_child(struct device *dev, void *data)
>>> +{
>>> +	pm_runtime_get_sync(dev);
>>> +	return 0;
>>> +}
>>> +static int release_child(struct device *dev, void *data)
>>> +{
>>> +	pm_runtime_put_autosuspend(dev);
>>> +	return 0;
>>> +}
>>> +
>>>  /**
>>>   *	tty_release		-	vfs callback for close
>>>   *	@inode: inode of tty
>>> @@ -1712,6 +1725,8 @@ int tty_release(struct inode *inode, struct file *filp)
>>>  	long	timeout = 0;
>>>  	int	once = 1;
>>>  
>>> +	if (tty->dev)
>>> +		device_for_each_child(tty->dev, NULL, release_child);
>>>  	if (tty_paranoia_check(tty, inode, __func__))
>>>  		return 0;
>>>  
>>> @@ -2118,6 +2133,8 @@ retry_open:
>>>  		__proc_set_tty(current, tty);
>>>  	spin_unlock_irq(&current->sighand->siglock);
>>>  	tty_unlock(tty);
>>> +	if (tty->dev)
>>> +		device_for_each_child(tty->dev, NULL, open_child);
>>>  	mutex_unlock(&tty_mutex);
>>>  	return 0;
>>>  err_unlock:
>>> @@ -3207,6 +3224,11 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
>>>  	retval = device_register(dev);
>>>  	if (retval)
>>>  		goto error;
>>> +	if (device && device->of_node)
>>> +		/* Children are platform devices and will be
>>> +		 * runtime_pm managed by this tty.
>>> +		 */
>>> +		of_platform_populate(device->of_node, NULL, NULL, dev);
>>>  
>>>  	return dev;


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alan Cox Dec. 13, 2014, 2:12 p.m. UTC | #6
> 2) why is this tied to the tty core and not the serial core
>    if this is only for UART?

I'm a bit baffled why you would try and tie it to serial core given that
serial core only covers a random subset of the uart drivers we have. If
we have a USB connected device with USB gpio lines doing power management
then it needs to be tied tty core.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alan Cox Dec. 13, 2014, 2:23 p.m. UTC | #7
On Fri, 12 Dec 2014 08:02:48 -0500
> Which brings up another point: why not do this in the runtime power management;
> ie, turn on the slave device when the master device is turned on? Sebastian
> recently made the 8250 driver power-managed per access, which would enable
> significant power savings over just leaving the slave device on the whole time.

That per access model only works on 8250 (in fact only on some 8250). On
most devices if the UART is in low power you lose bytes send to it rather
than then queuing up anywhere.

It doesn't handle cases where you need to keep power on to different rules
(for example there are cases where you do things like power the uart down
after no bits have been received for 'n' millseconds). Right now if you
look into Androidspace you'll find people doing this in userspace by
having the sysfs node open and playing crazy games with sysfs, Android
glue hacks and gpio poking via the gpio sysfs/gpio lib routines.

Good example is some of the GPS and serial based sensor chips. The
latency of tty open/close is unacceptable and risks losing bits so they
keep the tty open and whack the power management by hand right now.

The kind of thing many of them want is stuff like

"hold power on until we see receive data, then keep it on until it shuts
up for a bit"

"assert gpio, send, receive, wait idle, drop gpio"

"on GPIO interrupt wake uart, wait for data, when idle, power uart down"

> >> 2) why is this tied to the tty core and not the serial core
> >>    if this is only for UART?
> > 
> > Because the knowledge of "the device is being opened" or "the device is being
> > closed" seems to exist in the tty core but not in the serial core.
> 
> uart_open() = device file is being opened
> uart_close() = device file is being released

Only for a subset of uart type devices that use the uart layer. Quite a
few don't, including all the USB ones, and the sd ones.

> > I'm happy to move it to serial_core.c if that is preferred.
> > I'll also move the open/close handling if you can point to where it should go.
> 
> Yes, please.

NAK - I certainly object to it being moved to uart. That's the wrong
abstraction layer for this. It's a generic behaviour, it's a tty level
behaviour without any uart specific properties. It should work for uarts
that don't use the legacy serial_core code, uarts that do, uarts that use
USB, uarts that are directly connected to things like sdio etc.

That means it has to be tty layer.

Alan
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sebastian Reichel Dec. 13, 2014, 5:46 p.m. UTC | #8
Hi,

On Fri, Dec 12, 2014 at 11:59:20AM +0000, Grant Likely wrote:
> [...]
> > --- a/Documentation/devicetree/bindings/serial/of-serial.txt
> > +++ b/Documentation/devicetree/bindings/serial/of-serial.txt
> > @@ -39,6 +39,10 @@ Optional properties:
> >    driver is allowed to detect support for the capability even without this
> >    property.
> >  
> > +Optional child node:
> > +- a platform device listed as a child node will be probed and
> > +  powered-on whenever the tty is in use (open).
> > +
> 
> The biggest concern I have is what happens to nodes that already have
> child devices that /don't/ match this use case? It is possible that some
> UART nodes already have a child node used to store other data. There are
> two ways to handle this; 1) add a new bool property that indicates the
> child nodes are tty slave devices, or 2) Make each uart driver
> explicitly enable the feature so that driver authors can check if it is
> a problem for that device. I personally would suggest #1 because then it
> can be enabled in generic code.

maybe simple depend on the compatible value? If the UART node has
child nodes to store other random data it should not have a
compatible value?

-- Sebastian
Grant Likely Dec. 13, 2014, 10:22 p.m. UTC | #9
On Sat, Dec 13, 2014 at 5:46 PM, Sebastian Reichel <sre@kernel.org> wrote:
> Hi,
>
> On Fri, Dec 12, 2014 at 11:59:20AM +0000, Grant Likely wrote:
>> [...]
>> > --- a/Documentation/devicetree/bindings/serial/of-serial.txt
>> > +++ b/Documentation/devicetree/bindings/serial/of-serial.txt
>> > @@ -39,6 +39,10 @@ Optional properties:
>> >    driver is allowed to detect support for the capability even without this
>> >    property.
>> >
>> > +Optional child node:
>> > +- a platform device listed as a child node will be probed and
>> > +  powered-on whenever the tty is in use (open).
>> > +
>>
>> The biggest concern I have is what happens to nodes that already have
>> child devices that /don't/ match this use case? It is possible that some
>> UART nodes already have a child node used to store other data. There are
>> two ways to handle this; 1) add a new bool property that indicates the
>> child nodes are tty slave devices, or 2) Make each uart driver
>> explicitly enable the feature so that driver authors can check if it is
>> a problem for that device. I personally would suggest #1 because then it
>> can be enabled in generic code.
>
> maybe simple depend on the compatible value? If the UART node has
> child nodes to store other random data it should not have a
> compatible value?

That's not a given. It is entirely possible that drivers have used
compatible in the child nodes.

However, I may be stirring up trouble for nothing. We could enable it
for all child nodes that have a compatible value, and then blacklist
any parent nodes that want to use a different behaviour. If someone
complains then we will fix it.

g.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Peter Hurley Dec. 16, 2014, 4:14 p.m. UTC | #10
On 12/13/2014 09:23 AM, One Thousand Gnomes wrote:
> On Fri, 12 Dec 2014 08:02:48 -0500
>> Which brings up another point: why not do this in the runtime power management;
>> ie, turn on the slave device when the master device is turned on? Sebastian
>> recently made the 8250 driver power-managed per access, which would enable
>> significant power savings over just leaving the slave device on the whole time.
> 
> That per access model only works on 8250 (in fact only on some 8250). On
> most devices if the UART is in low power you lose bytes send to it rather
> than then queuing up anywhere.
> 
> It doesn't handle cases where you need to keep power on to different rules
> (for example there are cases where you do things like power the uart down
> after no bits have been received for 'n' millseconds). Right now if you
> look into Androidspace you'll find people doing this in userspace by
> having the sysfs node open and playing crazy games with sysfs, Android
> glue hacks and gpio poking via the gpio sysfs/gpio lib routines.
> 
> Good example is some of the GPS and serial based sensor chips. The
> latency of tty open/close is unacceptable and risks losing bits so they
> keep the tty open and whack the power management by hand right now.
> 
> The kind of thing many of them want is stuff like
> 
> "hold power on until we see receive data, then keep it on until it shuts
> up for a bit"
> 
> "assert gpio, send, receive, wait idle, drop gpio"
> 
> "on GPIO interrupt wake uart, wait for data, when idle, power uart down"
> 
>>>> 2) why is this tied to the tty core and not the serial core
>>>>    if this is only for UART?
>>>
>>> Because the knowledge of "the device is being opened" or "the device is being
>>> closed" seems to exist in the tty core but not in the serial core.
>>
>> uart_open() = device file is being opened
>> uart_close() = device file is being released
> 
> Only for a subset of uart type devices that use the uart layer. Quite a
> few don't, including all the USB ones, and the sd ones.
> 
>>> I'm happy to move it to serial_core.c if that is preferred.
>>> I'll also move the open/close handling if you can point to where it should go.
>>
>> Yes, please.
> 
> NAK - I certainly object to it being moved to uart. That's the wrong
> abstraction layer for this. It's a generic behaviour, it's a tty level
> behaviour without any uart specific properties. It should work for uarts
> that don't use the legacy serial_core code, uarts that do, uarts that use
> USB, uarts that are directly connected to things like sdio etc.
> 
> That means it has to be tty layer.

I was reviewing the patch submitted, which does none of the things you
outlined and does not provide the necessary infrastructure to build upon it.

I'm all for the functionality you describe but I think that design will end
up subsystem-agnostic.

Regards,
Peter Hurley


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pavel Machek Dec. 28, 2014, 2:20 p.m. UTC | #11
Hi!

> index 8c4fd0332028..b59501ee2f21 100644
> --- a/Documentation/devicetree/bindings/serial/of-serial.txt
> +++ b/Documentation/devicetree/bindings/serial/of-serial.txt
> @@ -39,6 +39,10 @@ Optional properties:
>    driver is allowed to detect support for the capability even without this
>    property.
>  
> +Optional child node:
> +- a platform device listed as a child node will be probed and
> +  powered-on whenever the tty is in use (open).
> +
>  Example:
>  
>  	uart@80230000 {

Hmm. Other devices may want it the other way around: probe the device
behind the uart, make it control power and open/close of the uart, and
hide the /dev/ttyXX from userspace...
								Pavel
NeilBrown Jan. 2, 2015, 9:33 p.m. UTC | #12
On Sun, 28 Dec 2014 15:20:10 +0100 Pavel Machek <pavel@ucw.cz> wrote:

> Hi!
> 
> > index 8c4fd0332028..b59501ee2f21 100644
> > --- a/Documentation/devicetree/bindings/serial/of-serial.txt
> > +++ b/Documentation/devicetree/bindings/serial/of-serial.txt
> > @@ -39,6 +39,10 @@ Optional properties:
> >    driver is allowed to detect support for the capability even without this
> >    property.
> >  
> > +Optional child node:
> > +- a platform device listed as a child node will be probed and
> > +  powered-on whenever the tty is in use (open).
> > +
> >  Example:
> >  
> >  	uart@80230000 {
> 
> Hmm. Other devices may want it the other way around: probe the device
> behind the uart, make it control power and open/close of the uart, and
> hide the /dev/ttyXX from userspace...
> 								Pavel
> 								

I've been thinking a bit about this.

The current "tty" seems to be a combination of two things:
 - a line discipline
 - a char_dev

But some line disciplines don't really want the char_dev.
N_MOUSE wants a serio device.
N_HCI wants an HCI device
N_GSM07010 wants 63 different tty char_devs.
N_IRDA and N_PPP ultimately want a net_dev.
etc.

It would be really nice if the uart would register the line disciple as a
child device, then the line discipline would register whatever it wants.

Then if a uart had no children, it would register the 'N_TTY' line discipline
and get a tty char_dev.  If it had a child, it would probe the child device
and leave it to register and appropriate line discipline.

The child device could interpose itself in the control flow somehow so my
driver could add power control at open/close.

But that isn't how it works.  The line discipline doesn't talk to the uart.
Rather the tty layer talks to the uart (through tty_operations) and to the
line discipline (through tty_ldisc_ops) and also registers the char_dev.

One of the several difficulties with allowing a child device to select a line
discipline is the different line disciplines activate differently.

N_HCI activates (registers the hci dev) on HCIUARTSETPROTO ioctl.  A child
  device would need a way to specify the protocol I resume.
N_MOUSE activates on a 'read' on the tty - and deactivates when the read
  completes.
N_GSM0710 activates immediately that the ldisc is activated, as does N_IRDA
N_PPP seems to want a PPPIOCNEWUNIT ioctl to fully register.

Doing any of these in a driver for a uart slave device would certainly be
possible.  I wonder if it is something we really want to do in the kernel
though.  What is the gain over providing sufficient information in the
KOBJ_ADD uevent so that udev can do the required work in user-space?

I'm not against the idea, I am just finding it hard to justify.

However I do like the idea of having the UART probe the child instead of
registering a tty.  It could pass the tty_operations structure to the child,
and the child could then register a tty with a slightly different
tty_operations structure, allowing it to capture any operations that it wants
to capture (such as open/close).
I might try coding that and see what it looks like...

Thanks,
NeilBrown
Pavel Machek Jan. 4, 2015, 10:18 a.m. UTC | #13
Hi!

> > > +Optional child node:
> > > +- a platform device listed as a child node will be probed and
> > > +  powered-on whenever the tty is in use (open).
> > > +
> > >  Example:
> > >  
> > >  	uart@80230000 {
> > 

> But some line disciplines don't really want the char_dev.
> N_MOUSE wants a serio device.
> N_HCI wants an HCI device
> N_GSM07010 wants 63 different tty char_devs.
> N_IRDA and N_PPP ultimately want a net_dev.
> etc.
> 
> It would be really nice if the uart would register the line disciple as a
> child device, then the line discipline would register whatever it wants.

Yes.

> N_HCI activates (registers the hci dev) on HCIUARTSETPROTO ioctl.  A child
>   device would need a way to specify the protocol I resume.
> N_MOUSE activates on a 'read' on the tty - and deactivates when the read
>   completes.
> N_GSM0710 activates immediately that the ldisc is activated, as does N_IRDA
> N_PPP seems to want a PPPIOCNEWUNIT ioctl to fully register.
> 
> Doing any of these in a driver for a uart slave device would certainly be
> possible.  I wonder if it is something we really want to do in the kernel
> though.  What is the gain over providing sufficient information in the
> KOBJ_ADD uevent so that udev can do the required work in user-space?

Consistency. If you have bluetooth on USB, it automatically works,
without userspace help. If we have mouse on USB, it automatically
works, etc...

> However I do like the idea of having the UART probe the child instead of
> registering a tty.  It could pass the tty_operations structure to the child,
> and the child could then register a tty with a slightly different
> tty_operations structure, allowing it to capture any operations that it wants
> to capture (such as open/close).
> I might try coding that and see what it looks like...

Lets have a look...
									Pavel
NeilBrown Jan. 5, 2015, 7:09 a.m. UTC | #14
On Sun, 4 Jan 2015 11:18:47 +0100 Pavel Machek <pavel@ucw.cz> wrote:

> Hi!
> 
> > > > +Optional child node:
> > > > +- a platform device listed as a child node will be probed and
> > > > +  powered-on whenever the tty is in use (open).
> > > > +
> > > >  Example:
> > > >  
> > > >  	uart@80230000 {
> > > 
> 
> > But some line disciplines don't really want the char_dev.
> > N_MOUSE wants a serio device.
> > N_HCI wants an HCI device
> > N_GSM07010 wants 63 different tty char_devs.
> > N_IRDA and N_PPP ultimately want a net_dev.
> > etc.
> > 
> > It would be really nice if the uart would register the line disciple as a
> > child device, then the line discipline would register whatever it wants.
> 
> Yes.
> 
> > N_HCI activates (registers the hci dev) on HCIUARTSETPROTO ioctl.  A child
> >   device would need a way to specify the protocol I resume.
> > N_MOUSE activates on a 'read' on the tty - and deactivates when the read
> >   completes.
> > N_GSM0710 activates immediately that the ldisc is activated, as does N_IRDA
> > N_PPP seems to want a PPPIOCNEWUNIT ioctl to fully register.
> > 
> > Doing any of these in a driver for a uart slave device would certainly be
> > possible.  I wonder if it is something we really want to do in the kernel
> > though.  What is the gain over providing sufficient information in the
> > KOBJ_ADD uevent so that udev can do the required work in user-space?
> 
> Consistency. If you have bluetooth on USB, it automatically works,
> without userspace help. If we have mouse on USB, it automatically
> works, etc...

My point is: why is the kernel/userspace distinction important?  As long as
it "automatically works", does it really matter where the code is?
We can put a little bit of code in the kernel (to report the details of the
attached device) and a little bit of code in udev (to run hciattach) and it
will still be automatic.

NeilBrown


> 
> > However I do like the idea of having the UART probe the child instead of
> > registering a tty.  It could pass the tty_operations structure to the child,
> > and the child could then register a tty with a slightly different
> > tty_operations structure, allowing it to capture any operations that it wants
> > to capture (such as open/close).
> > I might try coding that and see what it looks like...
> 
> Lets have a look...
> 									Pavel
Pavel Machek Jan. 5, 2015, 1:43 p.m. UTC | #15
Hi!

> > > N_HCI activates (registers the hci dev) on HCIUARTSETPROTO ioctl.  A child
> > >   device would need a way to specify the protocol I resume.
> > > N_MOUSE activates on a 'read' on the tty - and deactivates when the read
> > >   completes.
> > > N_GSM0710 activates immediately that the ldisc is activated, as does N_IRDA
> > > N_PPP seems to want a PPPIOCNEWUNIT ioctl to fully register.
> > > 
> > > Doing any of these in a driver for a uart slave device would certainly be
> > > possible.  I wonder if it is something we really want to do in the kernel
> > > though.  What is the gain over providing sufficient information in the
> > > KOBJ_ADD uevent so that udev can do the required work in user-space?
> > 
> > Consistency. If you have bluetooth on USB, it automatically works,
> > without userspace help. If we have mouse on USB, it automatically
> > works, etc...
> 
> My point is: why is the kernel/userspace distinction important?  As long as
> it "automatically works", does it really matter where the code is?

For some cases, it does, as "devices needed during boot". Someone is
going to attach keyboard or something powermanagement related, sooner
or later.

> We can put a little bit of code in the kernel (to report the details of the
> attached device) and a little bit of code in udev (to run hciattach) and it
> will still be automatic.

Of course, that's also possible. There will be parameters such as
speed / parity / flow control that will need to be passed, and
userland will still see /dev/ttySX device that it perhaps does not
need to see.

And there will be problems with devices such as bcm2048 on Nokia,
which is connected by a serial line and (interrupt capable) GPIO lines
and clocks. Rather than extending hciattach to pass the neccessary
GPIO/clock information and extending udev to pass GPIO/clock
information to hciattach (and extending kernel to pass it to udev and
accept from hciattach), it makes sense to just do it internally.
									Pavel
Alan Cox Jan. 5, 2015, 3:41 p.m. UTC | #16
> It would be really nice if the uart would register the line disciple as a
> child device, then the line discipline would register whatever it wants.

For almost every case this doesn't work. You need a tty interface as well
because thats how you manage it.

> But that isn't how it works.  The line discipline doesn't talk to the uart.
> Rather the tty layer talks to the uart (through tty_operations) and to the
> line discipline (through tty_ldisc_ops) and also registers the char_dev.

This is intentional. An ldisc has no business knowing what it's connected
to. Try running bluetooth over a tty/pty pair remotely to a dongle - and
you can do it or faking a GSM mux over a tty/pty pair for testing.

There are lots of cases where we know the correct ldisc from information
in the ACPI, DT or even USB identifiers in order to plug in the right
ldisc and daemon but I think that pretty much has to be in user space.
The kernel might be able to set an ldisc but it can't go around starting
bluetooth daemons, doing modem chats to go into mux mode or firing up
JMRI and java when it sees a Sprog. That's a job for systemd/udev.

Alan
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pavel Machek Jan. 5, 2015, 4:28 p.m. UTC | #17
On Mon 2015-01-05 15:41:41, One Thousand Gnomes wrote:
> > It would be really nice if the uart would register the line disciple as a
> > child device, then the line discipline would register whatever it wants.
> 
> For almost every case this doesn't work. You need a tty interface as well
> because thats how you manage it.
> 
> > But that isn't how it works.  The line discipline doesn't talk to the uart.
> > Rather the tty layer talks to the uart (through tty_operations) and to the
> > line discipline (through tty_ldisc_ops) and also registers the char_dev.
> 
> This is intentional. An ldisc has no business knowing what it's connected
> to. Try running bluetooth over a tty/pty pair remotely to a dongle - and
> you can do it or faking a GSM mux over a tty/pty pair for testing.

Not all cases are like that. IIRC Neil's hardware uses CTS/RTS in an
interesting way. bc2048 is connected to serial+clocks+gpios...

> There are lots of cases where we know the correct ldisc from information
> in the ACPI, DT or even USB identifiers in order to plug in the right
> ldisc and daemon but I think that pretty much has to be in user space.
> The kernel might be able to set an ldisc but it can't go around starting
> bluetooth daemons, doing modem chats to go into mux mode or firing up
> JMRI and java when it sees a Sprog. That's a job for systemd/udev.

No need to start bluetooth daemons: userspace can start them
itself. Just like in btusb case.

									Pavel
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/serial/of-serial.txt b/Documentation/devicetree/bindings/serial/of-serial.txt
index 8c4fd0332028..b59501ee2f21 100644
--- a/Documentation/devicetree/bindings/serial/of-serial.txt
+++ b/Documentation/devicetree/bindings/serial/of-serial.txt
@@ -39,6 +39,10 @@  Optional properties:
   driver is allowed to detect support for the capability even without this
   property.
 
+Optional child node:
+- a platform device listed as a child node will be probed and
+  powered-on whenever the tty is in use (open).
+
 Example:
 
 	uart@80230000 {
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 0508a1d8e4cd..7acdc6f093f4 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -95,6 +95,8 @@ 
 #include <linux/seq_file.h>
 #include <linux/serial.h>
 #include <linux/ratelimit.h>
+#include <linux/pm_runtime.h>
+#include <linux/of_platform.h>
 
 #include <linux/uaccess.h>
 
@@ -1683,6 +1685,17 @@  static int tty_release_checks(struct tty_struct *tty, struct tty_struct *o_tty,
 	return 0;
 }
 
+static int open_child(struct device *dev, void *data)
+{
+	pm_runtime_get_sync(dev);
+	return 0;
+}
+static int release_child(struct device *dev, void *data)
+{
+	pm_runtime_put_autosuspend(dev);
+	return 0;
+}
+
 /**
  *	tty_release		-	vfs callback for close
  *	@inode: inode of tty
@@ -1712,6 +1725,8 @@  int tty_release(struct inode *inode, struct file *filp)
 	long	timeout = 0;
 	int	once = 1;
 
+	if (tty->dev)
+		device_for_each_child(tty->dev, NULL, release_child);
 	if (tty_paranoia_check(tty, inode, __func__))
 		return 0;
 
@@ -2118,6 +2133,8 @@  retry_open:
 		__proc_set_tty(current, tty);
 	spin_unlock_irq(&current->sighand->siglock);
 	tty_unlock(tty);
+	if (tty->dev)
+		device_for_each_child(tty->dev, NULL, open_child);
 	mutex_unlock(&tty_mutex);
 	return 0;
 err_unlock:
@@ -3207,6 +3224,11 @@  struct device *tty_register_device_attr(struct tty_driver *driver,
 	retval = device_register(dev);
 	if (retval)
 		goto error;
+	if (device && device->of_node)
+		/* Children are platform devices and will be
+		 * runtime_pm managed by this tty.
+		 */
+		of_platform_populate(device->of_node, NULL, NULL, dev);
 
 	return dev;