Re: Turris Omnia firmware possibilities [Was: Re: led: hw-trigger, global brightness and multi-colored leds]

2018-05-25 Thread Tomas Hlavacek
On Fri, May 25, 2018 at 8:08 AM, Uwe Kleine-König <u...@kleine-koenig.org> 
wrote:
> Hello Tomas,
>
> On 05/25/2018 12:08 AM, Tomas Hlavacek wrote:
>> But I also have good news: The FW of the MCU is also OSS (see the repo
>> in the link (1)). There is a method for flashing the MCU over I2C from
>> Linux and there is JTAG connector for the MCU, in case un-bricking is
>> needed. Therefore the LED protocol can be changed to be more sensible
>> and/or it is even possible to emulate some existing HW LED driver chip
>> in Omnia MCU and reuse OSS driver for that chip.
>
> Yeah, I noticed, but when we start replacing the firmware, we'd need to
> detect somehow when a machine has an old (or only different) firmware.
> That would imply a versioning scheme and a generic way to read out the
> firmware version. (CMD_GET_FW_VERSION_BOOT is already a start, but this
> doesn't help me if I find an unknown hash.) So a CMD_GET_FW_SOMETHING
> that yields a version string that is similar to the soname of a library
> would be great.

Oh yes, I was actually trying to push rewrite of the FW before the
production started, but it looked like a redundant work and I rather
implemented the mentioned rule-breaking LED driver. Another good news
is that all the produced boards had the same FW image and there were
no (official and automated) updates so far. I think that in this
situation it is possible to re-write the firmware it if proves to be
the best solution for LED driver and fixing other glitches perhaps.
The only thing we need regarding versions we need is to either check
that we are upgrading the original version and/or consent from the
user to rewrite any other version that we might encounter. (If there
are some user-customized boards around.)

>
> Talking about firmware, I wonder if there is firmware supported needed
> to solve
> https://wiki.debian.org/InstallingDebianOn/TurrisOmnia#Power_Management
> . Didn't look into that deeply yet and probably not high prio given that
> normally the Turris Omnia will just run 7x24h.

That's right, there is no power-down signalization from the CPU right
now. Btw. is there any mechanism in kernel to signal over arbitrary
bus (like I2C) that the host is shutting down and the power can/should
be cut to CPU in N seconds?

Tomas


Re: Turris Omnia firmware possibilities [Was: Re: led: hw-trigger, global brightness and multi-colored leds]

2018-05-25 Thread Tomas Hlavacek
On Fri, May 25, 2018 at 8:08 AM, Uwe Kleine-König  
wrote:
> Hello Tomas,
>
> On 05/25/2018 12:08 AM, Tomas Hlavacek wrote:
>> But I also have good news: The FW of the MCU is also OSS (see the repo
>> in the link (1)). There is a method for flashing the MCU over I2C from
>> Linux and there is JTAG connector for the MCU, in case un-bricking is
>> needed. Therefore the LED protocol can be changed to be more sensible
>> and/or it is even possible to emulate some existing HW LED driver chip
>> in Omnia MCU and reuse OSS driver for that chip.
>
> Yeah, I noticed, but when we start replacing the firmware, we'd need to
> detect somehow when a machine has an old (or only different) firmware.
> That would imply a versioning scheme and a generic way to read out the
> firmware version. (CMD_GET_FW_VERSION_BOOT is already a start, but this
> doesn't help me if I find an unknown hash.) So a CMD_GET_FW_SOMETHING
> that yields a version string that is similar to the soname of a library
> would be great.

Oh yes, I was actually trying to push rewrite of the FW before the
production started, but it looked like a redundant work and I rather
implemented the mentioned rule-breaking LED driver. Another good news
is that all the produced boards had the same FW image and there were
no (official and automated) updates so far. I think that in this
situation it is possible to re-write the firmware it if proves to be
the best solution for LED driver and fixing other glitches perhaps.
The only thing we need regarding versions we need is to either check
that we are upgrading the original version and/or consent from the
user to rewrite any other version that we might encounter. (If there
are some user-customized boards around.)

>
> Talking about firmware, I wonder if there is firmware supported needed
> to solve
> https://wiki.debian.org/InstallingDebianOn/TurrisOmnia#Power_Management
> . Didn't look into that deeply yet and probably not high prio given that
> normally the Turris Omnia will just run 7x24h.

That's right, there is no power-down signalization from the CPU right
now. Btw. is there any mechanism in kernel to signal over arbitrary
bus (like I2C) that the host is shutting down and the power can/should
be cut to CPU in N seconds?

Tomas


Re: led: hw-trigger, global brightness and multi-colored leds

2018-05-24 Thread Tomas Hlavacek
Hi!

On Wed, May 2, 2018 at 5:11 PM, Uwe Kleine-König  wrote:
> Hello,
>
> on the Turris Omnia[1] the LEDs are controllable via an i2c device.
...
> Now I wonder how to match these two features to the LED device model. Do
> you have an idea?

That is an interesting question - I was quite clueless about that two
years ago - when I wrote the driver for Omnia LEDs
(https://github.com/tmshlvck/omnia-linux/blob/omnia/drivers/leds/leds-omnia.c).
I didn't even made an attempt to send it to upstream because it
obviously does not fit to the LED device model.

The fundamental problems were:

1) Sending commands over I2C to the MCU that drives LEDs is quite
slow. Therefore the interface is optimized for doing incremental
changes and batch changes. (Btw. the protocol description is here
https://gitlab.labs.nic.cz/hw/omnia_hw_ctrl/blob/master/turris_omnia_i2c_desc.adoc
).

2) "native" or autonomous mode means that MCU that drives LEDs take
independently wired (on/off) input from switch, PHY or PCI cards
without any kernel interaction, but color settings and brightness for
each individual LED are still active, just the on/off/blink trigger is
autonomous.

3) There is a global brightness (autonomous PWM control for cathode of
all LEDs - the best method for LED dimming, running on few MHz).

4) Per-LED brightness works, however PWM is running on just few
hundreds of kHz and when all LEDs are dimmed and you watch carefully,
you can see intermittent flickering.

5) The abstraction in the protocol (mentioned in (1)) is actually
counting 3 LEDs (separate RGB) as one arbitrary-color LED. The reason
was to save bandwidth on I2C I guess, because color is expected to
change less frequently than brightness.

But I also have good news: The FW of the MCU is also OSS (see the repo
in the link (1)). There is a method for flashing the MCU over I2C from
Linux and there is JTAG connector for the MCU, in case un-bricking is
needed. Therefore the LED protocol can be changed to be more sensible
and/or it is even possible to emulate some existing HW LED driver chip
in Omnia MCU and reuse OSS driver for that chip.

Tomas


Re: led: hw-trigger, global brightness and multi-colored leds

2018-05-24 Thread Tomas Hlavacek
Hi!

On Wed, May 2, 2018 at 5:11 PM, Uwe Kleine-König  wrote:
> Hello,
>
> on the Turris Omnia[1] the LEDs are controllable via an i2c device.
...
> Now I wonder how to match these two features to the LED device model. Do
> you have an idea?

That is an interesting question - I was quite clueless about that two
years ago - when I wrote the driver for Omnia LEDs
(https://github.com/tmshlvck/omnia-linux/blob/omnia/drivers/leds/leds-omnia.c).
I didn't even made an attempt to send it to upstream because it
obviously does not fit to the LED device model.

The fundamental problems were:

1) Sending commands over I2C to the MCU that drives LEDs is quite
slow. Therefore the interface is optimized for doing incremental
changes and batch changes. (Btw. the protocol description is here
https://gitlab.labs.nic.cz/hw/omnia_hw_ctrl/blob/master/turris_omnia_i2c_desc.adoc
).

2) "native" or autonomous mode means that MCU that drives LEDs take
independently wired (on/off) input from switch, PHY or PCI cards
without any kernel interaction, but color settings and brightness for
each individual LED are still active, just the on/off/blink trigger is
autonomous.

3) There is a global brightness (autonomous PWM control for cathode of
all LEDs - the best method for LED dimming, running on few MHz).

4) Per-LED brightness works, however PWM is running on just few
hundreds of kHz and when all LEDs are dimmed and you watch carefully,
you can see intermittent flickering.

5) The abstraction in the protocol (mentioned in (1)) is actually
counting 3 LEDs (separate RGB) as one arbitrary-color LED. The reason
was to save bandwidth on I2C I guess, because color is expected to
change less frequently than brightness.

But I also have good news: The FW of the MCU is also OSS (see the repo
in the link (1)). There is a method for flashing the MCU over I2C from
Linux and there is JTAG connector for the MCU, in case un-bricking is
needed. Therefore the LED protocol can be changed to be more sensible
and/or it is even possible to emulate some existing HW LED driver chip
in Omnia MCU and reuse OSS driver for that chip.

Tomas


rtl8723bs memory leak

2017-06-12 Thread Tomas Hlavacek

Hello!

It seems that we have discovered a memory leak in the rtl8723bs driver. 
The problem is that when the SDIO read fails in sd_recv_rxfifo() (in 
drivers/staging/rtl8723bs/hal/sdio_ops.c, l1016) the function simply 
returns NULL, but the dequeued recvbuf is never returned to the 
precvpriv->free_recv_buf_queue.


After several SDIO read failures it would bleed off the recvbuf queue 
and it would subsequently stop processing packets while producing 
endless flow of messages like this:


[   49.618639] RTL8723BS: ERROR sd_recv_rxfifo: alloc recvbuf FAIL!
[   49.624340] RTL8723BS: ERROR precvbuf is Null for 8 times because 
alloc memory failed

[   49.641654] RTL8723BS: ERROR sd_recv_rxfifo: alloc recvbuf FAIL!
[   49.648015] RTL8723BS: ERROR precvbuf is Null for 9 times because 
alloc memory failed

[   49.665105] RTL8723BS: ERROR sd_recv_rxfifo: alloc recvbuf FAIL!
[   49.671474] RTL8723BS: ERROR precvbuf is Null for 10 times because 
alloc memory failed
[   49.679394] RTL8723BS: ERROR exit because alloc memory failed more 
than 10 times

...

A possible fix might look like the following (however, this is only my 
testing hot-fix to make the driver work and I have to admit that I do 
not fully understand the whole thing - that's why I am not posting a 
patch at this point):


diff --git a/drivers/staging/rtl8723bs/hal/sdio_ops.c 
b/drivers/staging/rtl8723bs/hal/sdio_ops.c

index 6285b72faa9a..ad65cd74c3c8 100644
--- a/drivers/staging/rtl8723bs/hal/sdio_ops.c
+++ b/drivers/staging/rtl8723bs/hal/sdio_ops.c
@@ -1008,6 +1008,7 @@ static struct recv_buf *sd_recv_rxfifo(struct 
adapter *padapter, u32 size)

}

if (precvbuf->pskb == NULL) {
+   rtw_enqueue_recvbuf(precvbuf, 
>free_recv_buf_queue);
DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, 
readsize);
return NULL;
}
@@ -1017,6 +1018,7 @@ static struct recv_buf *sd_recv_rxfifo(struct 
adapter *padapter, u32 size)

preadbuf = precvbuf->pskb->data;
	ret = sdio_read_port(>iopriv.intf, WLAN_RX0FF_DEVICE_ID, 
readsize, preadbuf);

if (ret == _FAIL) {
+   rtw_enqueue_recvbuf(precvbuf, >free_recv_buf_queue);
		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", 
__func__));

return NULL;
}

Cheers,
Tomas



rtl8723bs memory leak

2017-06-12 Thread Tomas Hlavacek

Hello!

It seems that we have discovered a memory leak in the rtl8723bs driver. 
The problem is that when the SDIO read fails in sd_recv_rxfifo() (in 
drivers/staging/rtl8723bs/hal/sdio_ops.c, l1016) the function simply 
returns NULL, but the dequeued recvbuf is never returned to the 
precvpriv->free_recv_buf_queue.


After several SDIO read failures it would bleed off the recvbuf queue 
and it would subsequently stop processing packets while producing 
endless flow of messages like this:


[   49.618639] RTL8723BS: ERROR sd_recv_rxfifo: alloc recvbuf FAIL!
[   49.624340] RTL8723BS: ERROR precvbuf is Null for 8 times because 
alloc memory failed

[   49.641654] RTL8723BS: ERROR sd_recv_rxfifo: alloc recvbuf FAIL!
[   49.648015] RTL8723BS: ERROR precvbuf is Null for 9 times because 
alloc memory failed

[   49.665105] RTL8723BS: ERROR sd_recv_rxfifo: alloc recvbuf FAIL!
[   49.671474] RTL8723BS: ERROR precvbuf is Null for 10 times because 
alloc memory failed
[   49.679394] RTL8723BS: ERROR exit because alloc memory failed more 
than 10 times

...

A possible fix might look like the following (however, this is only my 
testing hot-fix to make the driver work and I have to admit that I do 
not fully understand the whole thing - that's why I am not posting a 
patch at this point):


diff --git a/drivers/staging/rtl8723bs/hal/sdio_ops.c 
b/drivers/staging/rtl8723bs/hal/sdio_ops.c

index 6285b72faa9a..ad65cd74c3c8 100644
--- a/drivers/staging/rtl8723bs/hal/sdio_ops.c
+++ b/drivers/staging/rtl8723bs/hal/sdio_ops.c
@@ -1008,6 +1008,7 @@ static struct recv_buf *sd_recv_rxfifo(struct 
adapter *padapter, u32 size)

}

if (precvbuf->pskb == NULL) {
+   rtw_enqueue_recvbuf(precvbuf, 
>free_recv_buf_queue);
DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, 
readsize);
return NULL;
}
@@ -1017,6 +1018,7 @@ static struct recv_buf *sd_recv_rxfifo(struct 
adapter *padapter, u32 size)

preadbuf = precvbuf->pskb->data;
	ret = sdio_read_port(>iopriv.intf, WLAN_RX0FF_DEVICE_ID, 
readsize, preadbuf);

if (ret == _FAIL) {
+   rtw_enqueue_recvbuf(precvbuf, >free_recv_buf_queue);
		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", 
__func__));

return NULL;
}

Cheers,
Tomas



Re: [RFC PATCH] ARM: dts: Add support for Turris Omnia

2016-11-25 Thread Tomas Hlavacek

Hi!

On Thu, Nov 24, 2016 at 4:07 PM, Andrew Lunn  wrote:
 @Tomas: I think it doesn't make sense when we alternate sending 
patches
 without prior arrangement. Do you already work on a v5? If not I 
can do

 that to fix the last few comments. Not sure when a submission is too
 late to enter v4.10, but I think the window isn't that big any more.


It is getting a bit late. But maybe Linus will add in another -rc
week.



 > No leds? No buttons via gpio-keys?

 The leds are controlled by a Cortex-M0 and without intervention 
blink
 according to a hardware function (network, power, pci). IMHO that's 
ok

 for an initial setup.


Yes. That is fine. It is just unusual. Most boards have gpio-led and
gpio-keys, which are easy to add. That is why i asked. Adding an LED
driver which talks to this M0 can be added later.


Actually the WiP driver for MCU LED interface, that we use in our 
kernel is here: 
https://github.com/tmshlvck/omnia-linux/commit/2121afd8fbd2e4c720edcdd472b11b5303bc0dfb


It definitely needs some cleanup and it adds non-standard features 
(main PWM for all LEDs, autonomous blink mode, colors) via custom /sys 
files, which I suspect that is not going to be acceptable for upstream. 
Let's keep it for the next iteration.


Regarding the button, we actually have one, that is connected to the 
MCU and by default it sets LED brigtness autonomously, but it should be 
able to generate IRQs via the MCU if we change the mode in the MCU. 
I'll look into that.


Tomas



Re: [RFC PATCH] ARM: dts: Add support for Turris Omnia

2016-11-25 Thread Tomas Hlavacek

Hi!

On Thu, Nov 24, 2016 at 4:07 PM, Andrew Lunn  wrote:
 @Tomas: I think it doesn't make sense when we alternate sending 
patches
 without prior arrangement. Do you already work on a v5? If not I 
can do

 that to fix the last few comments. Not sure when a submission is too
 late to enter v4.10, but I think the window isn't that big any more.


It is getting a bit late. But maybe Linus will add in another -rc
week.



 > No leds? No buttons via gpio-keys?

 The leds are controlled by a Cortex-M0 and without intervention 
blink
 according to a hardware function (network, power, pci). IMHO that's 
ok

 for an initial setup.


Yes. That is fine. It is just unusual. Most boards have gpio-led and
gpio-keys, which are easy to add. That is why i asked. Adding an LED
driver which talks to this M0 can be added later.


Actually the WiP driver for MCU LED interface, that we use in our 
kernel is here: 
https://github.com/tmshlvck/omnia-linux/commit/2121afd8fbd2e4c720edcdd472b11b5303bc0dfb


It definitely needs some cleanup and it adds non-standard features 
(main PWM for all LEDs, autonomous blink mode, colors) via custom /sys 
files, which I suspect that is not going to be acceptable for upstream. 
Let's keep it for the next iteration.


Regarding the button, we actually have one, that is connected to the 
MCU and by default it sets LED brigtness autonomously, but it should be 
able to generate IRQs via the MCU if we change the mode in the MCU. 
I'll look into that.


Tomas



[RFC PATCH] ARM: dts: Add support for Turris Omnia

2016-11-22 Thread Tomas Hlavacek
Turris Omnia board by CZ.NIC:

  * Marvell Armada 385 SoC
  * 1 or 2 GB DDR3
  * eMMC
  * 8 MB SPI flash (U-Boot and rescue Linux image)
  * 88E1514 PHY
  * 88E6176 Ethernet switch (not supported)

Supported board revision: CZ11NIC13 (production board).

Signed-off-by: Tomas Hlavacek <tmshl...@gmail.com>
---
Changes since Uwe's version:

- add MBUS regions (needed for Marvell CESA)
- remove rtc disable (WFM with CZ11NIC13 = production board)
- cleanup comments

Unsupported peripherals:
- MV88E7176 switch
- SFP
- LEDs

---
 arch/arm/boot/dts/Makefile|   1 +
 arch/arm/boot/dts/armada-385-turris-omnia.dts | 279 ++
 2 files changed, 280 insertions(+)
 create mode 100644 arch/arm/boot/dts/armada-385-turris-omnia.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index befcd26..f1d3b9ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -920,6 +920,7 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \
armada-385-db-ap.dtb \
armada-385-linksys-caiman.dtb \
armada-385-linksys-cobra.dtb \
+   armada-385-turris-omnia.dtb \
armada-388-clearfog.dtb \
armada-388-db.dtb \
armada-388-gp.dtb \
diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts 
b/arch/arm/boot/dts/armada-385-turris-omnia.dts
new file mode 100644
index 000..5ef3d62
--- /dev/null
+++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts
@@ -0,0 +1,279 @@
+/*
+ * Device Tree file for the Turris Omnia
+ * Schematic available at https://www.turris.cz/doc/_media/rtrom01-schema.pdf
+ *
+ * Copyright (C) 2016 Uwe Kleine-König <u...@kleine-koenig.org>
+ * Copyright (C) 2016 Tomas Hlavacek <tmshl...@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include 
+#include 
+#include "armada-385.dtsi"
+
+/ {
+   model = "Turris Omnia";
+   compatible = "cznic,turris-omnia", "marvell,armada385", \
+   "marvell,armada380";
+
+   chosen {
+   stdout-path = 
+   };
+
+   memory {
+   device_type = "memory";
+   reg = <0x 0x4000>; /* 1024 MB */
+   };
+
+   soc {
+   ranges = <MBUS_ID(0xf0, 0x01) 0 0xf100 0x10
+ MBUS_ID(0x01, 0x1d) 0 0xfff0 0x10
+ MBUS_ID(0x09, 0x19) 0 0xf110 0x1
+ MBUS_ID(0x09, 0x15) 0 0xf111 0x1>;
+
+   internal-regs {
+
+   /* USB part of the PCIe2/USB 2.0 port */
+   usb@58000 {
+   status = "okay";
+   };
+
+   sata@a8000 {
+   status = "okay";
+   };
+
+   sdhci@d8000 {
+   pinctrl-names = "default";
+   pinctrl-0 = <_pins>;
+   status = "okay";
+
+   bus-width = <8>;
+   no-1-8-v;
+   non-removable;
+   };
+
+   us

[RFC PATCH] ARM: dts: Add support for Turris Omnia

2016-11-22 Thread Tomas Hlavacek
Turris Omnia board by CZ.NIC:

  * Marvell Armada 385 SoC
  * 1 or 2 GB DDR3
  * eMMC
  * 8 MB SPI flash (U-Boot and rescue Linux image)
  * 88E1514 PHY
  * 88E6176 Ethernet switch (not supported)

Supported board revision: CZ11NIC13 (production board).

Signed-off-by: Tomas Hlavacek 
---
Changes since Uwe's version:

- add MBUS regions (needed for Marvell CESA)
- remove rtc disable (WFM with CZ11NIC13 = production board)
- cleanup comments

Unsupported peripherals:
- MV88E7176 switch
- SFP
- LEDs

---
 arch/arm/boot/dts/Makefile|   1 +
 arch/arm/boot/dts/armada-385-turris-omnia.dts | 279 ++
 2 files changed, 280 insertions(+)
 create mode 100644 arch/arm/boot/dts/armada-385-turris-omnia.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index befcd26..f1d3b9ff 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -920,6 +920,7 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \
armada-385-db-ap.dtb \
armada-385-linksys-caiman.dtb \
armada-385-linksys-cobra.dtb \
+   armada-385-turris-omnia.dtb \
armada-388-clearfog.dtb \
armada-388-db.dtb \
armada-388-gp.dtb \
diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts 
b/arch/arm/boot/dts/armada-385-turris-omnia.dts
new file mode 100644
index 000..5ef3d62
--- /dev/null
+++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts
@@ -0,0 +1,279 @@
+/*
+ * Device Tree file for the Turris Omnia
+ * Schematic available at https://www.turris.cz/doc/_media/rtrom01-schema.pdf
+ *
+ * Copyright (C) 2016 Uwe Kleine-König 
+ * Copyright (C) 2016 Tomas Hlavacek 
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include 
+#include 
+#include "armada-385.dtsi"
+
+/ {
+   model = "Turris Omnia";
+   compatible = "cznic,turris-omnia", "marvell,armada385", \
+   "marvell,armada380";
+
+   chosen {
+   stdout-path = 
+   };
+
+   memory {
+   device_type = "memory";
+   reg = <0x 0x4000>; /* 1024 MB */
+   };
+
+   soc {
+   ranges = ;
+
+   internal-regs {
+
+   /* USB part of the PCIe2/USB 2.0 port */
+   usb@58000 {
+   status = "okay";
+   };
+
+   sata@a8000 {
+   status = "okay";
+   };
+
+   sdhci@d8000 {
+   pinctrl-names = "default";
+   pinctrl-0 = <_pins>;
+   status = "okay";
+
+   bus-width = <8>;
+   no-1-8-v;
+   non-removable;
+   };
+
+   usb3@f {
+   status = "okay";
+   };
+
+   usb3@f8000 {
+   status = "okay";
+   };
+   };
+
+   pcie-controller {
+   status = "okay";
+
+   

[PATCH v2] mtd: fsl_elbc_nand Add ECC mode selection in DT

2015-05-21 Thread Tomas Hlavacek
Add device tree pointer to chip structure in order to allow turn off the
HW ECC and force own ECC mode and ECC parameters. Newly supported entries
are as per documentation: nand-ecc-mode, nand-ecc-step-size
and nand-ecc-strength.

Add RNDOUT operation which is required for SOFT and SOFT_BCH modes.

Do not set write_subpage function pointer from the driver when it
initializes in SOFT and SOFT_BCH modes.

Signed-off-by: Tomas Hlavacek 
---
 drivers/mtd/nand/fsl_elbc_nand.c | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 04b22fd..b6cdda6 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -335,6 +335,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, 
unsigned int command,
fsl_elbc_run_command(mtd);
return;
 
+   case NAND_CMD_RNDOUT:
+   dev_vdbg(priv->dev,
+   "fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n",
+   column);
+
+   elbc_fcm_ctrl->index = column;
+   return;
+
/* READOOB reads only the OOB because no ECC is performed. */
case NAND_CMD_READOOB:
dev_vdbg(priv->dev,
@@ -656,6 +664,10 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip->ecc.steps);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
chip->ecc.bytes);
+   dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.size = %d\n",
+   chip->ecc.size);
+   dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.strength = %d\n",
+   chip->ecc.strength);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
chip->ecc.total);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
@@ -677,8 +689,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
priv->page_size = 1;
setbits32(>bank[priv->bank].or, OR_FCM_PGS);
/* adjust ecc setup if needed */
-   if ((in_be32(>bank[priv->bank].br) & BR_DECC) ==
-   BR_DECC_CHK_GEN) {
+   if (((in_be32(>bank[priv->bank].br) & BR_DECC) ==
+   BR_DECC_CHK_GEN) && (chip->ecc.mode == NAND_ECC_HW)) {
chip->ecc.size = 512;
chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
   _elbc_oob_lp_eccm1 :
@@ -742,6 +754,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct nand_chip *chip = >chip;
+   struct device_node *node = priv->dev->of_node;
 
dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
 
@@ -749,6 +762,9 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
priv->mtd.priv = chip;
priv->mtd.owner = THIS_MODULE;
 
+   /* Fill in OF node */
+   chip->dn = node;
+
/* set timeout to maximum */
priv->fmr = 15 << FMR_CWTO_SHIFT;
if (in_be32(>bank[priv->bank].or) & OR_FCM_PGS)
@@ -774,7 +790,6 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 
chip->ecc.read_page = fsl_elbc_read_page;
chip->ecc.write_page = fsl_elbc_write_page;
-   chip->ecc.write_subpage = fsl_elbc_write_subpage;
 
/* If CS Base Register selects full hardware ECC then use it */
if ((in_be32(>bank[priv->bank].br) & BR_DECC) ==
@@ -786,6 +801,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
chip->ecc.size = 512;
chip->ecc.bytes = 3;
chip->ecc.strength = 1;
+   chip->ecc.write_subpage = fsl_elbc_write_subpage;
} else {
/* otherwise fall back to default software ECC */
chip->ecc.mode = NAND_ECC_SOFT;
-- 
2.1.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 at  http://www.tux.org/lkml/


[PATCH v2] mtd: fsl_elbc_nand Add ECC mode selection in DT

2015-05-21 Thread Tomas Hlavacek
Add device tree pointer to chip structure in order to allow turn off the
HW ECC and force own ECC mode and ECC parameters. Newly supported entries
are as per documentation: nand-ecc-mode, nand-ecc-step-size
and nand-ecc-strength.

Add RNDOUT operation which is required for SOFT and SOFT_BCH modes.

Do not set write_subpage function pointer from the driver when it
initializes in SOFT and SOFT_BCH modes.

Signed-off-by: Tomas Hlavacek tmshl...@gmail.com
---
 drivers/mtd/nand/fsl_elbc_nand.c | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 04b22fd..b6cdda6 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -335,6 +335,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, 
unsigned int command,
fsl_elbc_run_command(mtd);
return;
 
+   case NAND_CMD_RNDOUT:
+   dev_vdbg(priv-dev,
+   fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n,
+   column);
+
+   elbc_fcm_ctrl-index = column;
+   return;
+
/* READOOB reads only the OOB because no ECC is performed. */
case NAND_CMD_READOOB:
dev_vdbg(priv-dev,
@@ -656,6 +664,10 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip-ecc.steps);
dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.bytes = %d\n,
chip-ecc.bytes);
+   dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.size = %d\n,
+   chip-ecc.size);
+   dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.strength = %d\n,
+   chip-ecc.strength);
dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.total = %d\n,
chip-ecc.total);
dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.layout = %p\n,
@@ -677,8 +689,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
priv-page_size = 1;
setbits32(lbc-bank[priv-bank].or, OR_FCM_PGS);
/* adjust ecc setup if needed */
-   if ((in_be32(lbc-bank[priv-bank].br)  BR_DECC) ==
-   BR_DECC_CHK_GEN) {
+   if (((in_be32(lbc-bank[priv-bank].br)  BR_DECC) ==
+   BR_DECC_CHK_GEN)  (chip-ecc.mode == NAND_ECC_HW)) {
chip-ecc.size = 512;
chip-ecc.layout = (priv-fmr  FMR_ECCM) ?
   fsl_elbc_oob_lp_eccm1 :
@@ -742,6 +754,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
struct fsl_lbc_regs __iomem *lbc = ctrl-regs;
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl-nand;
struct nand_chip *chip = priv-chip;
+   struct device_node *node = priv-dev-of_node;
 
dev_dbg(priv-dev, eLBC Set Information for bank %d\n, priv-bank);
 
@@ -749,6 +762,9 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
priv-mtd.priv = chip;
priv-mtd.owner = THIS_MODULE;
 
+   /* Fill in OF node */
+   chip-dn = node;
+
/* set timeout to maximum */
priv-fmr = 15  FMR_CWTO_SHIFT;
if (in_be32(lbc-bank[priv-bank].or)  OR_FCM_PGS)
@@ -774,7 +790,6 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 
chip-ecc.read_page = fsl_elbc_read_page;
chip-ecc.write_page = fsl_elbc_write_page;
-   chip-ecc.write_subpage = fsl_elbc_write_subpage;
 
/* If CS Base Register selects full hardware ECC then use it */
if ((in_be32(lbc-bank[priv-bank].br)  BR_DECC) ==
@@ -786,6 +801,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
chip-ecc.size = 512;
chip-ecc.bytes = 3;
chip-ecc.strength = 1;
+   chip-ecc.write_subpage = fsl_elbc_write_subpage;
} else {
/* otherwise fall back to default software ECC */
chip-ecc.mode = NAND_ECC_SOFT;
-- 
2.1.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 at  http://www.tux.org/lkml/


[RFC] mtd: fsl_elbc_nand Add ECC mode selection in DT

2015-04-22 Thread Tomas Hlavacek
Add device tree parameters to turn off the HW ECC and force own ECC mode
and ECC parameters. New entries are: nand-ecc-mode, nand-ecc-step-size
and nand-ecc-strength.

Add RNDOUT operation which is required for SOFT and SOFT_BCH modes.

Do not set write_subpage function pointer from the driver when it initializes
in SOFT and SOFT_BCH modes.

Signed-off-by: Tomas Hlavacek 
---
 drivers/mtd/nand/fsl_elbc_nand.c | 47 +---
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 04b22fd..76ab2e2 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -335,6 +335,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, 
unsigned int command,
fsl_elbc_run_command(mtd);
return;
 
+   case NAND_CMD_RNDOUT:
+   dev_vdbg(priv->dev,
+"fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n",
+column);
+
+   elbc_fcm_ctrl->index = column;
+   return;
+
/* READOOB reads only the OOB because no ECC is performed. */
case NAND_CMD_READOOB:
dev_vdbg(priv->dev,
@@ -656,6 +664,10 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip->ecc.steps);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
chip->ecc.bytes);
+   dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.size = %d\n",
+   chip->ecc.size);
+   dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.strength = %d\n",
+   chip->ecc.strength);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
chip->ecc.total);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
@@ -677,8 +689,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
priv->page_size = 1;
setbits32(>bank[priv->bank].or, OR_FCM_PGS);
/* adjust ecc setup if needed */
-   if ((in_be32(>bank[priv->bank].br) & BR_DECC) ==
-   BR_DECC_CHK_GEN) {
+   if (((in_be32(>bank[priv->bank].br) & BR_DECC) ==
+   BR_DECC_CHK_GEN) && (chip->ecc.mode == NAND_ECC_HW)) {
chip->ecc.size = 512;
chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
   _elbc_oob_lp_eccm1 :
@@ -742,6 +754,8 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
struct nand_chip *chip = >chip;
+   struct device_node *node = priv->dev->of_node;
+   const char *ecc_mode;
 
dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
 
@@ -774,11 +788,38 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 
chip->ecc.read_page = fsl_elbc_read_page;
chip->ecc.write_page = fsl_elbc_write_page;
-   chip->ecc.write_subpage = fsl_elbc_write_subpage;
+
+   /* Override default HW ECC according to settings in DT */
+   if (!of_property_read_string(node, "nand-ecc-mode", _mode)) {
+   if (!strncmp("none", ecc_mode, 4)) {
+   chip->ecc.mode = NAND_ECC_NONE;
+   return 0;
+   }
+
+   if (!strncmp("soft_bch", ecc_mode, 8)) {
+   chip->ecc.mode = NAND_ECC_SOFT_BCH;
+   chip->ecc.size = 512;
+   chip->ecc.strength = 4;
+
+   of_property_read_u32(node, "nand-ecc-step-size",
+   >ecc.size);
+   of_property_read_u32(node, "nand-ecc-strength",
+   >ecc.strength);
+   chip->ecc.bytes = ((fls(1+8*chip->ecc.size)*
+   chip->ecc.strength)/8);
+   return 0;
+   }
+
+   if (!strncmp("soft", ecc_mode, 4)) {
+   chip->ecc.mode = NAND_ECC_SOFT;
+   return 0;
+   }
+   }
 
/* If CS Base Register selects full hardware ECC then use it */
if ((in_be32(>bank[priv->bank].br) & BR_DECC) ==
BR_DECC_CHK_GEN) {
+   chip->ecc.write_subpage = fsl_elbc_write_subpage;
chip->ecc.mode = NAND_ECC_HW;
/* put in small page settings and adjust later if needed */
chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
-- 
2.1.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 at  http://www.tux.org/lkml/


[RFC] mtd: fsl_elbc_nand Add ECC mode selection in DT

2015-04-22 Thread Tomas Hlavacek
Add device tree parameters to turn off the HW ECC and force own ECC mode
and ECC parameters. New entries are: nand-ecc-mode, nand-ecc-step-size
and nand-ecc-strength.

Add RNDOUT operation which is required for SOFT and SOFT_BCH modes.

Do not set write_subpage function pointer from the driver when it initializes
in SOFT and SOFT_BCH modes.

Signed-off-by: Tomas Hlavacek tmshl...@gmail.com
---
 drivers/mtd/nand/fsl_elbc_nand.c | 47 +---
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 04b22fd..76ab2e2 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -335,6 +335,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, 
unsigned int command,
fsl_elbc_run_command(mtd);
return;
 
+   case NAND_CMD_RNDOUT:
+   dev_vdbg(priv-dev,
+fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n,
+column);
+
+   elbc_fcm_ctrl-index = column;
+   return;
+
/* READOOB reads only the OOB because no ECC is performed. */
case NAND_CMD_READOOB:
dev_vdbg(priv-dev,
@@ -656,6 +664,10 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip-ecc.steps);
dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.bytes = %d\n,
chip-ecc.bytes);
+   dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.size = %d\n,
+   chip-ecc.size);
+   dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.strength = %d\n,
+   chip-ecc.strength);
dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.total = %d\n,
chip-ecc.total);
dev_dbg(priv-dev, fsl_elbc_init: nand-ecc.layout = %p\n,
@@ -677,8 +689,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
priv-page_size = 1;
setbits32(lbc-bank[priv-bank].or, OR_FCM_PGS);
/* adjust ecc setup if needed */
-   if ((in_be32(lbc-bank[priv-bank].br)  BR_DECC) ==
-   BR_DECC_CHK_GEN) {
+   if (((in_be32(lbc-bank[priv-bank].br)  BR_DECC) ==
+   BR_DECC_CHK_GEN)  (chip-ecc.mode == NAND_ECC_HW)) {
chip-ecc.size = 512;
chip-ecc.layout = (priv-fmr  FMR_ECCM) ?
   fsl_elbc_oob_lp_eccm1 :
@@ -742,6 +754,8 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
struct fsl_lbc_regs __iomem *lbc = ctrl-regs;
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl-nand;
struct nand_chip *chip = priv-chip;
+   struct device_node *node = priv-dev-of_node;
+   const char *ecc_mode;
 
dev_dbg(priv-dev, eLBC Set Information for bank %d\n, priv-bank);
 
@@ -774,11 +788,38 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 
chip-ecc.read_page = fsl_elbc_read_page;
chip-ecc.write_page = fsl_elbc_write_page;
-   chip-ecc.write_subpage = fsl_elbc_write_subpage;
+
+   /* Override default HW ECC according to settings in DT */
+   if (!of_property_read_string(node, nand-ecc-mode, ecc_mode)) {
+   if (!strncmp(none, ecc_mode, 4)) {
+   chip-ecc.mode = NAND_ECC_NONE;
+   return 0;
+   }
+
+   if (!strncmp(soft_bch, ecc_mode, 8)) {
+   chip-ecc.mode = NAND_ECC_SOFT_BCH;
+   chip-ecc.size = 512;
+   chip-ecc.strength = 4;
+
+   of_property_read_u32(node, nand-ecc-step-size,
+   chip-ecc.size);
+   of_property_read_u32(node, nand-ecc-strength,
+   chip-ecc.strength);
+   chip-ecc.bytes = ((fls(1+8*chip-ecc.size)*
+   chip-ecc.strength)/8);
+   return 0;
+   }
+
+   if (!strncmp(soft, ecc_mode, 4)) {
+   chip-ecc.mode = NAND_ECC_SOFT;
+   return 0;
+   }
+   }
 
/* If CS Base Register selects full hardware ECC then use it */
if ((in_be32(lbc-bank[priv-bank].br)  BR_DECC) ==
BR_DECC_CHK_GEN) {
+   chip-ecc.write_subpage = fsl_elbc_write_subpage;
chip-ecc.mode = NAND_ECC_HW;
/* put in small page settings and adjust later if needed */
chip-ecc.layout = (priv-fmr  FMR_ECCM) ?
-- 
2.1.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 at  http://www.tux.org/lkml/


Re: [PATCH] tty_register_device_attr updated for tty-next

2012-09-06 Thread Tomas Hlavacek
Hello!

On Thu, Sep 6, 2012 at 11:17 PM, Tomas Hlavacek  wrote:
> Added tty_device_create_release() and bound to dev->release in
> tty_register_device_attr().
> Added tty_port_register_device_attr() and used in uart_add_one_port()
> instead of tty_register_device_attr().
>
> Signed-off-by: Tomas Hlavacek 
> ---
>  drivers/tty/serial/serial_core.c |8 
>  drivers/tty/tty_io.c |7 +++
>  drivers/tty/tty_port.c   |   24 
>  include/linux/tty.h  |4 
>  4 files changed, 39 insertions(+), 4 deletions(-)
>

A little bit more explanation regarding this patch: It fixes two
problems with my previous patch (tty: uartclk value from serial_core
exposed to sysfs) which Jiri has pointed out earlier today. Both are
related to the changed interface in the tty-next branch and both
should have been dealt with in the first patch. It also fixes minor
problems (one const keyword added and newlines rearranged in the
uart_get_attr_uartclk() function).

Tomas
--
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/


[PATCH] tty_register_device_attr updated for tty-next

2012-09-06 Thread Tomas Hlavacek
Added tty_device_create_release() and bound to dev->release in
tty_register_device_attr().
Added tty_port_register_device_attr() and used in uart_add_one_port()
instead of tty_register_device_attr().

Signed-off-by: Tomas Hlavacek 
---
 drivers/tty/serial/serial_core.c |8 
 drivers/tty/tty_io.c |7 +++
 drivers/tty/tty_port.c   |   24 
 include/linux/tty.h  |4 
 4 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index f629bdf..046279c 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2313,9 +2313,9 @@ 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(>port.mutex);
ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
mutex_unlock(>port.mutex);
@@ -2330,7 +2330,7 @@ static struct attribute *tty_dev_attrs[] = {
NULL,
};
 
-static struct attribute_group tty_dev_attr_group = {
+static const struct attribute_group tty_dev_attr_group = {
.attrs = tty_dev_attrs,
};
 
@@ -2392,8 +2392,8 @@ 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.
 */
-   tty_dev = tty_register_device_attr(drv->tty_driver, uport->line,
-   uport->dev, port, tty_dev_attr_groups);
+   tty_dev = tty_port_register_device_attr(port, 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 dcb30d5..8a5a8b0 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3045,6 +3045,12 @@ struct device *tty_register_device(struct tty_driver 
*driver, unsigned index,
 }
 EXPORT_SYMBOL(tty_register_device);
 
+static void tty_device_create_release(struct device *dev)
+{
+   pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
+   kfree(dev);
+}
+
 /**
  * tty_register_device_attr - register a tty device
  * @driver: the tty driver that describes the tty device
@@ -3103,6 +3109,7 @@ struct device *tty_register_device_attr(struct tty_driver 
*driver,
dev->devt = devt;
dev->class = tty_class;
dev->parent = device;
+   dev->release = tty_device_create_release;
dev_set_name(dev, "%s", name);
dev->groups = attr_grp;
dev_set_drvdata(dev, drvdata);
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 96302f4..d7bdd8d 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -73,6 +73,30 @@ struct device *tty_port_register_device(struct tty_port 
*port,
 }
 EXPORT_SYMBOL_GPL(tty_port_register_device);
 
+/**
+ * tty_port_register_device_attr - register tty device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ * @device: parent if exists, otherwise NULL
+ * @drvdata: Driver data to be set to device.
+ * @attr_grp: Attribute group to be set on device.
+ *
+ * It is the same as tty_register_device_attr except the provided @port is
+ * linked to a concrete tty specified by @index. Use this or tty_port_install
+ * (or both). Call tty_port_link_device as a last resort.
+ */
+struct device *tty_port_register_device_attr(struct tty_port *port,
+   struct tty_driver *driver, unsigned index,
+   struct device *device, void *drvdata,
+   const struct attribute_group **attr_grp)
+{
+   tty_port_link_device(port, driver, index);
+   return tty_register_device_attr(driver, index, device, drvdata,
+   attr_grp);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
+
 int tty_port_alloc_xmit_buf(struct tty_port *port)
 {
/* We may sleep in get_zeroed_page() */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 599d603..1509b86 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -507,6 +507,10 @@ extern void tty_port_link_device(struct tty_port *port,
 extern struct device *tty_port_register_device(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device);
+extern struct device *tty_port_register_device_attr(struct tty_port *port,
+   struct tty_driver *driver, unsigned index,
+   struct device *device, void *drvdata,
+   const struct attribute_group **attr_

Re: [PATCH v6] uartclk value from serial_core exposed to sysfs

2012-09-06 Thread Tomas Hlavacek
Hello!

On Thu, Sep 6, 2012 at 8:54 PM, Jiri Slaby  wrote:
> On 09/06/2012 08:39 PM, Tomas Hlavacek wrote:
>> On Thu, Sep 6, 2012 at 7:54 PM, Jiri Slaby  wrote:
>>> On 09/06/2012 03:17 AM, Tomas Hlavacek wrote:
>>>> @@ -2362,8 +2392,8 @@ 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.
>>>>*/
>>>> - tty_dev = tty_port_register_device(port, 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);
>>>
>>> This makes me believe you have not tested the change at all?
>>
>> Thanks! I can't believe I missed that. (And I actually tested that,
>> but I have to admit that it was not enough apparently.)
>>
>> I will re-send the patch (after some additional testing and double-checking).
>
> Ok. A couple more questions...
>
> * why are you passing tty_port to the struct device's private data and
> not uart_port proper? Is this for some future use?

I actually used the uart_port structure in older RFC versions of the
patch. Alan Cox advised to use struct tty_port because of consistency.
More precisely he said (in an e-mail from Aug 12):

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.

> * cannot be all those attribute structs const?

It seems that making

static const struct attribute *tty_dev_attrs[] = ...

produces warning:

drivers/tty/serial/serial_core.c:2334:2: warning: initialization from
incompatible pointer type [enabled by default]
drivers/tty/serial/serial_core.c:2334:2: warning: (near initialization
for ‘tty_dev_attr_group.attrs’) [enabled by default]

But others can. I am going to make them const in following patch.

> * kdoc for tty_register_device_attr says that when
> TTY_DRIVER_DYNAMIC_DEV is not set, tty_register_device_attr *should* not
> be called. But it must not be called, otherwise it will fail and emit a
> warning as a bonus, right?

Yes. In fact it does the same thing as tty_register_device() did
before itself. The _attr version is only slightly refactored and the
doc regarding the TTY_DRIVER_DYNAMIC_DEV test is the same as in old
non-_attr version.
I am not sure that I am the right person to change the doc because I
am not an author of this part of doc nor of the test in the function.

> * final remark. I would prefer declaration and code be delimited by a
> new line in uart_get_attr_uartclk:
> <===>
> +   int ret;
> +
> +   struct tty_port *port = dev_get_drvdata(dev);
> +   struct uart_state *state = container_of(port, struct uart_state,
> port);
> +   mutex_lock(>port.mutex);
> <===>
>
> Like:
> <===>
>   struct tty_port *port = ...;
>   struct uart_state *state = ...;
>   int ret;
>
>   mutex_lock(>port.mutex);
> <===>

Yes, it looks better. I am going to it accordingly.

Tomas
--
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 v6] uartclk value from serial_core exposed to sysfs

2012-09-06 Thread Tomas Hlavacek
Hi Jiri,

On Thu, Sep 6, 2012 at 7:54 PM, Jiri Slaby  wrote:
> On 09/06/2012 03:17 AM, Tomas Hlavacek wrote:
>> @@ -2362,8 +2392,8 @@ 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.
>>*/
>> - tty_dev = tty_port_register_device(port, 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);
>
> This makes me believe you have not tested the change at all?

Thanks! I can't believe I missed that. (And I actually tested that,
but I have to admit that it was not enough apparently.)

I will re-send the patch (after some additional testing and double-checking).

Tomas
--
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 v6] uartclk value from serial_core exposed to sysfs

2012-09-06 Thread Tomas Hlavacek
Hi Jiri,

On Thu, Sep 6, 2012 at 7:54 PM, Jiri Slaby jsl...@suse.cz wrote:
 On 09/06/2012 03:17 AM, Tomas Hlavacek wrote:
 @@ -2362,8 +2392,8 @@ 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.
*/
 - tty_dev = tty_port_register_device(port, 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);

 This makes me believe you have not tested the change at all?

Thanks! I can't believe I missed that. (And I actually tested that,
but I have to admit that it was not enough apparently.)

I will re-send the patch (after some additional testing and double-checking).

Tomas
--
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 v6] uartclk value from serial_core exposed to sysfs

2012-09-06 Thread Tomas Hlavacek
Hello!

On Thu, Sep 6, 2012 at 8:54 PM, Jiri Slaby jsl...@suse.cz wrote:
 On 09/06/2012 08:39 PM, Tomas Hlavacek wrote:
 On Thu, Sep 6, 2012 at 7:54 PM, Jiri Slaby jsl...@suse.cz wrote:
 On 09/06/2012 03:17 AM, Tomas Hlavacek wrote:
 @@ -2362,8 +2392,8 @@ 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.
*/
 - tty_dev = tty_port_register_device(port, 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);

 This makes me believe you have not tested the change at all?

 Thanks! I can't believe I missed that. (And I actually tested that,
 but I have to admit that it was not enough apparently.)

 I will re-send the patch (after some additional testing and double-checking).

 Ok. A couple more questions...

 * why are you passing tty_port to the struct device's private data and
 not uart_port proper? Is this for some future use?

I actually used the uart_port structure in older RFC versions of the
patch. Alan Cox advised to use struct tty_port because of consistency.
More precisely he said (in an e-mail from Aug 12):

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.

 * cannot be all those attribute structs const?

It seems that making

static const struct attribute *tty_dev_attrs[] = ...

produces warning:

drivers/tty/serial/serial_core.c:2334:2: warning: initialization from
incompatible pointer type [enabled by default]
drivers/tty/serial/serial_core.c:2334:2: warning: (near initialization
for ‘tty_dev_attr_group.attrs’) [enabled by default]

But others can. I am going to make them const in following patch.

 * kdoc for tty_register_device_attr says that when
 TTY_DRIVER_DYNAMIC_DEV is not set, tty_register_device_attr *should* not
 be called. But it must not be called, otherwise it will fail and emit a
 warning as a bonus, right?

Yes. In fact it does the same thing as tty_register_device() did
before itself. The _attr version is only slightly refactored and the
doc regarding the TTY_DRIVER_DYNAMIC_DEV test is the same as in old
non-_attr version.
I am not sure that I am the right person to change the doc because I
am not an author of this part of doc nor of the test in the function.

 * final remark. I would prefer declaration and code be delimited by a
 new line in uart_get_attr_uartclk:
 ===
 +   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);
 ===

 Like:
 ===
   struct tty_port *port = ...;
   struct uart_state *state = ...;
   int ret;

   mutex_lock(state-port.mutex);
 ===

Yes, it looks better. I am going to it accordingly.

Tomas
--
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/


[PATCH] tty_register_device_attr updated for tty-next

2012-09-06 Thread Tomas Hlavacek
Added tty_device_create_release() and bound to dev-release in
tty_register_device_attr().
Added tty_port_register_device_attr() and used in uart_add_one_port()
instead of tty_register_device_attr().

Signed-off-by: Tomas Hlavacek tmshl...@gmail.com
---
 drivers/tty/serial/serial_core.c |8 
 drivers/tty/tty_io.c |7 +++
 drivers/tty/tty_port.c   |   24 
 include/linux/tty.h  |4 
 4 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index f629bdf..046279c 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2313,9 +2313,9 @@ 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);
@@ -2330,7 +2330,7 @@ static struct attribute *tty_dev_attrs[] = {
NULL,
};
 
-static struct attribute_group tty_dev_attr_group = {
+static const struct attribute_group tty_dev_attr_group = {
.attrs = tty_dev_attrs,
};
 
@@ -2392,8 +2392,8 @@ 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.
 */
-   tty_dev = tty_register_device_attr(drv-tty_driver, uport-line,
-   uport-dev, port, tty_dev_attr_groups);
+   tty_dev = tty_port_register_device_attr(port, 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 dcb30d5..8a5a8b0 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3045,6 +3045,12 @@ struct device *tty_register_device(struct tty_driver 
*driver, unsigned index,
 }
 EXPORT_SYMBOL(tty_register_device);
 
+static void tty_device_create_release(struct device *dev)
+{
+   pr_debug(device: '%s': %s\n, dev_name(dev), __func__);
+   kfree(dev);
+}
+
 /**
  * tty_register_device_attr - register a tty device
  * @driver: the tty driver that describes the tty device
@@ -3103,6 +3109,7 @@ struct device *tty_register_device_attr(struct tty_driver 
*driver,
dev-devt = devt;
dev-class = tty_class;
dev-parent = device;
+   dev-release = tty_device_create_release;
dev_set_name(dev, %s, name);
dev-groups = attr_grp;
dev_set_drvdata(dev, drvdata);
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 96302f4..d7bdd8d 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -73,6 +73,30 @@ struct device *tty_port_register_device(struct tty_port 
*port,
 }
 EXPORT_SYMBOL_GPL(tty_port_register_device);
 
+/**
+ * tty_port_register_device_attr - register tty device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ * @device: parent if exists, otherwise NULL
+ * @drvdata: Driver data to be set to device.
+ * @attr_grp: Attribute group to be set on device.
+ *
+ * It is the same as tty_register_device_attr except the provided @port is
+ * linked to a concrete tty specified by @index. Use this or tty_port_install
+ * (or both). Call tty_port_link_device as a last resort.
+ */
+struct device *tty_port_register_device_attr(struct tty_port *port,
+   struct tty_driver *driver, unsigned index,
+   struct device *device, void *drvdata,
+   const struct attribute_group **attr_grp)
+{
+   tty_port_link_device(port, driver, index);
+   return tty_register_device_attr(driver, index, device, drvdata,
+   attr_grp);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
+
 int tty_port_alloc_xmit_buf(struct tty_port *port)
 {
/* We may sleep in get_zeroed_page() */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 599d603..1509b86 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -507,6 +507,10 @@ extern void tty_port_link_device(struct tty_port *port,
 extern struct device *tty_port_register_device(struct tty_port *port,
struct tty_driver *driver, unsigned index,
struct device *device);
+extern struct device *tty_port_register_device_attr(struct tty_port *port,
+   struct tty_driver *driver, unsigned index,
+   struct device *device, void *drvdata,
+   const struct attribute_group **attr_grp);
 extern int tty_port_alloc_xmit_buf(struct tty_port *port);
 extern void

Re: [PATCH] tty_register_device_attr updated for tty-next

2012-09-06 Thread Tomas Hlavacek
Hello!

On Thu, Sep 6, 2012 at 11:17 PM, Tomas Hlavacek tmshl...@gmail.com wrote:
 Added tty_device_create_release() and bound to dev-release in
 tty_register_device_attr().
 Added tty_port_register_device_attr() and used in uart_add_one_port()
 instead of tty_register_device_attr().

 Signed-off-by: Tomas Hlavacek tmshl...@gmail.com
 ---
  drivers/tty/serial/serial_core.c |8 
  drivers/tty/tty_io.c |7 +++
  drivers/tty/tty_port.c   |   24 
  include/linux/tty.h  |4 
  4 files changed, 39 insertions(+), 4 deletions(-)


A little bit more explanation regarding this patch: It fixes two
problems with my previous patch (tty: uartclk value from serial_core
exposed to sysfs) which Jiri has pointed out earlier today. Both are
related to the changed interface in the tty-next branch and both
should have been dealt with in the first patch. It also fixes minor
problems (one const keyword added and newlines rearranged in the
uart_get_attr_uartclk() function).

Tomas
--
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/


[PATCH v6] uartclk value from serial_core exposed to sysfs

2012-09-05 Thread Tomas Hlavacek
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 
---
 Documentation/ABI/testing/sysfs-tty |9 +
 drivers/tty/serial/serial_core.c|   34 -
 drivers/tty/tty_io.c|   69 ++-
 include/linux/tty.h |4 ++
 4 files changed, 104 insertions(+), 12 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-tty 
b/Documentation/ABI/testing/sysfs-tty
index b138b66..0c43015 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 
+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 137b25c..5d212f8 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2309,6 +2309,36 @@ 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(>port.mutex);
+   ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
+   mutex_unlock(>port.mutex);
+
+   return ret;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL);
+
+static struct attribute *tty_dev_attrs[] = {
+   _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[] = {
+   _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
@@ -2362,8 +2392,8 @@ 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.
 */
-   tty_dev = tty_port_register_device(port, 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 d3bf91a..dcb30d5 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3041,9 +3041,39 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t 
dev,
 struct device *tty_register_device(struct tty_driver *driver, unsigned index,
   struct device *device)
 {
-   struct device *ret;
+   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;

Re: [PATCHv5 1/1] uartclk value from serial_core exposed to sysfs

2012-09-05 Thread Tomas Hlavacek
Hello Greg,

On Thu, Sep 6, 2012 at 1:42 AM, Greg KH  wrote:
> On Thu, Sep 06, 2012 at 01:16:56AM +0200, Tomas Hlavacek wrote:
>> 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 
>> ---
>>  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
>
> Odd, what tree did you make this against?  It doesn't apply at all, even
> if I mess with it to try a --3way merge, it still throws up a ton of
> conflicts.
>
> Care to do it against my tty-next branch in git?

I did it wrong obviously. Sorry. I am resending it (it is going to be
against tty-next branch in
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git, I hope
it is right this time).

Tomas
--
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/


[PATCHv5 1/1] uartclk value from serial_core exposed to sysfs

2012-09-05 Thread Tomas Hlavacek
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 
---
 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 
+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(>port.mutex);
+ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
+mutex_unlock(>port.mutex);
+
+return ret;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk,
+   NULL);
+
+static struct attribute *tty_dev_attrs[] = {
+   _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[] = {
+   _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;
+   

[PATCHv5 1/1] uartclk value from serial_core exposed to sysfs

2012-09-05 Thread Tomas Hlavacek
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 tmshl...@gmail.com
---
 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 tmshl...@gmail.com
+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

Re: [PATCHv5 1/1] uartclk value from serial_core exposed to sysfs

2012-09-05 Thread Tomas Hlavacek
Hello Greg,

On Thu, Sep 6, 2012 at 1:42 AM, Greg KH gre...@linuxfoundation.org wrote:
 On Thu, Sep 06, 2012 at 01:16:56AM +0200, Tomas Hlavacek wrote:
 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 tmshl...@gmail.com
 ---
  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

 Odd, what tree did you make this against?  It doesn't apply at all, even
 if I mess with it to try a --3way merge, it still throws up a ton of
 conflicts.

 Care to do it against my tty-next branch in git?

I did it wrong obviously. Sorry. I am resending it (it is going to be
against tty-next branch in
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git, I hope
it is right this time).

Tomas
--
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/


[PATCH v6] uartclk value from serial_core exposed to sysfs

2012-09-05 Thread Tomas Hlavacek
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 tmshl...@gmail.com
---
 Documentation/ABI/testing/sysfs-tty |9 +
 drivers/tty/serial/serial_core.c|   34 -
 drivers/tty/tty_io.c|   69 ++-
 include/linux/tty.h |4 ++
 4 files changed, 104 insertions(+), 12 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-tty 
b/Documentation/ABI/testing/sysfs-tty
index b138b66..0c43015 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 tmshl...@gmail.com
+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 137b25c..5d212f8 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2309,6 +2309,36 @@ 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
@@ -2362,8 +2392,8 @@ 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.
 */
-   tty_dev = tty_port_register_device(port, 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 d3bf91a..dcb30d5 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3041,9 +3041,39 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t 
dev,
 struct device *tty_register_device(struct tty_driver *driver, unsigned index,
   struct device *device)
 {
-   struct device *ret;
+   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;
+   dev_t

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

2012-08-21 Thread Tomas Hlavacek
Hello!

On Sun, Aug 19, 2012 at 8:34 PM, Tomas Hlavacek  wrote:
> Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
> uartclk value in struct uart_port in serial_core via sysfs.
>
> It simplifies initialization verification of no-name cards that
> have non-standard oscillator speed while having no distinguishing
> PCI IDs to allow autodetection.
>
> tty_register_device() has been generalized and refactored in order
> to add support for setting drvdata and attribute_group to the device.
>

I have updated the patch to a new v4 in order to remove the race in
sysfs file creation and add sysfs file description to a Documentation
directory. But still the patch creates the sysfs file separately for
each serial TTY device by assigning attribute_groups to the struct
device and not for the whole driver at once as Greg advised because I
was unable to figure out how to do that (even though I tried pretty
hard). Does it make sense like this? Or do you have any hint for a
better way to do it, please?

Thanks,
Tomas
--
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: [PATCHv4 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-21 Thread Tomas Hlavacek
Hello!

On Sun, Aug 19, 2012 at 8:34 PM, Tomas Hlavacek tmshl...@gmail.com wrote:
 Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
 uartclk value in struct uart_port in serial_core via sysfs.

 It simplifies initialization verification of no-name cards that
 have non-standard oscillator speed while having no distinguishing
 PCI IDs to allow autodetection.

 tty_register_device() has been generalized and refactored in order
 to add support for setting drvdata and attribute_group to the device.


I have updated the patch to a new v4 in order to remove the race in
sysfs file creation and add sysfs file description to a Documentation
directory. But still the patch creates the sysfs file separately for
each serial TTY device by assigning attribute_groups to the struct
device and not for the whole driver at once as Greg advised because I
was unable to figure out how to do that (even though I tried pretty
hard). Does it make sense like this? Or do you have any hint for a
better way to do it, please?

Thanks,
Tomas
--
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/


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

2012-08-19 Thread Tomas Hlavacek
Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
uartclk value in struct uart_port in serial_core via sysfs.

It simplifies initialization verification of no-name cards that
have non-standard oscillator speed while having no distinguishing
PCI IDs to allow autodetection.

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 
---
 Documentation/ABI/testing/sysfs-tty |9 +
 drivers/tty/serial/serial_core.c|   37 +++-
 drivers/tty/tty_io.c|   63 ---
 include/linux/tty.h |4 +++
 4 files changed, 108 insertions(+), 5 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-tty 
b/Documentation/ABI/testing/sysfs-tty
index b138b66..b93a174 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:  Aug 2012
+Contact:   Tomas Hlavacek 
+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..e0c11da 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2293,6 +2293,38 @@ 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(>port.mutex);
+   ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
+   mutex_unlock(>port.mutex);
+
+   return ret;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk,
+   NULL);
+
+static struct attribute *tty_dev_attrs[] = {
+   _attr_uartclk.attr,
+   NULL,
+};
+
+static struct attribute_group tty_dev_attr_group = {
+   .attrs = tty_dev_attrs,
+};
+
+static struct attribute_group *tty_dev_attr_groups[] = {
+   _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 +2377,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..1c9d5b5 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3009,12 +3009,42 @@ struct class *tty_class;
  *
  * Locking: ??
  */
-
 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 (NULL = do not touch).
+ * @attr_grp: Attribute group to be set on device (NULL = do not touch).
+ *
+ * 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,
+

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

2012-08-19 Thread Tomas Hlavacek
Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
uartclk value in struct uart_port in serial_core via sysfs.

It simplifies initialization verification of no-name cards that
have non-standard oscillator speed while having no distinguishing
PCI IDs to allow autodetection.

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 tmshl...@gmail.com
---
 Documentation/ABI/testing/sysfs-tty |9 +
 drivers/tty/serial/serial_core.c|   37 +++-
 drivers/tty/tty_io.c|   63 ---
 include/linux/tty.h |4 +++
 4 files changed, 108 insertions(+), 5 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-tty 
b/Documentation/ABI/testing/sysfs-tty
index b138b66..b93a174 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:  Aug 2012
+Contact:   Tomas Hlavacek tmshl...@gmail.com
+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..e0c11da 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2293,6 +2293,38 @@ 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 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 +2377,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..1c9d5b5 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3009,12 +3009,42 @@ struct class *tty_class;
  *
  * Locking: ??
  */
-
 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 (NULL = do not touch).
+ * @attr_grp: Attribute group to be set on device (NULL = do not touch).
+ *
+ * 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

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

2012-08-17 Thread Tomas Hlavacek
Hello!

On Fri, Aug 17, 2012 at 9:01 PM, Greg KH  wrote:
> On Fri, Aug 17, 2012 at 08:44:14PM +0200, Marek Vasut wrote:
>> Dear Greg KH,
>>
>> > On Fri, Aug 17, 2012 at 06:30:36PM +0200, Tomas Hlavacek wrote:
>> > > Hello Greg!
>> > >
>> > > On Fri, Aug 17, 2012 at 5:06 PM, Greg KH  
>> > > wrote:
>> > > >> @@ -2355,6 +2373,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, port);
>> > > >> + if (device_create_file(tty_dev, _attr_uartclk) < 0)
>> > > >> + dev_err(tty_dev, "Failed to add uartclk attr\n");
>> > > >
>> > > > I think you just raced with userspace in creating the file after the
>> > > > device was announced to userspace.  Are you sure it's ok?
>> > > >
>> > > > If not (hint, I don't think so), please make it a default attribute of
>> > > > the device, which will then cause the file to be created before it is
>> > > > announced to userspace.  It will also be less code as you don't have to
>> > > > clean it up by hand :)
>> > >
>> > > Do you mean I should modify the tty_register_device() function not to
>> > > use device_create() but it should rather do the device initialization
>> > > on it's own.
>> >
>> > No, not at all.
>> >
>> > > And I should add add the attribute (via struct attribute_group) to
>> > > struct device in between device_initialize() and device_add() calls.
>> > > Did I get it right?
>> >
>> > No, make this a driver attribute, that way when the device is
>> > registered, it adds the attribute automagically to the device that is
>> > bound to it.
>>
>> (hint, DEVICE_ATTR), right ?
>
> No, that's just a macro that creates the structure for the attribute.
> You need to take that structure and tie it to the driver itself, using
> the struct device_driver->groups; field.

Please forgive me my ignorance, but I am lost in this. I tried to read
through the serial_core and tty_io.c over and over to figure out how
the drivers are registered and where could I hook the driver
initialization for all UART ports, but I do not get it.

And there is another thing I am confused of: Should I use macro
DEVICE_ATTR or DRIVER_ATTR? There is a different signature of
callbacks in case of DRIVER_ATTR and I do not know how to find out
from struct device_driver which particular UART port it is associated
to? (Is it indeed associated with one particular port?) Value uartclk
could be, AFAIK, different on each port of the same chip and therefore
I need to know which particular TTY device I want to operate on. More
precisely, I have to get to proper struct uart_state associated with
the particular port.

Thanks,
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: [PATCHv3 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-17 Thread Tomas Hlavacek
Hello Greg!

On Fri, Aug 17, 2012 at 5:06 PM, Greg KH  wrote:
>> @@ -2355,6 +2373,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, port);
>> + if (device_create_file(tty_dev, _attr_uartclk) < 0)
>> + dev_err(tty_dev, "Failed to add uartclk attr\n");
>
> I think you just raced with userspace in creating the file after the
> device was announced to userspace.  Are you sure it's ok?
>
> If not (hint, I don't think so), please make it a default attribute of
> the device, which will then cause the file to be created before it is
> announced to userspace.  It will also be less code as you don't have to
> clean it up by hand :)

Do you mean I should modify the tty_register_device() function not to
use device_create() but it should rather do the device initialization
on it's own. And I should add add the attribute (via struct
attribute_group) to struct device in between device_initialize() and
device_add() calls. Did I get it right?

Thanks,
Tomas
--
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/


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

2012-08-17 Thread Tomas Hlavacek
Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
uartclk value in struct uart_port in serial_core via sysfs.

It simplifies initialization verification of no-name cards that
have non-standard oscillator speed while having no distinguishing
PCI IDs to allow autodetection.

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

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a21dc8e..454e9d3 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2293,6 +2293,24 @@ 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(>port.mutex);
+   ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
+   mutex_unlock(>port.mutex);
+
+   return ret;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk,
+   NULL);
+
 /**
  * uart_add_one_port - attach a driver-defined port structure
  * @drv: pointer to the uart low level driver structure for this port
@@ -2355,6 +2373,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, port);
+   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 +2423,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 at  http://www.tux.org/lkml/


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

2012-08-17 Thread Tomas Hlavacek
Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
uartclk value in struct uart_port in serial_core via sysfs.

It simplifies initialization verification of no-name cards that
have non-standard oscillator speed while having no distinguishing
PCI IDs to allow autodetection.

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

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a21dc8e..454e9d3 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2293,6 +2293,24 @@ 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);
+
 /**
  * uart_add_one_port - attach a driver-defined port structure
  * @drv: pointer to the uart low level driver structure for this port
@@ -2355,6 +2373,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, port);
+   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 +2423,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  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


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

2012-08-17 Thread Tomas Hlavacek
Hello Greg!

On Fri, Aug 17, 2012 at 5:06 PM, Greg KH gre...@linuxfoundation.org wrote:
 @@ -2355,6 +2373,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, port);
 + if (device_create_file(tty_dev, dev_attr_uartclk)  0)
 + dev_err(tty_dev, Failed to add uartclk attr\n);

 I think you just raced with userspace in creating the file after the
 device was announced to userspace.  Are you sure it's ok?

 If not (hint, I don't think so), please make it a default attribute of
 the device, which will then cause the file to be created before it is
 announced to userspace.  It will also be less code as you don't have to
 clean it up by hand :)

Do you mean I should modify the tty_register_device() function not to
use device_create() but it should rather do the device initialization
on it's own. And I should add add the attribute (via struct
attribute_group) to struct device in between device_initialize() and
device_add() calls. Did I get it right?

Thanks,
Tomas
--
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: [PATCHv3 1/1] [RFC] uartclk from serial_core exposed to sysfs

2012-08-17 Thread Tomas Hlavacek
Hello!

On Fri, Aug 17, 2012 at 9:01 PM, Greg KH gre...@linuxfoundation.org wrote:
 On Fri, Aug 17, 2012 at 08:44:14PM +0200, Marek Vasut wrote:
 Dear Greg KH,

  On Fri, Aug 17, 2012 at 06:30:36PM +0200, Tomas Hlavacek wrote:
   Hello Greg!
  
   On Fri, Aug 17, 2012 at 5:06 PM, Greg KH gre...@linuxfoundation.org 
   wrote:
@@ -2355,6 +2373,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, port);
+ if (device_create_file(tty_dev, dev_attr_uartclk)  0)
+ dev_err(tty_dev, Failed to add uartclk attr\n);
   
I think you just raced with userspace in creating the file after the
device was announced to userspace.  Are you sure it's ok?
   
If not (hint, I don't think so), please make it a default attribute of
the device, which will then cause the file to be created before it is
announced to userspace.  It will also be less code as you don't have to
clean it up by hand :)
  
   Do you mean I should modify the tty_register_device() function not to
   use device_create() but it should rather do the device initialization
   on it's own.
 
  No, not at all.
 
   And I should add add the attribute (via struct attribute_group) to
   struct device in between device_initialize() and device_add() calls.
   Did I get it right?
 
  No, make this a driver attribute, that way when the device is
  registered, it adds the attribute automagically to the device that is
  bound to it.

 (hint, DEVICE_ATTR), right ?

 No, that's just a macro that creates the structure for the attribute.
 You need to take that structure and tie it to the driver itself, using
 the struct device_driver-groups; field.

Please forgive me my ignorance, but I am lost in this. I tried to read
through the serial_core and tty_io.c over and over to figure out how
the drivers are registered and where could I hook the driver
initialization for all UART ports, but I do not get it.

And there is another thing I am confused of: Should I use macro
DEVICE_ATTR or DRIVER_ATTR? There is a different signature of
callbacks in case of DRIVER_ATTR and I do not know how to find out
from struct device_driver which particular UART port it is associated
to? (Is it indeed associated with one particular port?) Value uartclk
could be, AFAIK, different on each port of the same chip and therefore
I need to know which particular TTY device I want to operate on. More
precisely, I have to get to proper struct uart_state associated with
the particular port.

Thanks,
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/


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

2012-08-15 Thread Tomas Hlavacek
Added file /sys/devices/.../tty/ttySX/uartclk to allow read/modify
uartclk value in struct uart_port in serial_core via sysfs.

It simplifies initialization of no-name cards that have non-standard
oscillator speed while having no distinguishing PCI IDs to allow
autodetection.

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

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a21dc8e..0929fe3 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2293,6 +2293,47 @@ 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 uart_state *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 uart_set_attr_uartclk(struct device *dev,
+   struct device_attribute *attr, const char *buf, size_t count)
+{
+   struct uart_state *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 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.
+*/
+   if (val >= 153600)
+   state->uart_port->uartclk = val;
+
+   mutex_unlock(>port.mutex);
+
+   return count;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUGO | S_IWUSR, uart_get_attr_uartclk,
+   uart_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 +2396,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 +2446,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 

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/


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

2012-08-15 Thread Tomas Hlavacek
Added file /sys/devices/.../tty/ttySX/uartclk to allow read/modify
uartclk value in struct uart_port in serial_core via sysfs.

It simplifies initialization of no-name cards that have non-standard
oscillator speed while having no distinguishing PCI IDs to allow
autodetection.

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

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a21dc8e..0929fe3 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2293,6 +2293,47 @@ 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 uart_state *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 uart_set_attr_uartclk(struct device *dev,
+   struct device_attribute *attr, const char *buf, size_t count)
+{
+   struct uart_state *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 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.
+*/
+   if (val = 153600)
+   state-uart_port-uartclk = val;
+
+   mutex_unlock(state-port.mutex);
+
+   return count;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUGO | S_IWUSR, uart_get_attr_uartclk,
+   uart_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 +2396,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 +2446,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

[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

[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  http://vger.kernel.org

ioatdma Self-test copy timeout

2008-02-17 Thread Tomas Hlavacek
Short description: In 2.6.25-rc2 ioatdma driver fails to initialize due 
to Self-test timeout when the ioatdma is linked into the kernel.



Long descr: When I select to compile ioatdma into the kernel I get:

ACPI: PCI Interrupt :00:08.0[A] -> GSI 16 (level, low) -> IRQ 16
PCI: Setting latency timer of device :00:08.0 to 64
ioatdma :00:08.0: Intel(R) I/OAT DMA Engine found, 4 channels, 
device version 0x12, driver version 2.04

ioatdma: ioat_dma_test_callback(8086)
ioatdma :00:08.0: Self-test copy timed out, disabling
ioatdma :00:08.0: Intel(R) I/OAT DMA Engine initialization failed
ACPI: PCI interrupt for device :00:08.0 disabled

As a kernel module ioatdma initializes just fine with the same kernel on 
the same HW without any other changes than selecting it to be a module. 
And it also succeeded to initialize when i tried to do this:


--- a/drivers/dma/ioat_dma.c2008-02-17 01:52:19.0 +0100
+++ b/drivers/dma/ioat_dma.c2008-02-18 02:47:27.0 +0100
@@ -1089,7 +1089,7 @@
   goto free_resources;
   }
   device->common.device_issue_pending(dma_chan);
-   msleep(1);
+   msleep(100);

   if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, 
NULL)

   != DMA_SUCCESS) {


My lspci:
00:00.0 Host bridge: Intel Corporation 5000P Chipset Memory Controller 
Hub (rev b1)
00:02.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI Express x8 
Port 2-3 (rev b1)
00:04.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI Express x8 
Port 4-5 (rev b1)
00:06.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI Express x8 
Port 6-7 (rev b1)
00:08.0 System peripheral: Intel Corporation 5000 Series Chipset DMA 
Engine (rev b1)
00:10.0 Host bridge: Intel Corporation 5000 Series Chipset FSB Registers 
(rev b1)
00:10.1 Host bridge: Intel Corporation 5000 Series Chipset FSB Registers 
(rev b1)
00:10.2 Host bridge: Intel Corporation 5000 Series Chipset FSB Registers 
(rev b1)
00:11.0 Host bridge: Intel Corporation 5000 Series Chipset Reserved 
Registers (rev b1)
00:13.0 Host bridge: Intel Corporation 5000 Series Chipset Reserved 
Registers (rev b1)
00:15.0 Host bridge: Intel Corporation 5000 Series Chipset FBD Registers 
(rev b1)
00:16.0 Host bridge: Intel Corporation 5000 Series Chipset FBD Registers 
(rev b1)
00:1d.0 USB Controller: Intel Corporation 631xESB/632xESB/3100 Chipset 
UHCI USB Controller #1 (rev 09)
00:1d.1 USB Controller: Intel Corporation 631xESB/632xESB/3100 Chipset 
UHCI USB Controller #2 (rev 09)
00:1d.2 USB Controller: Intel Corporation 631xESB/632xESB/3100 Chipset 
UHCI USB Controller #3 (rev 09)
00:1d.7 USB Controller: Intel Corporation 631xESB/632xESB/3100 Chipset 
EHCI USB2 Controller (rev 09)

00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev d9)
00:1f.0 ISA bridge: Intel Corporation 631xESB/632xESB/3100 Chipset LPC 
Interface Controller (rev 09)
00:1f.1 IDE interface: Intel Corporation 631xESB/632xESB IDE Controller 
(rev 09)
00:1f.3 SMBus: Intel Corporation 631xESB/632xESB/3100 Chipset SMBus 
Controller (rev 09)
01:00.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express 
Upstream Port (rev 01)
01:00.3 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express to 
PCI-X Bridge (rev 01)
02:00.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express 
Downstream Port E1 (rev 01)
02:01.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express 
Downstream Port E2 (rev 01)
02:02.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express 
Downstream Port E3 (rev 01)
05:00.0 Ethernet controller: Intel Corporation 80003ES2LAN Gigabit 
Ethernet Controller (Copper) (rev 01)
05:00.1 Ethernet controller: Intel Corporation 80003ES2LAN Gigabit 
Ethernet Controller (Copper) (rev 01)
07:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet 
Controller (rev 06)
07:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet 
Controller (rev 06)

09:01.0 VGA compatible controller: ATI Technologies Inc ES1000 (rev 02)

I placed my full dmesg output here: 
http://manwe.elfove.cz/~brill/tmp/dmesg-2.6.25-rc2


--
Tomas Hlavacek <[EMAIL PROTECTED]>

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


ioatdma Self-test copy timeout

2008-02-17 Thread Tomas Hlavacek
Short description: In 2.6.25-rc2 ioatdma driver fails to initialize due 
to Self-test timeout when the ioatdma is linked into the kernel.



Long descr: When I select to compile ioatdma into the kernel I get:

ACPI: PCI Interrupt :00:08.0[A] - GSI 16 (level, low) - IRQ 16
PCI: Setting latency timer of device :00:08.0 to 64
ioatdma :00:08.0: Intel(R) I/OAT DMA Engine found, 4 channels, 
device version 0x12, driver version 2.04

ioatdma: ioat_dma_test_callback(8086)
ioatdma :00:08.0: Self-test copy timed out, disabling
ioatdma :00:08.0: Intel(R) I/OAT DMA Engine initialization failed
ACPI: PCI interrupt for device :00:08.0 disabled

As a kernel module ioatdma initializes just fine with the same kernel on 
the same HW without any other changes than selecting it to be a module. 
And it also succeeded to initialize when i tried to do this:


--- a/drivers/dma/ioat_dma.c2008-02-17 01:52:19.0 +0100
+++ b/drivers/dma/ioat_dma.c2008-02-18 02:47:27.0 +0100
@@ -1089,7 +1089,7 @@
   goto free_resources;
   }
   device-common.device_issue_pending(dma_chan);
-   msleep(1);
+   msleep(100);

   if (device-common.device_is_tx_complete(dma_chan, cookie, NULL, 
NULL)

   != DMA_SUCCESS) {


My lspci:
00:00.0 Host bridge: Intel Corporation 5000P Chipset Memory Controller 
Hub (rev b1)
00:02.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI Express x8 
Port 2-3 (rev b1)
00:04.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI Express x8 
Port 4-5 (rev b1)
00:06.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI Express x8 
Port 6-7 (rev b1)
00:08.0 System peripheral: Intel Corporation 5000 Series Chipset DMA 
Engine (rev b1)
00:10.0 Host bridge: Intel Corporation 5000 Series Chipset FSB Registers 
(rev b1)
00:10.1 Host bridge: Intel Corporation 5000 Series Chipset FSB Registers 
(rev b1)
00:10.2 Host bridge: Intel Corporation 5000 Series Chipset FSB Registers 
(rev b1)
00:11.0 Host bridge: Intel Corporation 5000 Series Chipset Reserved 
Registers (rev b1)
00:13.0 Host bridge: Intel Corporation 5000 Series Chipset Reserved 
Registers (rev b1)
00:15.0 Host bridge: Intel Corporation 5000 Series Chipset FBD Registers 
(rev b1)
00:16.0 Host bridge: Intel Corporation 5000 Series Chipset FBD Registers 
(rev b1)
00:1d.0 USB Controller: Intel Corporation 631xESB/632xESB/3100 Chipset 
UHCI USB Controller #1 (rev 09)
00:1d.1 USB Controller: Intel Corporation 631xESB/632xESB/3100 Chipset 
UHCI USB Controller #2 (rev 09)
00:1d.2 USB Controller: Intel Corporation 631xESB/632xESB/3100 Chipset 
UHCI USB Controller #3 (rev 09)
00:1d.7 USB Controller: Intel Corporation 631xESB/632xESB/3100 Chipset 
EHCI USB2 Controller (rev 09)

00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev d9)
00:1f.0 ISA bridge: Intel Corporation 631xESB/632xESB/3100 Chipset LPC 
Interface Controller (rev 09)
00:1f.1 IDE interface: Intel Corporation 631xESB/632xESB IDE Controller 
(rev 09)
00:1f.3 SMBus: Intel Corporation 631xESB/632xESB/3100 Chipset SMBus 
Controller (rev 09)
01:00.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express 
Upstream Port (rev 01)
01:00.3 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express to 
PCI-X Bridge (rev 01)
02:00.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express 
Downstream Port E1 (rev 01)
02:01.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express 
Downstream Port E2 (rev 01)
02:02.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express 
Downstream Port E3 (rev 01)
05:00.0 Ethernet controller: Intel Corporation 80003ES2LAN Gigabit 
Ethernet Controller (Copper) (rev 01)
05:00.1 Ethernet controller: Intel Corporation 80003ES2LAN Gigabit 
Ethernet Controller (Copper) (rev 01)
07:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet 
Controller (rev 06)
07:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet 
Controller (rev 06)

09:01.0 VGA compatible controller: ATI Technologies Inc ES1000 (rev 02)

I placed my full dmesg output here: 
http://manwe.elfove.cz/~brill/tmp/dmesg-2.6.25-rc2


--
Tomas Hlavacek [EMAIL PROTECTED]

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