Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH v3 3/4] bluetooth: hci_uart: add LL protocol serdev driver support
From: Rob Herring @ 2017-04-19 20:47 UTC (permalink / raw)
  To: Adam Ford
  Cc: Marcel Holtmann, open list:BLUETOOTH DRIVERS, Mark Rutland,
	devicetree@vger.kernel.org, Johan Hedberg, Gustavo Padovan,
	Satish Patel, Wei Xu, Eyal Reizer, netdev,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <CAHCN7xLNcD1rmifEOyPhG2rpB_C81hsyzV9W2q6kCQkKa69sZg@mail.gmail.com>

On Mon, Apr 17, 2017 at 3:11 PM, Adam Ford <aford173@gmail.com> wrote:
> On Thu, Apr 13, 2017 at 10:03 AM, Rob Herring <robh@kernel.org> wrote:
>> Turns out that the LL protocol and the TI-ST are the same thing AFAICT.
>> The TI-ST adds firmware loading, GPIO control, and shared access for
>> NFC, FM radio, etc. For now, we're only implementing what is needed for
>> BT. This mirrors other drivers like BCM and Intel, but uses the new
>> serdev bus.
>>
>> The firmware loading is greatly simplified by using existing
>> infrastructure to send commands. It may be a bit slower than the
>> original code using synchronous functions, but the real bottleneck is
>> likely doing firmware load at 115.2kbps.
>
> I am using pdata-quirks to drive my wl1283 Bluetooth on a DM3730.  I
> have the Bluetooth set to 3000000 baud in pdata quirks.  Looking at
> the binding, I don't see an option to set the baudrate.  Is there (or
> will there) be a way to set the baud rate of the Bluetooth?

If you read hci_ti_probe, you will see it is already there. The
default is 3Mbps and the DT can override that with "max-speed". The
intent is that 3Mbps is the max the device can do and max-speed is
only for board or host limitations. Though I just checked the
datasheet on the 1835 and it can go up to 4364kbps. No datasheets for
wl1283, so I have no idea what the max is.

>> +static int hci_ti_probe(struct serdev_device *serdev)
>> +{
>> +       struct hci_uart *hu;
>> +       struct ll_device *lldev;
>> +       u32 max_speed = 3000000;

[...]

>> +       of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed);
>> +       hci_uart_set_speeds(hu, 115200, max_speed);

^ permalink raw reply

* Re: [PATCH] blutooth: try to improve CONFIG_SERIAL_DEV_BUS dependency
From: Marcel Holtmann @ 2017-04-19 20:09 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Gustavo F. Padovan, Johan Hedberg, Sebastian Reichel, Rob Herring,
	Bjorn Andersson, David S. Miller, Kalle Valo, Linux Bluetooth,
	linux-kernel
In-Reply-To: <20170419175051.4177480-1-arnd@arndb.de>

Hi Arnd,

> With CONFIG_SERIAL_DEV_BUS=m, the hci_serdev.o file does not actually
> get built into hci_uart.o as the Makefile doesn't pick it up, leading
> to a link error with anything referring to it:
> 
> ERROR: "hci_uart_register_device" [drivers/bluetooth/hci_nokia.ko] undefined!
> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
> 
> Changing this in the Makefile would cause another problem when
> hci_uart itself is built-in and cannot reference symbols from the
> serdev module.
> 
> This tries to address both problems by introducing a new hidden
> Kconfig symbol that controls both the compilation of hci_serdev.o
> and whether the Nokia driver can be selected. This seems to address
> the problem for me, though there might be a better way to do it.
> 
> Fixes: 7bb318680e86 ("Bluetooth: add nokia driver")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/bluetooth/Kconfig  | 8 +++++++-
> drivers/bluetooth/Makefile | 2 +-
> 2 files changed, 8 insertions(+), 2 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel

^ permalink raw reply

* Re: [PATCH BlueZ] monitor: Add frame number support
From: Marcel Holtmann @ 2017-04-19 19:35 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <20170419184012.5650-1-luiz.dentz@gmail.com>

Hi Luiz,

> This adds -f/--frames options which can be used to show the frame
> number:
> 
>  #1 < HCI Command: Write Voice Setting (0x03|0x0026) plen 2
>        Setting: 0x0060
>          Input Coding: Linear
>          Input Data Format: 2's complement
>          Input Sample Size: 16-bit
>          # of bits padding at MSB: 0
>          Air Coding Format: CVSD
>  #2 > HCI Event: Command Complete (0x0e) plen 4
>      Write Voice Setting (0x03|0x0026) ncmd 1
>        Status: Success (0x00)

I have been avoiding adding anything in the front. So if you want extra indicators, they go at the end of the line.

Regards

Marcel


^ permalink raw reply

* [PATCH BlueZ] monitor: Add frame number support
From: Luiz Augusto von Dentz @ 2017-04-19 18:40 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds -f/--frames options which can be used to show the frame
number:

  #1 < HCI Command: Write Voice Setting (0x03|0x0026) plen 2
        Setting: 0x0060
          Input Coding: Linear
          Input Data Format: 2's complement
          Input Sample Size: 16-bit
          # of bits padding at MSB: 0
          Air Coding Format: CVSD
  #2 > HCI Event: Command Complete (0x0e) plen 4
      Write Voice Setting (0x03|0x0026) ncmd 1
        Status: Success (0x00)
---
 monitor/main.c   | 7 ++++++-
 monitor/packet.c | 9 ++++++++-
 monitor/packet.h | 1 +
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/monitor/main.c b/monitor/main.c
index f9bca22..e1a2375 100644
--- a/monitor/main.c
+++ b/monitor/main.c
@@ -70,6 +70,7 @@ static void usage(void)
 		"\t-T, --date             Show time and date information\n"
 		"\t-S, --sco              Dump SCO traffic\n"
 		"\t-E, --ellisys [ip]     Send Ellisys HCI Injection\n"
+		"\t-f, --frames           Show frame counter\n"
 		"\t-h, --help             Show help options\n");
 }
 
@@ -86,6 +87,7 @@ static const struct option main_options[] = {
 	{ "date",    no_argument,       NULL, 'T' },
 	{ "sco",     no_argument,	NULL, 'S' },
 	{ "ellisys", required_argument, NULL, 'E' },
+	{ "frames",  no_argument,	NULL, 'f' },
 	{ "todo",    no_argument,       NULL, '#' },
 	{ "version", no_argument,       NULL, 'v' },
 	{ "help",    no_argument,       NULL, 'h' },
@@ -113,7 +115,7 @@ int main(int argc, char *argv[])
 	for (;;) {
 		int opt;
 
-		opt = getopt_long(argc, argv, "d:r:w:a:s:p:i:tTSE:vh",
+		opt = getopt_long(argc, argv, "d:r:w:a:s:p:i:tfTSE:vh",
 						main_options, NULL);
 		if (opt < 0)
 			break;
@@ -171,6 +173,9 @@ int main(int argc, char *argv[])
 			ellisys_server = optarg;
 			ellisys_port = 24352;
 			break;
+		case 'f':
+			filter_mask |= PACKET_FILTER_SHOW_FRAME;
+			break;
 		case '#':
 			packet_todo();
 			lmp_todo();
diff --git a/monitor/packet.c b/monitor/packet.c
index 3c43356..d369a4d 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -349,7 +349,14 @@ static void print_packet(struct timeval *tv, struct ucred *cred, char ident,
 			pos += n;
 	}
 
-	n = sprintf(line + pos, "%c %s", ident, label ? label : "");
+	if (filter_mask & PACKET_FILTER_SHOW_FRAME) {
+		static size_t frame;
+
+		n = sprintf(line + pos, "#%zu %c %s", ++frame, ident,
+						label ? label : "");
+	} else
+		n = sprintf(line + pos, "%c %s", ident, label ? label : "");
+
 	if (n > 0) {
 		pos += n;
 		len += n;
diff --git a/monitor/packet.h b/monitor/packet.h
index 354f4fe..2516ec1 100644
--- a/monitor/packet.h
+++ b/monitor/packet.h
@@ -33,6 +33,7 @@
 #define PACKET_FILTER_SHOW_TIME_OFFSET	(1 << 3)
 #define PACKET_FILTER_SHOW_ACL_DATA	(1 << 4)
 #define PACKET_FILTER_SHOW_SCO_DATA	(1 << 5)
+#define PACKET_FILTER_SHOW_FRAME	(1 << 6)
 
 void packet_set_filter(unsigned long filter);
 void packet_add_filter(unsigned long filter);
-- 
2.9.3


^ permalink raw reply related

* Re: bluetooth 6lowpan interfaces are not virtual anymore
From: Alexander Aring @ 2017-04-19 18:01 UTC (permalink / raw)
  To: Michael Richardson
  Cc: Network Development, Jukka Rissanen, Luiz Augusto von Dentz,
	linux-wpan@vger.kernel.org, Linux Bluetooth
In-Reply-To: <28530.1492534783@obiwan.sandelman.ca>

Hi Michael,

On 04/18/2017 06:59 PM, Michael Richardson wrote:
> 
> Alexander Aring <aar@pengutronix.de> wrote:
>     > What does the 6LoWPAN interface?
> 
>     > It will do a protocol change (an adaptation, because 6LoWPAN should
>     > provide the same functionality as IPv6) from IPv6 to 6LoWPAN (tx) and
>     > vice versa for (rx). In my opinion this should be handled as a virtual
>     > interface and not as an interface with a queue.
> 
> I wonder if modeling all the 6lowpan work as a virtual interface is even
> the right abstraction anymore.  I think that it was certainly a good model at
> the time the interface was created, given no other clear thing to do.
> 
> We don't model IPv6 ND (or IPv4 ARP) or fragmentation in general as a
> virtual interface on top of a raw interface.
> 
> Really, it's a set of operations that happens on a packet.
> 802.15.4 is notable for it's current lack of an ethertype (IEEE is fixing
> that though), so you can't actually run different protocols on the
> same PANID.
> BT does have a variety of different protocols, and IPv6 is only one.
> 
> In a classic SVR4 STREAMS works, it would have been just another module.
> (No, I'm not a fan of *STREAMS* or of SVR4 in general,  although I liked
> some of the ideas).
> 

ok, I see you complain about "having a virtual on top of wpan
interface", or?

I wanted to talk at first about the queue handling which is introduced
when 6LoWPAN is not a virtual interface anymore. Or do you want to have
a queue in front of 6lowpan adaptation (see other mail reply with ASCII
graphics).

My definition of virtual interfaces:
 - Virtual interfaces: has no queue.
 - Non Virtual interfaces: has queue(s).

> At this time, things like PANID and channel are set on the wpanX interface.
> If they were set on the 6lowpan interface, such that one could (in theory,
> assuming the hardware could do it, which some can, and some can not) then
> one could have multiple 6lowpan interfaces on top of the same wpanX.
> Or one could run some non-IP protocol like pre-IP Zigbee on one PANID
> while one runs 6lowpan on another.  THEN, a virtual interface would make
> sense for the same reason VLAN interfaces make sense.
> 

We can change that you can run multiple interfaces on one PHY. Currently
we just allow one, because address filtering. Disable address filtering
-> we will loose ACK handling on hardware.

I can try to implement all stuff in software "for fun, maybe see what we
can do to handle ACK in software, etc" Then you can run multiple wpan
interfaces on different "source PANID". Then we need some additonal
parameter for creating 6lowpan interfaces in case of 802.15.4 to add a
destination PANID. Last one should not big deal, because this doesn't
require to turn address filtering off.

One question would be:
It's fine to have it as _per_ interface setting or do you want to have
that on sendmsg(2) level?

---

You complain also, maybe... because currently it's hard to deal with
configuration 6lowpan interfaces with 802.15.4 interfaces. Because you
need to have both down to change address filtering etc.

What we can do there is "make it easier" if wpan interface goes down,
then upper 6LoWPAN interface goes also down (we can do that). But here
is the question - a userspace programm can do the same job.

For setting channels/panid for 6lowpan interfaces -> we can make that
nl802154 will also accept net_device namens for 802.15.4 6lowpan
interfaces which makes changes to the "lower" wpan interface -> should
be possible.

Let me known if you like to have such solution, which should make it
just simpler to dealing with ifdown/ifup and changing interface naming
stuff.

Currently, we forbid much stuff - We can do some changes (tx parameters)
when interface is up, just need to besure we don't changes paramters
while transmit. But make everything at first forbidden and then allows
more will usally not break UAPI. :-)

- Alex

^ permalink raw reply

* [PATCH] blutooth: try to improve CONFIG_SERIAL_DEV_BUS dependency
From: Arnd Bergmann @ 2017-04-19 17:50 UTC (permalink / raw)
  To: Marcel Holtmann, Gustavo Padovan, Johan Hedberg
  Cc: Sebastian Reichel, Rob Herring, Arnd Bergmann, Bjorn Andersson,
	David S. Miller, Kalle Valo, linux-bluetooth, linux-kernel

With CONFIG_SERIAL_DEV_BUS=m, the hci_serdev.o file does not actually
get built into hci_uart.o as the Makefile doesn't pick it up, leading
to a link error with anything referring to it:

ERROR: "hci_uart_register_device" [drivers/bluetooth/hci_nokia.ko] undefined!
scripts/Makefile.modpost:91: recipe for target '__modpost' failed

Changing this in the Makefile would cause another problem when
hci_uart itself is built-in and cannot reference symbols from the
serdev module.

This tries to address both problems by introducing a new hidden
Kconfig symbol that controls both the compilation of hci_serdev.o
and whether the Nokia driver can be selected. This seems to address
the problem for me, though there might be a better way to do it.

Fixes: 7bb318680e86 ("Bluetooth: add nokia driver")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/bluetooth/Kconfig  | 8 +++++++-
 drivers/bluetooth/Makefile | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 8aafbed9e160..737d93ef27c5 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -76,6 +76,12 @@ config BT_HCIUART
 	  Say Y here to compile support for Bluetooth UART devices into the
 	  kernel or say M to compile it as module (hci_uart).
 
+config BT_HCIUART_SERDEV
+	bool
+	depends on SERIAL_DEV_BUS && BT_HCIUART
+	depends on SERIAL_DEV_BUS=y || SERIAL_DEV_BUS=BT_HCIUART
+	default y
+
 config BT_HCIUART_H4
 	bool "UART (H4) protocol support"
 	depends on BT_HCIUART
@@ -89,7 +95,7 @@ config BT_HCIUART_H4
 config BT_HCIUART_NOKIA
 	tristate "UART Nokia H4+ protocol support"
 	depends on BT_HCIUART
-	depends on SERIAL_DEV_BUS
+	depends on BT_HCIUART_SERDEV
 	depends on PM
 	help
 	  Nokia H4+ is serial protocol for communication between Bluetooth
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index a7f237320f4b..e693ca6eeed9 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -31,7 +31,7 @@ btmrvl-y			:= btmrvl_main.o
 btmrvl-$(CONFIG_DEBUG_FS)	+= btmrvl_debugfs.o
 
 hci_uart-y				:= hci_ldisc.o
-hci_uart-$(CONFIG_SERIAL_DEV_BUS)	+= hci_serdev.o
+hci_uart-$(CONFIG_BT_HCIUART_SERDEV)	+= hci_serdev.o
 hci_uart-$(CONFIG_BT_HCIUART_H4)	+= hci_h4.o
 hci_uart-$(CONFIG_BT_HCIUART_BCSP)	+= hci_bcsp.o
 hci_uart-$(CONFIG_BT_HCIUART_LL)	+= hci_ll.o
-- 
2.9.0

^ permalink raw reply related

* Re: bluetooth 6lowpan interfaces are not virtual anymore
From: Alexander Aring @ 2017-04-19 17:43 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: Network Development, Jukka Rissanen, linux-wpan@vger.kernel.org,
	Linux Bluetooth, Michael Richardson
In-Reply-To: <CABBYNZLqTvd5cnG4fKJgPKJGvS6hsk8vOM+7NQ_RhLJ-WOszmg@mail.gmail.com>

Hi,

at first I want to clarify what my definition of virtual and non virtual
interface is:

- virtual interfaces: has no queue(s)
- non virtual interfaces: has a queue(s)

I did some "big" ASCII graphic what I think it will do now.
At first the virtual interface:

--- snip ---

Transmit side only! Case of virtual interface.            
                                                          
IPv6 Stack                                                
                                                          
                +-----------------------------+           
                |    IPv6 Packet (ND, etc)    |           
                +--------------+--------------+           
                               |                          
      -------------------------+---------------------------------
6LoWPAN Interface              |                          
                               |                          
                +--------------v--------------+           
                | Adaptation (IPv6 to 6Lo)    |           
                +--------------+--------------+
    +--------------------------+
    |
    | -----------------------------------------------------------
Link|Layer (802.15.4/hci_dev/etc)
    |
    |                  SKB Queue (With kind of discipline)
    |           +----------------+---------------+-------------+
    +----------->      SKB1      |     SKBN      |     ...     +----+
                +----------------+---------------+-------------+    |
                                                                    |
                                                                    |
      ------------------------------------------------------------  |
Real Transeiver Hardware                                            |
                                       +----------------------------+
                                       |
              +------------------------v-----------------------+
              |        Framebuffers (YOUR hardware resource)   |
              +------------------------------------------------+

--- snap ---

The non virtual interface:

--- snip ---

Transmit side only! Case of non virtual interface.
                                                          
IPv6 Stack                                                
                                                          
                +-----------------------------+           
                |    IPv6 Packet (ND, etc)    |           
                +--------------+--------------+
                               |
      -------------------------+---------------------------------
6LoWPAN Interface              |
                               |
    +--------------------------+
    |                                                              /> Will be queued if you stop the queue          
    |                  SKB Queue (With kind of discipline)      /--   Because Link Layer is full/software limitation
    |           +----------------+---------------+-------------+                                                     
    +----------->      SKB1      |     SKBN      |     ...     +----+                                                
                +----------------+---------------+-------------+    |                                                
                                                                    |                                                
                               +------------------------------------+                                                
                               |                                                                                     
                +--------------v--------------+                                                                      
                | Adaptation (IPv6 to 6Lo)    |                                                                      
                +--------------+--------------+                                                                      
    +--------------------------+                                                                                     
    |                                                                                                                
    | -----------------------------------------------------------                                                    
Link|Layer (802.15.4/hci_dev/etc)                                                                                    
    |                                                              -> software limitation (tx credits?)              
    |                  SKB Queue (With kind of discipline)     ---/   Right position to make different handling (for virtual case).
    |           +----------------+---------------+------------/+
    +----------->      SKB1      |     SKBN      |     ...     +----+
                +----------------+---------------+-------------+    |
                                                                    |
                                                                    |
      ------------------------------------------------------------  |
Real Transeiver Hardware                                            | 
                                       +----------------------------+
                                       |
              +------------------------v-----------------------+
              |        Framebuffers (YOUR hardware resource)   |
              +------------------------------------------------+


--- snap ---

Adding a queue to a interface which does a protocol translation only is
in my opinion: wrong.

At least if you want to try to make a more efficient qdisc handling,
means dropping skb's in queue when userspace sends too much. You will
change it back, control two queues seems to be difficult.

On 04/18/2017 12:43 PM, Luiz Augusto von Dentz wrote:
> Hi Alex,
> 
> On Mon, Apr 17, 2017 at 8:56 PM, Alexander Aring <aar@pengutronix.de> wrote:
>> Hi,
>>
>> bluetooth-next contains patches which introduces a queue for bluetooth
>> 6LoWPAN interfaces. [0]
>>
>> At first, the current behaviour is now that 802.15.4 6LoWPAN interfaces
>> are virtual and bluetooth 6LoWPAN interfaces are not virtual anymore.
>> To have a different handling in both subsystems is _definitely_ wrong.
> 
> Well 15.4 and Bluetooth have very different handling, iirc in 15.4 you
> do have a real interface which has, in fact, queueing support:
> 
> net/mac802154/iface.c:ieee802154_if_setup:
> dev->tx_queue_len = 300;
> 

Is l2cap_chan_send a call with is synchronized which wait for it so
after that the "l2cap bluetooth *frame*. etc." is send?

I looked at the code [0]. It will queue it in some skb queue, so far I
see. Hard to see it in this code, but I see some queueing and workqueue
scheduling [1] in the function which will be called by l2cap_chan_send.

This queue should have the same meaning like our queue in IEEE
802.15.4 interface which you mentioned above.
At this point, we have no difference. There exists already a queue for
your real transeiver hardware.

>> What does the 6LoWPAN interface?
>>
>> It will do a protocol change (an adaptation, because 6LoWPAN should
>> provide the same functionality as IPv6) from IPv6 to 6LoWPAN (tx) and
>> vice versa for (rx). In my opinion this should be handled as a virtual
>> interface and not as an interface with a queue.
> 
> Then we need a real netif for Bluetooth as well, one that does
> queueing since introducing for l2cap_chan makes no sense when most of
> time the userspace has a socket which does its own queueing. Btw, I
> have the opinion that doing a second interface just to make Bluetooth
> behave like 15.4 is very wasteful since we don't have any other
> network support except for bnep, which in fact does the same thing
> regarding queueing.
> 

If bnep just generates some ethernet frames and you put L2CAP around,
then it should be virtual too. If it queue skbs for sending out for the
hci_dev. Then it ends in a similar queue handling like "non virtual
6LoWPAN interface".

What you mean with second interface? At least you need a capable
net_device interface to offer an IP connection from userspace.

>> What makes a queue on 6LoWPAN interfaces?
>>
>> It will queue IPv6 packets which waits for it adaptation (the protocol
>> change) with some additional qdisc handling.
>> If finally the xmit_do callback will occur it will replace IPv6 header
>> with 6LoWPAN, etc. After that it should be queued into some queue on
>> link layer side which should be do the transmit finally.
> 
> In case of Bluetooth it does the Link Layer using L2CAP, which is not
> exactly at Link Layer, in fact it is one of the major problems of
> having this in Kernel space since it is similar of doing IP over TCP
> tunnel.
> 

aha, but this has nothing to do to decide that you have a 6LoWPAN queue,
or? I think this is one reason why you want a "6lowtun" interface. To
handle L2CAP in userspace.

>> Why I think bluetooth introduced a queue handling on 6LoWPAN interfaces?
>>
>> Because I think they don't like their own *qdisc* handling on their link
>> layer interface. I write *qdisc* here because, they have no net_devices
>> and use some kind of own qdisc handling.
> 
> No we don't, and except we do change the whole architecture of
> Bluetooth to work as a net_device I don't think we can have a similar
> design as 15.4. Anyway Bluetooth is not really designed to carry IP,
> the L2CAP and other profiles above are mostly a Bluetooth thing so
> having a net_device would not buy us much more than queueing for bnep
> and ipsp.
> 

At least, having a queue and don't put anything anymore into the queue
when "tx credits" is at zero (because queue is full). _Is_ a kind of
qdisc handling.

>> My question: is this correct?
>>
>> How to fix that (In my opinion):
>>
>> So commit [0] says something "out of credits" that's what I think it's
>> the *qdisc* handling. If you cannot queue anymore -> you need to drop
>> it. If you don't like how the current behaviour is, you need to change
>> your *qdisc* handling on your link layer interface. Introducing queue at
>> 6LoWPAN interfaces will introduce "buffer bloating".
> 
> That is not what the code comments says, eg. netif_stop_queue:
> 
>  * Stop upper layers calling the device hard_start_xmit routine.
>  * Used for flow control when transmit resources are unavailable.
> 

This comments are correct so long you operate on "real hardware
resources" which 6LoWPAN interfaces doesn't do. In case so far I see, it
will call l2cap_chan_send which putting some L2CAP protocol on it (to
provide data) and somewhere queue it for transmit to fill "real hardware
resources" e.g. framebuffers.

Your "resource" which is unavailable is the link layer queue, but this
is just a software limitation by bluetooth, which you can change by
software to make a different handling, than just adding more software queues.

What _virtual_ 6LoWPAN interface does is:

Input: IPv6 -> Output: 6LoWPAN, without any queueing in front of that.

> The fact 15.4, and bnep, uses these APIs makes me believe this is the
> proper way of using qdisc handling, the only difference here is at
> what level we would be using them.
> 

On 15.4 we use it for link layer interface queue, but we don't put
another queue in 6LoWPAN. See my aboves ASCII arts which shows the
different when 6LoWPAN is virtual and not virtual.

---

We have already qdisc problems in our case. In 15.4 it "just works" for
now, but we need more handling there to send not garbage if one frame
gets dropped there, see [2].

In my opinion, if bluetooth people will hit similar issues, you will
change it back that 6LoWPAN has no queue anymore. Otherwise it will very
hard to decide which skbs you drop or not - because you need to deal
with two queues.

To make 6LoWPAN non virtual anymore and just adding a queue will occur
that you don't drop much anymore... but the queue at link layer
(hci_dev) will work as before and this occurs buffer bloating only.

>> ---
>>
>> I don't care what bluetooth does with the 6LoWPAN interface. If bluetooth
>> people wants such behaviour, then I am okay with that.
>>
>> I will bookmark this mail for the time when somebody reverts it to a
>> virtual interface again. I think somebody will change it again, or maybe
>> somebody will argument why we need a queue here.
> 
> From what I could grasp from the code except if 6LoWPAN start creating
> its own interface, which it doesn't currently, it should never assume
> any specific behavior for an interface. 6LoWPAN right now only have
> helper functions which the interface code call on TX/RX, and by
> looking at code under 15.4 the only thing we would be doing is to set
> skb->dev = wdev; (wdev being the real device) as Bluetooth don't use
> 6lowpan fragmentation.
> 

yep, there is a lot of work do make a better framework, but has nothing
do to why bluetooth introduced a second queue on 6lowpan interfaces.

> Btw, another big different in terms of design that it seems 15.4 does
> create interfaces to each and every link, in Bluetooth the interface
> is per adapter so it is in fact multi-link, I guess in practice 15.4
> shall only have one 6lowpan link since it is connected to mesh, but in
> Bluetooth we may have more than one Link and I don't think it would be
> a good idea to have each of these links as a different interface,
> especially not with the same mac address as it seems to be what 15.4
> code is doing:
> 
> /* Set the lowpan hardware address to the wpan hardware address. */
> memcpy(ldev->dev_addr, wdev->dev_addr, IEEE802154_ADDR_LEN);
> 

Of course we need the same mac address there (at first), because we
have an address filter on hardware.

(Be aware that you _cannot_ change the mac address (dev->dev_addr) while IP
 capable net device is up. They assume the mac address is read only if net
 device is up.)

There is currently an idea to provide multiple links, but then hardware
need to go into promiscuous mode (disable address filtering) but then we
will lose some hardware offloading stuff e.g. ACK handling.
If we have that, we can provide multiple links with different mac
addresses, at least this will be handled as multiple wpan interfaces for
one PHY.

> So at least with IPSP/RFC-7668 the topology is completely different
> from what we can see in 15.4, it may happen that this changes with
> upcoming changes to Bluetooth, adding yet another topology that we
> will need to support. Personally I wouldn't mind if 15.4 and Bluetooth
> had more in common, at least at 6lowpan level, so we wouldn't have the
> need to create separated modules just to deal with their differences,
> but in reality, these technologies are competing for the same market
> so I don't think it will happen, unfortunately.
>

You already have separated modules, this is .e.g IPHC stuff and 6lowpan
specific implementation for bluetooth. In net/bluetooth/6lowpan.c you
can put your changes for make specific bluetooth handling.

This discussion moved currently to a more complex question about how to
make the whole 6lowpan architecture...

I think I tried to explain so much as possible what a queue on top of
6lowpan interface will do, at least if you want to make a better queue
handling (when dropping skb's inside the queue(s)) then you will fail
and revert that change (I think). But then I can say "I told you so" :-)

- Alex

[0] http://lxr.free-electrons.com/source/net/bluetooth/l2cap_core.c#L2455
[1] http://lxr.free-electrons.com/source/net/bluetooth/hci_core.c#L3490
[2] http://www.spinics.net/lists/linux-wpan/msg03679.html

^ permalink raw reply

* Re: [PATCH BlueZ v2 1/5] monitor: Add description for filter in scan parameters
From: Szymon Janc @ 2017-04-19 14:12 UTC (permalink / raw)
  To: Łukasz Rymanowski; +Cc: linux-bluetooth
In-Reply-To: <20170412124127.31486-1-lukasz.rymanowski@codecoup.pl>

Hi =C5=81ukasz,

On Wednesday, 12 April 2017 14:41:23 CEST =C5=81ukasz Rymanowski wrote:
> < HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7
>         Type: Active (0x01)
>         Interval: 30.000 msec (0x0030)
>         Window: 30.000 msec (0x0030)
>         Own address type: Public (0x00)
>         Filter policy: Accept all advertisement, inc. directed unresolved
> RPA (0x02) ---
>  monitor/packet.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>=20
> diff --git a/monitor/packet.c b/monitor/packet.c
> index 5d927f5..219542e 100644
> --- a/monitor/packet.c
> +++ b/monitor/packet.c
> @@ -6309,6 +6309,12 @@ static void le_set_scan_parameters_cmd(const void
> *data, uint8_t size) case 0x01:
>  		str =3D "Ignore not in white list";
>  		break;
> +	case 0x02:
> +		str =3D "Accept all advertisement, inc. directed unresolved RPA";
> +		break;
> +	case 0x03:
> +		str =3D "Ignore not in white list, exc. directed unresolved RPA";
> +		break;
>  	default:
>  		str =3D "Reserved";
>  		break;

All patches applied, thanks.

=2D-=20
pozdrawiam
Szymon Janc

^ permalink raw reply

* [bug report] Bluetooth: Introduce Qualcomm WCNSS SMD based HCI driver
From: Dan Carpenter @ 2017-04-19 13:51 UTC (permalink / raw)
  To: bjorn.andersson; +Cc: linux-bluetooth

Hello Bjorn Andersson,

The patch 1511cc750c3d: "Bluetooth: Introduce Qualcomm WCNSS SMD
based HCI driver" from Aug 12, 2016, leads to the following static
checker warning:

	net/bluetooth/hci_core.c:3349 hci_send_frame()
	error: double free of 'skb'

net/bluetooth/hci_core.c
    68  static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
    69  {
    70          struct btqcomsmd *btq = hci_get_drvdata(hdev);
    71          int ret;
    72  
    73          switch (hci_skb_pkt_type(skb)) {
    74          case HCI_ACLDATA_PKT:
    75                  ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
    76                  hdev->stat.acl_tx++;
    77                  hdev->stat.byte_tx += skb->len;
    78                  break;
    79          case HCI_COMMAND_PKT:
    80                  ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
    81                  hdev->stat.cmd_tx++;
    82                  break;
    83          default:
    84                  ret = -EILSEQ;
    85                  break;
    86          }
    87  
    88          kfree_skb(skb);
    89  
    90          return ret;
    91  }
    92  

This function is called from:

net/bluetooth/hci_core.c
  3320  static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
  3321  {
  3322          int err;
  3323  
  3324          BT_DBG("%s type %d len %d", hdev->name, hci_skb_pkt_type(skb),
  3325                 skb->len);
  3326  
  3327          /* Time stamp */
  3328          __net_timestamp(skb);
  3329  
  3330          /* Send copy to monitor */
  3331          hci_send_to_monitor(hdev, skb);
  3332  
  3333          if (atomic_read(&hdev->promisc)) {
  3334                  /* Send copy to the sockets */
  3335                  hci_send_to_sock(hdev, skb);
  3336          }
  3337  
  3338          /* Get rid of skb owner, prior to sending to the driver. */
  3339          skb_orphan(skb);
  3340  
  3341          if (!test_bit(HCI_RUNNING, &hdev->flags)) {
  3342                  kfree_skb(skb);
  3343                  return;
  3344          }
  3345  
  3346          err = hdev->send(hdev, skb);
  3347          if (err < 0) {
  3348                  BT_ERR("%s sending frame failed (%d)", hdev->name, err);
  3349                  kfree_skb(skb);

It expects that "skb" is freed on success but not on failure.  I think
ti_st_send_frame() has a similar bug.

  3350          }
  3351  }

regards,
dan carpenter

^ permalink raw reply

* Re: bluetooth 6lowpan interfaces are not virtual anymore
From: Michael Richardson @ 2017-04-18 16:59 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Network Development, Jukka Rissanen, Luiz Augusto von Dentz,
	linux-wpan@vger.kernel.org, Linux Bluetooth
In-Reply-To: <2d178eb8-3fbc-3385-6e0c-fa9941713959@pengutronix.de>

[-- Attachment #1: Type: text/plain, Size: 1888 bytes --]


Alexander Aring <aar@pengutronix.de> wrote:
    > What does the 6LoWPAN interface?

    > It will do a protocol change (an adaptation, because 6LoWPAN should
    > provide the same functionality as IPv6) from IPv6 to 6LoWPAN (tx) and
    > vice versa for (rx). In my opinion this should be handled as a virtual
    > interface and not as an interface with a queue.

I wonder if modeling all the 6lowpan work as a virtual interface is even
the right abstraction anymore.  I think that it was certainly a good model at
the time the interface was created, given no other clear thing to do.

We don't model IPv6 ND (or IPv4 ARP) or fragmentation in general as a
virtual interface on top of a raw interface.

Really, it's a set of operations that happens on a packet.
802.15.4 is notable for it's current lack of an ethertype (IEEE is fixing
that though), so you can't actually run different protocols on the
same PANID.
BT does have a variety of different protocols, and IPv6 is only one.

In a classic SVR4 STREAMS works, it would have been just another module.
(No, I'm not a fan of *STREAMS* or of SVR4 in general,  although I liked
some of the ideas).

At this time, things like PANID and channel are set on the wpanX interface.
If they were set on the 6lowpan interface, such that one could (in theory,
assuming the hardware could do it, which some can, and some can not) then
one could have multiple 6lowpan interfaces on top of the same wpanX.
Or one could run some non-IP protocol like pre-IP Zigbee on one PANID
while one runs 6lowpan on another.  THEN, a virtual interface would make
sense for the same reason VLAN interfaces make sense.


--
]               Never tell me the odds!                 | ipv6 mesh networks [
]   Michael Richardson, Sandelman Software Works        | network architect  [
]     mcr@sandelman.ca  http://www.sandelman.ca/        |   ruby on rails    [


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 487 bytes --]

^ permalink raw reply

* Re: bluetooth 6lowpan interfaces are not virtual anymore
From: Luiz Augusto von Dentz @ 2017-04-18 10:43 UTC (permalink / raw)
  To: Alexander Aring
  Cc: Network Development, Jukka Rissanen, linux-wpan@vger.kernel.org,
	Linux Bluetooth
In-Reply-To: <2d178eb8-3fbc-3385-6e0c-fa9941713959@pengutronix.de>

Hi Alex,

On Mon, Apr 17, 2017 at 8:56 PM, Alexander Aring <aar@pengutronix.de> wrote:
> Hi,
>
> bluetooth-next contains patches which introduces a queue for bluetooth
> 6LoWPAN interfaces. [0]
>
> At first, the current behaviour is now that 802.15.4 6LoWPAN interfaces
> are virtual and bluetooth 6LoWPAN interfaces are not virtual anymore.
> To have a different handling in both subsystems is _definitely_ wrong.

Well 15.4 and Bluetooth have very different handling, iirc in 15.4 you
do have a real interface which has, in fact, queueing support:

net/mac802154/iface.c:ieee802154_if_setup:
dev->tx_queue_len = 300;

> What does the 6LoWPAN interface?
>
> It will do a protocol change (an adaptation, because 6LoWPAN should
> provide the same functionality as IPv6) from IPv6 to 6LoWPAN (tx) and
> vice versa for (rx). In my opinion this should be handled as a virtual
> interface and not as an interface with a queue.

Then we need a real netif for Bluetooth as well, one that does
queueing since introducing for l2cap_chan makes no sense when most of
time the userspace has a socket which does its own queueing. Btw, I
have the opinion that doing a second interface just to make Bluetooth
behave like 15.4 is very wasteful since we don't have any other
network support except for bnep, which in fact does the same thing
regarding queueing.

> What makes a queue on 6LoWPAN interfaces?
>
> It will queue IPv6 packets which waits for it adaptation (the protocol
> change) with some additional qdisc handling.
> If finally the xmit_do callback will occur it will replace IPv6 header
> with 6LoWPAN, etc. After that it should be queued into some queue on
> link layer side which should be do the transmit finally.

In case of Bluetooth it does the Link Layer using L2CAP, which is not
exactly at Link Layer, in fact it is one of the major problems of
having this in Kernel space since it is similar of doing IP over TCP
tunnel.

> Why I think bluetooth introduced a queue handling on 6LoWPAN interfaces?
>
> Because I think they don't like their own *qdisc* handling on their link
> layer interface. I write *qdisc* here because, they have no net_devices
> and use some kind of own qdisc handling.

No we don't, and except we do change the whole architecture of
Bluetooth to work as a net_device I don't think we can have a similar
design as 15.4. Anyway Bluetooth is not really designed to carry IP,
the L2CAP and other profiles above are mostly a Bluetooth thing so
having a net_device would not buy us much more than queueing for bnep
and ipsp.

> My question: is this correct?
>
> How to fix that (In my opinion):
>
> So commit [0] says something "out of credits" that's what I think it's
> the *qdisc* handling. If you cannot queue anymore -> you need to drop
> it. If you don't like how the current behaviour is, you need to change
> your *qdisc* handling on your link layer interface. Introducing queue at
> 6LoWPAN interfaces will introduce "buffer bloating".

That is not what the code comments says, eg. netif_stop_queue:

 * Stop upper layers calling the device hard_start_xmit routine.
 * Used for flow control when transmit resources are unavailable.

The fact 15.4, and bnep, uses these APIs makes me believe this is the
proper way of using qdisc handling, the only difference here is at
what level we would be using them.

> ---
>
> I don't care what bluetooth does with the 6LoWPAN interface. If bluetooth
> people wants such behaviour, then I am okay with that.
>
> I will bookmark this mail for the time when somebody reverts it to a
> virtual interface again. I think somebody will change it again, or maybe
> somebody will argument why we need a queue here.

>From what I could grasp from the code except if 6LoWPAN start creating
its own interface, which it doesn't currently, it should never assume
any specific behavior for an interface. 6LoWPAN right now only have
helper functions which the interface code call on TX/RX, and by
looking at code under 15.4 the only thing we would be doing is to set
skb->dev = wdev; (wdev being the real device) as Bluetooth don't use
6lowpan fragmentation.

Btw, another big different in terms of design that it seems 15.4 does
create interfaces to each and every link, in Bluetooth the interface
is per adapter so it is in fact multi-link, I guess in practice 15.4
shall only have one 6lowpan link since it is connected to mesh, but in
Bluetooth we may have more than one Link and I don't think it would be
a good idea to have each of these links as a different interface,
especially not with the same mac address as it seems to be what 15.4
code is doing:

/* Set the lowpan hardware address to the wpan hardware address. */
memcpy(ldev->dev_addr, wdev->dev_addr, IEEE802154_ADDR_LEN);

So at least with IPSP/RFC-7668 the topology is completely different
from what we can see in 15.4, it may happen that this changes with
upcoming changes to Bluetooth, adding yet another topology that we
will need to support. Personally I wouldn't mind if 15.4 and Bluetooth
had more in common, at least at 6lowpan level, so we wouldn't have the
need to create separated modules just to deal with their differences,
but in reality, these technologies are competing for the same market
so I don't think it will happen, unfortunately.

> - Alex
>
> [0] https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git/commit/?id=814f1b243d2c63928f6aa72d66bec0e5fae2f4a9



-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH v3 3/4] bluetooth: hci_uart: add LL protocol serdev driver support
From: Adam Ford @ 2017-04-17 20:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: Marcel Holtmann, linux-bluetooth, Mark Rutland, devicetree,
	Johan Hedberg, Gustavo Padovan, Satish Patel, Wei Xu, Eyal Reizer,
	netdev, linux-arm-kernel
In-Reply-To: <20170413150353.7389-4-robh@kernel.org>

On Thu, Apr 13, 2017 at 10:03 AM, Rob Herring <robh@kernel.org> wrote:
> Turns out that the LL protocol and the TI-ST are the same thing AFAICT.
> The TI-ST adds firmware loading, GPIO control, and shared access for
> NFC, FM radio, etc. For now, we're only implementing what is needed for
> BT. This mirrors other drivers like BCM and Intel, but uses the new
> serdev bus.
>
> The firmware loading is greatly simplified by using existing
> infrastructure to send commands. It may be a bit slower than the
> original code using synchronous functions, but the real bottleneck is
> likely doing firmware load at 115.2kbps.

I am using pdata-quirks to drive my wl1283 Bluetooth on a DM3730.  I
have the Bluetooth set to 3000000 baud in pdata quirks.  Looking at
the binding, I don't see an option to set the baudrate.  Is there (or
will there) be a way to set the baud rate of the Bluetooth?

adam
>
> Signed-off-by: Rob Herring <robh@kernel.org>
> Cc: Marcel Holtmann <marcel@holtmann.org>
> Cc: Gustavo Padovan <gustavo@padovan.org>
> Cc: Johan Hedberg <johan.hedberg@gmail.com>
> Cc: linux-bluetooth@vger.kernel.org
> ---
> v3:
> - rebase on bluetooth-next
> - Add explicit of.h include
> v2:
> - Use IS_ENABLED() to fix module build
>
>  drivers/bluetooth/hci_ll.c | 262 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 261 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
> index 02692fe30279..485e8eb04542 100644
> --- a/drivers/bluetooth/hci_ll.c
> +++ b/drivers/bluetooth/hci_ll.c
> @@ -34,20 +34,24 @@
>  #include <linux/sched.h>
>  #include <linux/types.h>
>  #include <linux/fcntl.h>
> +#include <linux/firmware.h>
>  #include <linux/interrupt.h>
>  #include <linux/ptrace.h>
>  #include <linux/poll.h>
>
>  #include <linux/slab.h>
> -#include <linux/tty.h>
>  #include <linux/errno.h>
>  #include <linux/string.h>
>  #include <linux/signal.h>
>  #include <linux/ioctl.h>
> +#include <linux/of.h>
> +#include <linux/serdev.h>
>  #include <linux/skbuff.h>
> +#include <linux/ti_wilink_st.h>
>
>  #include <net/bluetooth/bluetooth.h>
>  #include <net/bluetooth/hci_core.h>
> +#include <linux/gpio/consumer.h>
>
>  #include "hci_uart.h"
>
> @@ -76,6 +80,12 @@ struct hcill_cmd {
>         u8 cmd;
>  } __packed;
>
> +struct ll_device {
> +       struct hci_uart hu;
> +       struct serdev_device *serdev;
> +       struct gpio_desc *enable_gpio;
> +};
> +
>  struct ll_struct {
>         unsigned long rx_state;
>         unsigned long rx_count;
> @@ -136,6 +146,9 @@ static int ll_open(struct hci_uart *hu)
>
>         hu->priv = ll;
>
> +       if (hu->serdev)
> +               serdev_device_open(hu->serdev);
> +
>         return 0;
>  }
>
> @@ -164,6 +177,13 @@ static int ll_close(struct hci_uart *hu)
>
>         kfree_skb(ll->rx_skb);
>
> +       if (hu->serdev) {
> +               struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev);
> +               gpiod_set_value_cansleep(lldev->enable_gpio, 0);
> +
> +               serdev_device_close(hu->serdev);
> +       }
> +
>         hu->priv = NULL;
>
>         kfree(ll);
> @@ -505,9 +525,245 @@ static struct sk_buff *ll_dequeue(struct hci_uart *hu)
>         return skb_dequeue(&ll->txq);
>  }
>
> +#if IS_ENABLED(CONFIG_SERIAL_DEV_BUS)
> +static int read_local_version(struct hci_dev *hdev)
> +{
> +       int err = 0;
> +       unsigned short version = 0;
> +       struct sk_buff *skb;
> +       struct hci_rp_read_local_version *ver;
> +
> +       skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT);
> +       if (IS_ERR(skb)) {
> +               bt_dev_err(hdev, "Reading TI version information failed (%ld)",
> +                          PTR_ERR(skb));
> +               err = PTR_ERR(skb);
> +               goto out;
> +       }
> +       if (skb->len != sizeof(*ver)) {
> +               err = -EILSEQ;
> +               goto out;
> +       }
> +
> +       ver = (struct hci_rp_read_local_version *)skb->data;
> +       if (le16_to_cpu(ver->manufacturer) != 13) {
> +               err = -ENODEV;
> +               goto out;
> +       }
> +
> +       version = le16_to_cpu(ver->lmp_subver);
> +
> +out:
> +       if (err) bt_dev_err(hdev, "Failed to read TI version info: %d", err);
> +       kfree_skb(skb);
> +       return err ? err : version;
> +}
> +
> +/**
> + * download_firmware -
> + *     internal function which parses through the .bts firmware
> + *     script file intreprets SEND, DELAY actions only as of now
> + */
> +static int download_firmware(struct ll_device *lldev)
> +{
> +       unsigned short chip, min_ver, maj_ver;
> +       int version, err, len;
> +       unsigned char *ptr, *action_ptr;
> +       unsigned char bts_scr_name[40]; /* 40 char long bts scr name? */
> +       const struct firmware *fw;
> +       struct sk_buff *skb;
> +       struct hci_command *cmd;
> +
> +       version = read_local_version(lldev->hu.hdev);
> +       if (version < 0)
> +               return version;
> +
> +       chip = (version & 0x7C00) >> 10;
> +       min_ver = (version & 0x007F);
> +       maj_ver = (version & 0x0380) >> 7;
> +       if (version & 0x8000)
> +               maj_ver |= 0x0008;
> +
> +       snprintf(bts_scr_name, sizeof(bts_scr_name),
> +                "ti-connectivity/TIInit_%d.%d.%d.bts",
> +                chip, maj_ver, min_ver);
> +
> +       err = request_firmware(&fw, bts_scr_name, &lldev->serdev->dev);
> +       if (err || !fw->data || !fw->size) {
> +               bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s",
> +                          err, bts_scr_name);
> +               return -EINVAL;
> +       }
> +       ptr = (void *)fw->data;
> +       len = fw->size;
> +       /* bts_header to remove out magic number and
> +        * version
> +        */
> +       ptr += sizeof(struct bts_header);
> +       len -= sizeof(struct bts_header);
> +
> +       while (len > 0 && ptr) {
> +               bt_dev_dbg(lldev->hu.hdev, " action size %d, type %d ",
> +                          ((struct bts_action *)ptr)->size,
> +                          ((struct bts_action *)ptr)->type);
> +
> +               action_ptr = &(((struct bts_action *)ptr)->data[0]);
> +
> +               switch (((struct bts_action *)ptr)->type) {
> +               case ACTION_SEND_COMMAND:       /* action send */
> +                       bt_dev_dbg(lldev->hu.hdev, "S");
> +                       cmd = (struct hci_command *)action_ptr;
> +                       if (cmd->opcode == 0xff36) {
> +                               /* ignore remote change
> +                                * baud rate HCI VS command */
> +                               bt_dev_warn(lldev->hu.hdev, "change remote baud rate command in firmware");
> +                               break;
> +                       }
> +                       if (cmd->prefix != 1)
> +                               bt_dev_dbg(lldev->hu.hdev, "command type %d\n", cmd->prefix);
> +
> +                       skb = __hci_cmd_sync(lldev->hu.hdev, cmd->opcode, cmd->plen, &cmd->speed, HCI_INIT_TIMEOUT);
> +                       if (IS_ERR(skb)) {
> +                               bt_dev_err(lldev->hu.hdev, "send command failed\n");
> +                               goto out_rel_fw;
> +                       }
> +                       kfree_skb(skb);
> +                       break;
> +               case ACTION_WAIT_EVENT:  /* wait */
> +                       /* no need to wait as command was synchronous */
> +                       bt_dev_dbg(lldev->hu.hdev, "W");
> +                       break;
> +               case ACTION_DELAY:      /* sleep */
> +                       bt_dev_info(lldev->hu.hdev, "sleep command in scr");
> +                       mdelay(((struct bts_action_delay *)action_ptr)->msec);
> +                       break;
> +               }
> +               len -= (sizeof(struct bts_action) +
> +                       ((struct bts_action *)ptr)->size);
> +               ptr += sizeof(struct bts_action) +
> +                       ((struct bts_action *)ptr)->size;
> +       }
> +
> +out_rel_fw:
> +       /* fw download complete */
> +       release_firmware(fw);
> +       return err;
> +}
> +
> +static int ll_setup(struct hci_uart *hu)
> +{
> +       int err, retry = 3;
> +       struct ll_device *lldev;
> +       struct serdev_device *serdev = hu->serdev;
> +       u32 speed;
> +
> +       if (!serdev)
> +               return 0;
> +
> +       lldev = serdev_device_get_drvdata(serdev);
> +
> +       serdev_device_set_flow_control(serdev, true);
> +
> +       do {
> +               /* Configure BT_EN to HIGH state */
> +               gpiod_set_value_cansleep(lldev->enable_gpio, 0);
> +               msleep(5);
> +               gpiod_set_value_cansleep(lldev->enable_gpio, 1);
> +               msleep(100);
> +
> +               err = download_firmware(lldev);
> +               if (!err)
> +                       break;
> +
> +               /* Toggle BT_EN and retry */
> +               bt_dev_err(hu->hdev, "download firmware failed, retrying...");
> +       } while (retry--);
> +
> +       if (err)
> +               return err;
> +
> +       /* Operational speed if any */
> +       if (hu->oper_speed)
> +               speed = hu->oper_speed;
> +       else if (hu->proto->oper_speed)
> +               speed = hu->proto->oper_speed;
> +       else
> +               speed = 0;
> +
> +       if (speed) {
> +               struct sk_buff *skb = __hci_cmd_sync(hu->hdev, 0xff36, sizeof(speed), &speed, HCI_INIT_TIMEOUT);
> +               if (!IS_ERR(skb)) {
> +                       kfree_skb(skb);
> +                       serdev_device_set_baudrate(serdev, speed);
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct hci_uart_proto llp;
> +
> +static int hci_ti_probe(struct serdev_device *serdev)
> +{
> +       struct hci_uart *hu;
> +       struct ll_device *lldev;
> +       u32 max_speed = 3000000;
> +
> +       lldev = devm_kzalloc(&serdev->dev, sizeof(struct ll_device), GFP_KERNEL);
> +       if (!lldev)
> +               return -ENOMEM;
> +       hu = &lldev->hu;
> +
> +       serdev_device_set_drvdata(serdev, lldev);
> +       lldev->serdev = hu->serdev = serdev;
> +
> +       lldev->enable_gpio = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW);
> +       if (IS_ERR(lldev->enable_gpio))
> +               return PTR_ERR(lldev->enable_gpio);
> +
> +       of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed);
> +       hci_uart_set_speeds(hu, 115200, max_speed);
> +
> +       return hci_uart_register_device(hu, &llp);
> +}
> +
> +static void hci_ti_remove(struct serdev_device *serdev)
> +{
> +       struct ll_device *lldev = serdev_device_get_drvdata(serdev);
> +       struct hci_uart *hu = &lldev->hu;
> +       struct hci_dev *hdev = hu->hdev;
> +
> +       cancel_work_sync(&hu->write_work);
> +
> +       hci_unregister_dev(hdev);
> +       hci_free_dev(hdev);
> +       hu->proto->close(hu);
> +}
> +
> +static const struct of_device_id hci_ti_of_match[] = {
> +       { .compatible = "ti,wl1831-st" },
> +       { .compatible = "ti,wl1835-st" },
> +       { .compatible = "ti,wl1837-st" },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, hci_ti_of_match);
> +
> +static struct serdev_device_driver hci_ti_drv = {
> +       .driver         = {
> +               .name   = "hci-ti",
> +               .of_match_table = of_match_ptr(hci_ti_of_match),
> +       },
> +       .probe  = hci_ti_probe,
> +       .remove = hci_ti_remove,
> +};
> +#else
> +#define ll_setup NULL
> +#endif
> +
>  static const struct hci_uart_proto llp = {
>         .id             = HCI_UART_LL,
>         .name           = "LL",
> +       .setup          = ll_setup,
>         .open           = ll_open,
>         .close          = ll_close,
>         .recv           = ll_recv,
> @@ -518,10 +774,14 @@ static const struct hci_uart_proto llp = {
>
>  int __init ll_init(void)
>  {
> +       serdev_device_driver_register(&hci_ti_drv);
> +
>         return hci_uart_register_proto(&llp);
>  }
>
>  int __exit ll_deinit(void)
>  {
> +       serdev_device_driver_unregister(&hci_ti_drv);
> +
>         return hci_uart_unregister_proto(&llp);
>  }
> --
> 2.11.0
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: pull request: bluetooth-next 2017-04-14
From: David Miller @ 2017-04-17 19:02 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth, netdev
In-Reply-To: <20170414181212.GA27363@x1c.P-661HNU-F1>

From: Johan Hedberg <johan.hedberg@gmail.com>
Date: Fri, 14 Apr 2017 21:12:12 +0300

> Here's the main batch of Bluetooth & 802.15.4 patches for the 4.12
> kernel.
> 
>  - Many fixes to 6LoWPAN, in particular for BLE
>  - New CA8210 IEEE 802.15.4 device driver (accounting for most of the
>    lines of code added in this pull request)
>  - Added Nokia Bluetooth (UART) HCI driver
>  - Some serdev & TTY changes that are dependencies for the Nokia
>    driver (with acks from relevant maintainers and an agreement that
>    these come through the bluetooth tree)
>  - Support for new Intel Bluetooth device
>  - Various other minor cleanups/fixes here and there
> 
> Please let me know if there are any issues pulling. Thanks.

Applied, thanks.

^ permalink raw reply

* bluetooth 6lowpan interfaces are not virtual anymore
From: Alexander Aring @ 2017-04-17 17:56 UTC (permalink / raw)
  To: Network Development
  Cc: Jukka Rissanen, Luiz Augusto von Dentz,
	linux-wpan@vger.kernel.org, Linux Bluetooth

Hi,

bluetooth-next contains patches which introduces a queue for bluetooth
6LoWPAN interfaces. [0]

At first, the current behaviour is now that 802.15.4 6LoWPAN interfaces
are virtual and bluetooth 6LoWPAN interfaces are not virtual anymore.
To have a different handling in both subsystems is _definitely_ wrong.

What does the 6LoWPAN interface?

It will do a protocol change (an adaptation, because 6LoWPAN should
provide the same functionality as IPv6) from IPv6 to 6LoWPAN (tx) and
vice versa for (rx). In my opinion this should be handled as a virtual
interface and not as an interface with a queue.

What makes a queue on 6LoWPAN interfaces?

It will queue IPv6 packets which waits for it adaptation (the protocol
change) with some additional qdisc handling.
If finally the xmit_do callback will occur it will replace IPv6 header
with 6LoWPAN, etc. After that it should be queued into some queue on
link layer side which should be do the transmit finally.

Why I think bluetooth introduced a queue handling on 6LoWPAN interfaces?

Because I think they don't like their own *qdisc* handling on their link
layer interface. I write *qdisc* here because, they have no net_devices
and use some kind of own qdisc handling.

My question: is this correct?

How to fix that (In my opinion):

So commit [0] says something "out of credits" that's what I think it's
the *qdisc* handling. If you cannot queue anymore -> you need to drop
it. If you don't like how the current behaviour is, you need to change
your *qdisc* handling on your link layer interface. Introducing queue at
6LoWPAN interfaces will introduce "buffer bloating".

---

I don't care what bluetooth does with the 6LoWPAN interface. If bluetooth
people wants such behaviour, then I am okay with that.

I will bookmark this mail for the time when somebody reverts it to a
virtual interface again. I think somebody will change it again, or maybe
somebody will argument why we need a queue here. 

- Alex

[0] https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git/commit/?id=814f1b243d2c63928f6aa72d66bec0e5fae2f4a9

^ permalink raw reply

* Re: [PATCH] ARM: dts: omap4-droid4: add bluetooth
From: Rob Herring @ 2017-04-17 12:51 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Michael Scott, open list:BLUETOOTH DRIVERS, linux-omap,
	linux-kernel@vger.kernel.org, Tony Lindgren
In-Reply-To: <20170416152650.5376wwhhdcbpdba5@earth>

On Sun, Apr 16, 2017 at 10:26 AM, Sebastian Reichel <sre@kernel.org> wrote:
> Hi Michael,
>
> On Sat, Apr 15, 2017 at 07:00:29PM -0700, Michael Scott wrote:
>> On Apr 15, 2017 3:18 PM, "Sebastian Reichel" <sre@kernel.org> wrote:
>>> Droid 4 has wl1835 connected to the OMAP's UART4 port, which is
>>
>> Technically, I believe the Droid 4 has WL1283 WLAN chip.
>>
>> - Mike
>
> iFixit [0] has a nice photo in step 15, which clearly shows,
> that its a WL1285C, with 1835 looking similar I didn't notice
> Rob's binding does not cover wl128x. I will resend with proper
> compatible value (+ patches for the driver and binding).

I only documented what was publicly available as some parts have
failed to materialize. Any idea what the differences are?

Rob

^ permalink raw reply

* [bluetooth-next:master 25/60] drivers/clocksource/timer-sun5i.c:52:21: error: field 'clksrc' has incomplete type
From: kbuild test robot @ 2017-04-16 22:12 UTC (permalink / raw)
  To: Harry Morris; +Cc: kbuild-all, linux-bluetooth, Marcel Holtmann

[-- Attachment #1: Type: text/plain, Size: 44633 bytes --]

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
head:   297c3fb207ef8bc97daa144fb41c1fa9560f6965
commit: ded845a781a578dfb0b5b2c138e5a067aa3b1242 [25/60] ieee802154: Add CA8210 IEEE 802.15.4 device driver
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout ded845a781a578dfb0b5b2c138e5a067aa3b1242
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

>> drivers/clocksource/timer-sun5i.c:52:21: error: field 'clksrc' has incomplete type
     struct clocksource clksrc;
                        ^~~~~~
>> drivers/clocksource/timer-sun5i.c:60:28: error: field 'clkevt' has incomplete type
     struct clock_event_device clkevt;
                               ^~~~~~
   In file included from include/linux/clk.h:16:0,
                    from drivers/clocksource/timer-sun5i.c:13:
   drivers/clocksource/timer-sun5i.c: In function 'sun5i_clkevt_shutdown':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:108:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:108:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c: In function 'sun5i_clkevt_set_oneshot':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:116:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:116:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c: In function 'sun5i_clkevt_set_periodic':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:125:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:125:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c: In function 'sun5i_clkevt_next_event':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:136:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:136:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c: In function 'sun5i_clksrc_read':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:56:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clksrc, clksrc)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:157:34: note: in expansion of macro 'to_sun5i_timer_clksrc'
     struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'cs')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/timer-sun5i.c:56:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clksrc, clksrc)
     ^~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:157:34: note: in expansion of macro 'to_sun5i_timer_clksrc'
     struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c: In function 'sun5i_rate_cb_clksrc':
>> drivers/clocksource/timer-sun5i.c:171:3: error: implicit declaration of function 'clocksource_unregister' [-Werror=implicit-function-declaration]
      clocksource_unregister(&cs->clksrc);
      ^~~~~~~~~~~~~~~~~~~~~~
>> drivers/clocksource/timer-sun5i.c:175:3: error: implicit declaration of function 'clocksource_register_hz' [-Werror=implicit-function-declaration]
      clocksource_register_hz(&cs->clksrc, ndata->new_rate);
      ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c: In function 'sun5i_setup_clocksource':
>> drivers/clocksource/timer-sun5i.c:223:20: error: implicit declaration of function 'CLOCKSOURCE_MASK' [-Werror=implicit-function-declaration]
     cs->clksrc.mask = CLOCKSOURCE_MASK(32);
                       ^~~~~~~~~~~~~~~~
>> drivers/clocksource/timer-sun5i.c:224:21: error: 'CLOCK_SOURCE_IS_CONTINUOUS' undeclared (first use in this function)
     cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:224:21: note: each undeclared identifier is reported only once for each function it appears in
   drivers/clocksource/timer-sun5i.c: In function 'sun5i_rate_cb_clkevt':
>> drivers/clocksource/timer-sun5i.c:251:3: error: implicit declaration of function 'clockevents_update_freq' [-Werror=implicit-function-declaration]
      clockevents_update_freq(&ce->clkevt, ndata->new_rate);
      ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c: In function 'sun5i_setup_clockevent':
>> drivers/clocksource/timer-sun5i.c:291:24: error: 'CLOCK_EVT_FEAT_PERIODIC' undeclared (first use in this function)
     ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
                           ^~~~~~~~~~~~~~~~~~~~~~~
>> drivers/clocksource/timer-sun5i.c:291:50: error: 'CLOCK_EVT_FEAT_ONESHOT' undeclared (first use in this function)
     ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
                                                     ^~~~~~~~~~~~~~~~~~~~~~
>> drivers/clocksource/timer-sun5i.c:305:2: error: implicit declaration of function 'clockevents_config_and_register' [-Werror=implicit-function-declaration]
     clockevents_config_and_register(&ce->clkevt, rate,
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c: At top level:
>> drivers/clocksource/timer-sun5i.c:361:35: error: expected ')' before string constant
    CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:363:35: error: expected ')' before string constant
    CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/timer-sun5i.c:326:19: warning: 'sun5i_timer_init' defined but not used [-Wunused-function]
    static int __init sun5i_timer_init(struct device_node *node)
                      ^~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
>> drivers/clocksource/cadence_ttc_timer.c:92:21: error: field 'cs' has incomplete type
     struct clocksource cs;
                        ^~
>> drivers/clocksource/cadence_ttc_timer.c:100:28: error: field 'ce' has incomplete type
     struct clock_event_device ce;
                               ^~
   In file included from include/linux/clk.h:16:0,
                    from drivers/clocksource/cadence_ttc_timer.c:18:
   drivers/clocksource/cadence_ttc_timer.c: In function '__ttc_clocksource_read':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:96:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clocksource, cs)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:163:29: note: in expansion of macro 'to_ttc_timer_clksrc'
     struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc;
                                ^~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'timer')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:96:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clocksource, cs)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:163:29: note: in expansion of macro 'to_ttc_timer_clksrc'
     struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc;
                                ^~~~~~~~~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c: In function 'ttc_set_next_event':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:104:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clockevent, ce)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:185:38: note: in expansion of macro 'to_ttc_timer_clkevent'
     struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
                                         ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ttce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:104:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clockevent, ce)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:185:38: note: in expansion of macro 'to_ttc_timer_clkevent'
     struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
                                         ^~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c: In function 'ttc_shutdown':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:104:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clockevent, ce)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:199:38: note: in expansion of macro 'to_ttc_timer_clkevent'
     struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
                                         ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ttce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:104:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clockevent, ce)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:199:38: note: in expansion of macro 'to_ttc_timer_clkevent'
     struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
                                         ^~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c: In function 'ttc_set_periodic':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:104:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clockevent, ce)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:211:38: note: in expansion of macro 'to_ttc_timer_clkevent'
     struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
                                         ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ttce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:104:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clockevent, ce)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:211:38: note: in expansion of macro 'to_ttc_timer_clkevent'
     struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
                                         ^~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c: In function 'ttc_resume':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:104:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clockevent, ce)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:221:38: note: in expansion of macro 'to_ttc_timer_clkevent'
     struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
                                         ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ttce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers/clocksource/cadence_ttc_timer.c:104:3: note: in expansion of macro 'container_of'
      container_of(x, struct ttc_timer_clockevent, ce)
      ^~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:221:38: note: in expansion of macro 'to_ttc_timer_clkevent'
     struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
                                         ^~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c: In function 'ttc_setup_clocksource':
>> drivers/clocksource/cadence_ttc_timer.c:358:19: error: implicit declaration of function 'CLOCKSOURCE_MASK' [-Werror=implicit-function-declaration]
     ttccs->cs.mask = CLOCKSOURCE_MASK(timer_width);
                      ^~~~~~~~~~~~~~~~
>> drivers/clocksource/cadence_ttc_timer.c:359:20: error: 'CLOCK_SOURCE_IS_CONTINUOUS' undeclared (first use in this function)
     ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:359:20: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/clocksource/cadence_ttc_timer.c:372:8: error: implicit declaration of function 'clocksource_register_hz' [-Werror=implicit-function-declaration]
     err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE);
           ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c: In function 'ttc_rate_change_clockevent_cb':
>> drivers/clocksource/cadence_ttc_timer.c:398:3: error: implicit declaration of function 'clockevents_update_freq' [-Werror=implicit-function-declaration]
      clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE);
      ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c: In function 'ttc_setup_clockevent':
>> drivers/clocksource/cadence_ttc_timer.c:441:23: error: 'CLOCK_EVT_FEAT_PERIODIC' undeclared (first use in this function)
     ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
                          ^~~~~~~~~~~~~~~~~~~~~~~
>> drivers/clocksource/cadence_ttc_timer.c:441:49: error: 'CLOCK_EVT_FEAT_ONESHOT' undeclared (first use in this function)
     ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
                                                    ^~~~~~~~~~~~~~~~~~~~~~
>> drivers/clocksource/cadence_ttc_timer.c:468:2: error: implicit declaration of function 'clockevents_config_and_register' [-Werror=implicit-function-declaration]
     clockevents_config_and_register(&ttcce->ce,
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c: At top level:
>> drivers/clocksource/cadence_ttc_timer.c:542:29: error: expected ')' before string constant
    CLOCKSOURCE_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init);
                                ^~~~~~~~~~
   drivers/clocksource/cadence_ttc_timer.c:480:19: warning: 'ttc_timer_init' defined but not used [-Wunused-function]
    static int __init ttc_timer_init(struct device_node *timer)
                      ^~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers//clocksource/timer-sun5i.c:52:21: error: field 'clksrc' has incomplete type
     struct clocksource clksrc;
                        ^~~~~~
   drivers//clocksource/timer-sun5i.c:60:28: error: field 'clkevt' has incomplete type
     struct clock_event_device clkevt;
                               ^~~~~~
   In file included from include/linux/clk.h:16:0,
                    from drivers//clocksource/timer-sun5i.c:13:
   drivers//clocksource/timer-sun5i.c: In function 'sun5i_clkevt_shutdown':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:108:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:108:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c: In function 'sun5i_clkevt_set_oneshot':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:116:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:116:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c: In function 'sun5i_clkevt_set_periodic':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:125:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:125:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c: In function 'sun5i_clkevt_next_event':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:136:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'ce')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:64:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clkevt, clkevt)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:136:34: note: in expansion of macro 'to_sun5i_timer_clkevt'
     struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c: In function 'sun5i_clksrc_read':
>> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:56:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clksrc, clksrc)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:157:34: note: in expansion of macro 'to_sun5i_timer_clksrc'
     struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
                                     ^~~~~~~~~~~~~~~~~~~~~
   include/linux/kernel.h:852:48: note: (near initialization for 'cs')
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                   ^
   drivers//clocksource/timer-sun5i.c:56:2: note: in expansion of macro 'container_of'
     container_of(x, struct sun5i_timer_clksrc, clksrc)
     ^~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:157:34: note: in expansion of macro 'to_sun5i_timer_clksrc'
     struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
                                     ^~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c: In function 'sun5i_rate_cb_clksrc':
   drivers//clocksource/timer-sun5i.c:171:3: error: implicit declaration of function 'clocksource_unregister' [-Werror=implicit-function-declaration]
      clocksource_unregister(&cs->clksrc);
      ^~~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:175:3: error: implicit declaration of function 'clocksource_register_hz' [-Werror=implicit-function-declaration]
      clocksource_register_hz(&cs->clksrc, ndata->new_rate);
      ^~~~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c: In function 'sun5i_setup_clocksource':
   drivers//clocksource/timer-sun5i.c:223:20: error: implicit declaration of function 'CLOCKSOURCE_MASK' [-Werror=implicit-function-declaration]
     cs->clksrc.mask = CLOCKSOURCE_MASK(32);
                       ^~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:224:21: error: 'CLOCK_SOURCE_IS_CONTINUOUS' undeclared (first use in this function)
     cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:224:21: note: each undeclared identifier is reported only once for each function it appears in
   drivers//clocksource/timer-sun5i.c: In function 'sun5i_rate_cb_clkevt':
   drivers//clocksource/timer-sun5i.c:251:3: error: implicit declaration of function 'clockevents_update_freq' [-Werror=implicit-function-declaration]
      clockevents_update_freq(&ce->clkevt, ndata->new_rate);
      ^~~~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c: In function 'sun5i_setup_clockevent':
   drivers//clocksource/timer-sun5i.c:291:24: error: 'CLOCK_EVT_FEAT_PERIODIC' undeclared (first use in this function)
     ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
                           ^~~~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:291:50: error: 'CLOCK_EVT_FEAT_ONESHOT' undeclared (first use in this function)
     ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
                                                     ^~~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:305:2: error: implicit declaration of function 'clockevents_config_and_register' [-Werror=implicit-function-declaration]
     clockevents_config_and_register(&ce->clkevt, rate,
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c: At top level:
   drivers//clocksource/timer-sun5i.c:361:35: error: expected ')' before string constant
    CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:363:35: error: expected ')' before string constant
    CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers//clocksource/timer-sun5i.c:326:19: warning: 'sun5i_timer_init' defined but not used [-Wunused-function]
    static int __init sun5i_timer_init(struct device_node *node)
                      ^~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
..

vim +/clksrc +52 drivers/clocksource/timer-sun5i.c

4a59058f Maxime Ripard   2015-03-31   46  
3071efa4 Maxime Ripard   2015-03-31   47  #define to_sun5i_timer(x) \
3071efa4 Maxime Ripard   2015-03-31   48  	container_of(x, struct sun5i_timer, clk_rate_cb)
3071efa4 Maxime Ripard   2015-03-31   49  
4a59058f Maxime Ripard   2015-03-31   50  struct sun5i_timer_clksrc {
4a59058f Maxime Ripard   2015-03-31   51  	struct sun5i_timer	timer;
4a59058f Maxime Ripard   2015-03-31  @52  	struct clocksource	clksrc;
4a59058f Maxime Ripard   2015-03-31   53  };
4a59058f Maxime Ripard   2015-03-31   54  
4a59058f Maxime Ripard   2015-03-31   55  #define to_sun5i_timer_clksrc(x) \
4a59058f Maxime Ripard   2015-03-31  @56  	container_of(x, struct sun5i_timer_clksrc, clksrc)
4a59058f Maxime Ripard   2015-03-31   57  
4a59058f Maxime Ripard   2015-03-31   58  struct sun5i_timer_clkevt {
4a59058f Maxime Ripard   2015-03-31   59  	struct sun5i_timer		timer;
4a59058f Maxime Ripard   2015-03-31  @60  	struct clock_event_device	clkevt;
4a59058f Maxime Ripard   2015-03-31   61  };
4a59058f Maxime Ripard   2015-03-31   62  
4a59058f Maxime Ripard   2015-03-31   63  #define to_sun5i_timer_clkevt(x) \
4a59058f Maxime Ripard   2015-03-31   64  	container_of(x, struct sun5i_timer_clkevt, clkevt)
67905540 Maxime Ripard   2013-11-07   65  
67905540 Maxime Ripard   2013-11-07   66  /*
67905540 Maxime Ripard   2013-11-07   67   * When we disable a timer, we need to wait at least for 2 cycles of
67905540 Maxime Ripard   2013-11-07   68   * the timer source clock. We will use for that the clocksource timer
67905540 Maxime Ripard   2013-11-07   69   * that is already setup and runs at the same frequency than the other
67905540 Maxime Ripard   2013-11-07   70   * timers, and we never will be disabled.
67905540 Maxime Ripard   2013-11-07   71   */
4a59058f Maxime Ripard   2015-03-31   72  static void sun5i_clkevt_sync(struct sun5i_timer_clkevt *ce)
67905540 Maxime Ripard   2013-11-07   73  {
4a59058f Maxime Ripard   2015-03-31   74  	u32 old = readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1));
67905540 Maxime Ripard   2013-11-07   75  
4a59058f Maxime Ripard   2015-03-31   76  	while ((old - readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS)
67905540 Maxime Ripard   2013-11-07   77  		cpu_relax();
67905540 Maxime Ripard   2013-11-07   78  }
67905540 Maxime Ripard   2013-11-07   79  
4a59058f Maxime Ripard   2015-03-31   80  static void sun5i_clkevt_time_stop(struct sun5i_timer_clkevt *ce, u8 timer)
67905540 Maxime Ripard   2013-11-07   81  {
4a59058f Maxime Ripard   2015-03-31   82  	u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
4a59058f Maxime Ripard   2015-03-31   83  	writel(val & ~TIMER_CTL_ENABLE, ce->timer.base + TIMER_CTL_REG(timer));
67905540 Maxime Ripard   2013-11-07   84  
4a59058f Maxime Ripard   2015-03-31   85  	sun5i_clkevt_sync(ce);
67905540 Maxime Ripard   2013-11-07   86  }
67905540 Maxime Ripard   2013-11-07   87  
4a59058f Maxime Ripard   2015-03-31   88  static void sun5i_clkevt_time_setup(struct sun5i_timer_clkevt *ce, u8 timer, u32 delay)
67905540 Maxime Ripard   2013-11-07   89  {
4a59058f Maxime Ripard   2015-03-31   90  	writel(delay, ce->timer.base + TIMER_INTVAL_LO_REG(timer));
67905540 Maxime Ripard   2013-11-07   91  }
67905540 Maxime Ripard   2013-11-07   92  
4a59058f Maxime Ripard   2015-03-31   93  static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, bool periodic)
67905540 Maxime Ripard   2013-11-07   94  {
4a59058f Maxime Ripard   2015-03-31   95  	u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
67905540 Maxime Ripard   2013-11-07   96  
67905540 Maxime Ripard   2013-11-07   97  	if (periodic)
67905540 Maxime Ripard   2013-11-07   98  		val &= ~TIMER_CTL_ONESHOT;
67905540 Maxime Ripard   2013-11-07   99  	else
67905540 Maxime Ripard   2013-11-07  100  		val |= TIMER_CTL_ONESHOT;
67905540 Maxime Ripard   2013-11-07  101  
67905540 Maxime Ripard   2013-11-07  102  	writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
4a59058f Maxime Ripard   2015-03-31  103  	       ce->timer.base + TIMER_CTL_REG(timer));
67905540 Maxime Ripard   2013-11-07  104  }
67905540 Maxime Ripard   2013-11-07  105  
7486f5ad Viresh Kumar    2015-06-18  106  static int sun5i_clkevt_shutdown(struct clock_event_device *clkevt)
67905540 Maxime Ripard   2013-11-07  107  {
4a59058f Maxime Ripard   2015-03-31  108  	struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
4a59058f Maxime Ripard   2015-03-31  109  
4a59058f Maxime Ripard   2015-03-31  110  	sun5i_clkevt_time_stop(ce, 0);
7486f5ad Viresh Kumar    2015-06-18  111  	return 0;
7486f5ad Viresh Kumar    2015-06-18  112  }
7486f5ad Viresh Kumar    2015-06-18  113  
7486f5ad Viresh Kumar    2015-06-18  114  static int sun5i_clkevt_set_oneshot(struct clock_event_device *clkevt)
7486f5ad Viresh Kumar    2015-06-18  115  {
7486f5ad Viresh Kumar    2015-06-18  116  	struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
7486f5ad Viresh Kumar    2015-06-18  117  
4a59058f Maxime Ripard   2015-03-31  118  	sun5i_clkevt_time_stop(ce, 0);
4a59058f Maxime Ripard   2015-03-31  119  	sun5i_clkevt_time_start(ce, 0, false);
7486f5ad Viresh Kumar    2015-06-18  120  	return 0;
67905540 Maxime Ripard   2013-11-07  121  }
7486f5ad Viresh Kumar    2015-06-18  122  
7486f5ad Viresh Kumar    2015-06-18  123  static int sun5i_clkevt_set_periodic(struct clock_event_device *clkevt)
7486f5ad Viresh Kumar    2015-06-18  124  {
7486f5ad Viresh Kumar    2015-06-18  125  	struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
7486f5ad Viresh Kumar    2015-06-18  126  
7486f5ad Viresh Kumar    2015-06-18  127  	sun5i_clkevt_time_stop(ce, 0);
7486f5ad Viresh Kumar    2015-06-18  128  	sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy);
7486f5ad Viresh Kumar    2015-06-18  129  	sun5i_clkevt_time_start(ce, 0, true);
7486f5ad Viresh Kumar    2015-06-18  130  	return 0;
67905540 Maxime Ripard   2013-11-07  131  }
67905540 Maxime Ripard   2013-11-07  132  
67905540 Maxime Ripard   2013-11-07  133  static int sun5i_clkevt_next_event(unsigned long evt,
4a59058f Maxime Ripard   2015-03-31  134  				   struct clock_event_device *clkevt)
67905540 Maxime Ripard   2013-11-07  135  {
4a59058f Maxime Ripard   2015-03-31  136  	struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
4a59058f Maxime Ripard   2015-03-31  137  
4a59058f Maxime Ripard   2015-03-31  138  	sun5i_clkevt_time_stop(ce, 0);
4a59058f Maxime Ripard   2015-03-31  139  	sun5i_clkevt_time_setup(ce, 0, evt - TIMER_SYNC_TICKS);
4a59058f Maxime Ripard   2015-03-31  140  	sun5i_clkevt_time_start(ce, 0, false);
67905540 Maxime Ripard   2013-11-07  141  
67905540 Maxime Ripard   2013-11-07  142  	return 0;
67905540 Maxime Ripard   2013-11-07  143  }
67905540 Maxime Ripard   2013-11-07  144  
67905540 Maxime Ripard   2013-11-07  145  static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
67905540 Maxime Ripard   2013-11-07  146  {
4a59058f Maxime Ripard   2015-03-31  147  	struct sun5i_timer_clkevt *ce = (struct sun5i_timer_clkevt *)dev_id;
67905540 Maxime Ripard   2013-11-07  148  
4a59058f Maxime Ripard   2015-03-31  149  	writel(0x1, ce->timer.base + TIMER_IRQ_ST_REG);
4a59058f Maxime Ripard   2015-03-31  150  	ce->clkevt.event_handler(&ce->clkevt);
67905540 Maxime Ripard   2013-11-07  151  
67905540 Maxime Ripard   2013-11-07  152  	return IRQ_HANDLED;
67905540 Maxime Ripard   2013-11-07  153  }
67905540 Maxime Ripard   2013-11-07  154  
a5a1d1c2 Thomas Gleixner 2016-12-21  155  static u64 sun5i_clksrc_read(struct clocksource *clksrc)
59387683 Chen-Yu Tsai    2016-10-18  156  {
59387683 Chen-Yu Tsai    2016-10-18 @157  	struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
59387683 Chen-Yu Tsai    2016-10-18  158  
59387683 Chen-Yu Tsai    2016-10-18  159  	return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1));
59387683 Chen-Yu Tsai    2016-10-18  160  }
59387683 Chen-Yu Tsai    2016-10-18  161  
3071efa4 Maxime Ripard   2015-03-31  162  static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
3071efa4 Maxime Ripard   2015-03-31  163  				unsigned long event, void *data)
3071efa4 Maxime Ripard   2015-03-31  164  {
3071efa4 Maxime Ripard   2015-03-31  165  	struct clk_notifier_data *ndata = data;
3071efa4 Maxime Ripard   2015-03-31  166  	struct sun5i_timer *timer = to_sun5i_timer(nb);
3071efa4 Maxime Ripard   2015-03-31  167  	struct sun5i_timer_clksrc *cs = container_of(timer, struct sun5i_timer_clksrc, timer);
3071efa4 Maxime Ripard   2015-03-31  168  
3071efa4 Maxime Ripard   2015-03-31  169  	switch (event) {
3071efa4 Maxime Ripard   2015-03-31  170  	case PRE_RATE_CHANGE:
3071efa4 Maxime Ripard   2015-03-31 @171  		clocksource_unregister(&cs->clksrc);
3071efa4 Maxime Ripard   2015-03-31  172  		break;
3071efa4 Maxime Ripard   2015-03-31  173  
3071efa4 Maxime Ripard   2015-03-31  174  	case POST_RATE_CHANGE:
3071efa4 Maxime Ripard   2015-03-31 @175  		clocksource_register_hz(&cs->clksrc, ndata->new_rate);
3071efa4 Maxime Ripard   2015-03-31  176  		break;
3071efa4 Maxime Ripard   2015-03-31  177  
3071efa4 Maxime Ripard   2015-03-31  178  	default:
3071efa4 Maxime Ripard   2015-03-31  179  		break;
3071efa4 Maxime Ripard   2015-03-31  180  	}
3071efa4 Maxime Ripard   2015-03-31  181  
3071efa4 Maxime Ripard   2015-03-31  182  	return NOTIFY_DONE;
3071efa4 Maxime Ripard   2015-03-31  183  }
3071efa4 Maxime Ripard   2015-03-31  184  
4a59058f Maxime Ripard   2015-03-31  185  static int __init sun5i_setup_clocksource(struct device_node *node,
4a59058f Maxime Ripard   2015-03-31  186  					  void __iomem *base,
4a59058f Maxime Ripard   2015-03-31  187  					  struct clk *clk, int irq)
4a59058f Maxime Ripard   2015-03-31  188  {
4a59058f Maxime Ripard   2015-03-31  189  	struct sun5i_timer_clksrc *cs;
4a59058f Maxime Ripard   2015-03-31  190  	unsigned long rate;
4a59058f Maxime Ripard   2015-03-31  191  	int ret;
4a59058f Maxime Ripard   2015-03-31  192  
4a59058f Maxime Ripard   2015-03-31  193  	cs = kzalloc(sizeof(*cs), GFP_KERNEL);
4a59058f Maxime Ripard   2015-03-31  194  	if (!cs)
4a59058f Maxime Ripard   2015-03-31  195  		return -ENOMEM;
4a59058f Maxime Ripard   2015-03-31  196  
4a59058f Maxime Ripard   2015-03-31  197  	ret = clk_prepare_enable(clk);
4a59058f Maxime Ripard   2015-03-31  198  	if (ret) {
4a59058f Maxime Ripard   2015-03-31  199  		pr_err("Couldn't enable parent clock\n");
4a59058f Maxime Ripard   2015-03-31  200  		goto err_free;
4a59058f Maxime Ripard   2015-03-31  201  	}
4a59058f Maxime Ripard   2015-03-31  202  
4a59058f Maxime Ripard   2015-03-31  203  	rate = clk_get_rate(clk);
4a59058f Maxime Ripard   2015-03-31  204  
4a59058f Maxime Ripard   2015-03-31  205  	cs->timer.base = base;
4a59058f Maxime Ripard   2015-03-31  206  	cs->timer.clk = clk;
3071efa4 Maxime Ripard   2015-03-31  207  	cs->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clksrc;
3071efa4 Maxime Ripard   2015-03-31  208  	cs->timer.clk_rate_cb.next = NULL;
3071efa4 Maxime Ripard   2015-03-31  209  
3071efa4 Maxime Ripard   2015-03-31  210  	ret = clk_notifier_register(clk, &cs->timer.clk_rate_cb);
3071efa4 Maxime Ripard   2015-03-31  211  	if (ret) {
3071efa4 Maxime Ripard   2015-03-31  212  		pr_err("Unable to register clock notifier.\n");
3071efa4 Maxime Ripard   2015-03-31  213  		goto err_disable_clk;
3071efa4 Maxime Ripard   2015-03-31  214  	}
4a59058f Maxime Ripard   2015-03-31  215  
4a59058f Maxime Ripard   2015-03-31  216  	writel(~0, base + TIMER_INTVAL_LO_REG(1));
4a59058f Maxime Ripard   2015-03-31  217  	writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
4a59058f Maxime Ripard   2015-03-31  218  	       base + TIMER_CTL_REG(1));
4a59058f Maxime Ripard   2015-03-31  219  
59387683 Chen-Yu Tsai    2016-10-18  220  	cs->clksrc.name = node->name;
59387683 Chen-Yu Tsai    2016-10-18  221  	cs->clksrc.rating = 340;
59387683 Chen-Yu Tsai    2016-10-18  222  	cs->clksrc.read = sun5i_clksrc_read;
59387683 Chen-Yu Tsai    2016-10-18 @223  	cs->clksrc.mask = CLOCKSOURCE_MASK(32);
59387683 Chen-Yu Tsai    2016-10-18 @224  	cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
59387683 Chen-Yu Tsai    2016-10-18  225  
59387683 Chen-Yu Tsai    2016-10-18  226  	ret = clocksource_register_hz(&cs->clksrc, rate);
4a59058f Maxime Ripard   2015-03-31  227  	if (ret) {
4a59058f Maxime Ripard   2015-03-31  228  		pr_err("Couldn't register clock source.\n");
3071efa4 Maxime Ripard   2015-03-31  229  		goto err_remove_notifier;
4a59058f Maxime Ripard   2015-03-31  230  	}
4a59058f Maxime Ripard   2015-03-31  231  
4a59058f Maxime Ripard   2015-03-31  232  	return 0;
4a59058f Maxime Ripard   2015-03-31  233  
3071efa4 Maxime Ripard   2015-03-31  234  err_remove_notifier:
3071efa4 Maxime Ripard   2015-03-31  235  	clk_notifier_unregister(clk, &cs->timer.clk_rate_cb);
4a59058f Maxime Ripard   2015-03-31  236  err_disable_clk:
4a59058f Maxime Ripard   2015-03-31  237  	clk_disable_unprepare(clk);
4a59058f Maxime Ripard   2015-03-31  238  err_free:
4a59058f Maxime Ripard   2015-03-31  239  	kfree(cs);
4a59058f Maxime Ripard   2015-03-31  240  	return ret;
4a59058f Maxime Ripard   2015-03-31  241  }
4a59058f Maxime Ripard   2015-03-31  242  
3071efa4 Maxime Ripard   2015-03-31  243  static int sun5i_rate_cb_clkevt(struct notifier_block *nb,
3071efa4 Maxime Ripard   2015-03-31  244  				unsigned long event, void *data)
3071efa4 Maxime Ripard   2015-03-31  245  {
3071efa4 Maxime Ripard   2015-03-31  246  	struct clk_notifier_data *ndata = data;
3071efa4 Maxime Ripard   2015-03-31  247  	struct sun5i_timer *timer = to_sun5i_timer(nb);
3071efa4 Maxime Ripard   2015-03-31  248  	struct sun5i_timer_clkevt *ce = container_of(timer, struct sun5i_timer_clkevt, timer);
3071efa4 Maxime Ripard   2015-03-31  249  
3071efa4 Maxime Ripard   2015-03-31  250  	if (event == POST_RATE_CHANGE) {
3071efa4 Maxime Ripard   2015-03-31 @251  		clockevents_update_freq(&ce->clkevt, ndata->new_rate);
3071efa4 Maxime Ripard   2015-03-31  252  		ce->timer.ticks_per_jiffy = DIV_ROUND_UP(ndata->new_rate, HZ);
3071efa4 Maxime Ripard   2015-03-31  253  	}
3071efa4 Maxime Ripard   2015-03-31  254  

:::::: The code at line 52 was first introduced by commit
:::::: 4a59058f0b09682200c04b1db236b4a3b92128d7 clocksource/drivers/sun5i: Refactor the current code

:::::: TO: Maxime Ripard <maxime.ripard@free-electrons.com>
:::::: CC: Ingo Molnar <mingo@kernel.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47628 bytes --]

^ permalink raw reply

* Re: [PATCH] Bluetooth: hci_ll: Fix NULL pointer deref on FW upload failure
From: Marcel Holtmann @ 2017-04-16 18:32 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Gustavo F. Padovan, Rob Herring, Linux Bluetooth, linux-kernel
In-Reply-To: <20170415215413.15648-1-sre@kernel.org>

Hi Sebastian,

> Avoid NULL pointer dereference occurring due to freeing
> skb containing an error pointer. It can easily be triggered
> by using the driver with broken uart (i.e. due to misconfigured
> pinmuxing).
> 
> Fixes: 371805522f87 ("bluetooth: hci_uart: add LL protocol serdev driver support")
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
> ---
> drivers/bluetooth/hci_ll.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH] ARM: dts: omap4-droid4: add bluetooth
From: Sebastian Reichel @ 2017-04-16 15:26 UTC (permalink / raw)
  To: Michael Scott
  Cc: linux-bluetooth, linux-omap, Rob Herring, linux-kernel,
	Tony Lindgren
In-Reply-To: <CAEz3QY0duPa91TT3e86xA=tDGppiq0UXmDzuUm2i6cXbBi9CgQ@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 638 bytes --]

Hi Michael,

On Sat, Apr 15, 2017 at 07:00:29PM -0700, Michael Scott wrote:
> On Apr 15, 2017 3:18 PM, "Sebastian Reichel" <sre@kernel.org> wrote:
>> Droid 4 has wl1835 connected to the OMAP's UART4 port, which is
> 
> Technically, I believe the Droid 4 has WL1283 WLAN chip.
>
> - Mike

iFixit [0] has a nice photo in step 15, which clearly shows,
that its a WL1285C, with 1835 looking similar I didn't notice
Rob's binding does not cover wl128x. I will resend with proper
compatible value (+ patches for the driver and binding).

[0] https://www.ifixit.com/Teardown/Motorola+Droid+4+Teardown/7759#s31961

-- Sebastian

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH v3 1/4] dt-bindings: net: Add TI WiLink shared transport binding
From: Adam Ford @ 2017-04-16 14:09 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Rutland, Johan Hedberg, Wei Xu, Eyal Reizer, devicetree,
	linux-bluetooth, Gustavo Padovan, Marcel Holtmann, Satish Patel,
	linux-arm-kernel, netdev
In-Reply-To: <CAHCN7xLHZmS_3+JygQgRxi_tX0mXL22D1Nj9T8jkrMz3-8eQDg@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2207 bytes --]

On Apr 13, 2017 10:04 AM, "Rob Herring" <robh@kernel.org> wrote:

Add serial slave device binding for the TI WiLink series of Bluetooth/FM/GPS
devices.

Signed-off-by: Rob Herring <robh@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: netdev@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
v3:
- rebase on bluetooth-next

 .../devicetree/bindings/net/ti,wilink-st.txt       | 35
++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/ti,wilink-st.txt

diff --git a/Documentation/devicetree/bindings/net/ti,wilink-st.txt
b/Documentation/devicetree/bindings/net/ti,wilink-st.txt
new file mode 100644
index 000000000000..cbad73a84ac4
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/ti,wilink-st.txt
@@ -0,0 +1,35 @@
+TI WiLink 7/8 (wl12xx/wl18xx) Shared Transport BT/FM/GPS devices
+
+TI WiLink devices have a UART interface for providing Bluetooth, FM radio,
+and GPS over what's called "shared transport". The shared transport is
+standard BT HCI protocol with additional channels for the other functions.
+
+These devices also have a separate WiFi interface as described in
+wireless/ti,wlcore.txt.
+
+This bindings follows the UART slave device binding in
+../serial/slave-device.txt.
+
+Required properties:
+ - compatible: should be one of the following:
+    "ti,wl1271-st"
+    "ti,wl1273-st"
+    "ti,wl1831-st"
+    "ti,wl1835-st"
+    "ti,wl1837-st"
+


Would you expect the wl1283 chipset too?

I can help test this if you like after the holiday weekend. I have a board
with WL1283 and currently using pdata-quirks to support it.

Adam

+Optional properties:
+ - enable-gpios : GPIO signal controlling enabling of BT. Active high.
+ - vio-supply : Vio input supply (1.8V)
+ - vbat-supply : Vbat input supply (2.9-4.8V)
+
+Example:
+
+&serial0 {
+       compatible = "ns16550a";
+       ...
+       bluetooth {
+               compatible = "ti,wl1835-st";
+               enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+       };
+};
--
2.11.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

[-- Attachment #2: Type: text/html, Size: 3744 bytes --]

^ permalink raw reply related

* [PATCH BlueZ] test: Fix misuse of flags in re.sub() call
From: Jakub Wilk @ 2017-04-16 12:38 UTC (permalink / raw)
  To: linux-bluetooth

The 4th argument of re.sub() is maximum number of substitutions,
not flags.

The string doesn't contain any newlines, only hex digits, so the
re.DOTALL flag wouldn't have any effect. Let's remove it.
---
 test/sap_client.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/sap_client.py b/test/sap_client.py
index 413424c05..ba4f6f544 100644
--- a/test/sap_client.py
+++ b/test/sap_client.py
@@ -311,7 +311,7 @@ class SAPMessage:
 
     def getContent(self):
         s = "%s(id=0x%.2X) " % (self.name,  self.id)
-        if len( self.buf): s = s + "[%s]" % re.sub("(.{2})", "0x\\1 " , self.buf.tostring().encode("hex").upper(), re.DOTALL)
+        if len( self.buf): s = s + "[%s]" % re.sub("(.{2})", "0x\\1 " , self.buf.tostring().encode("hex").upper())
         s = s + "\n\t"
         for p in self.params:
             s = s + "\t" + p.getContent()
-- 
2.11.0


^ permalink raw reply related

* Re: [PATCH] ARM: dts: omap4-droid4: add bluetooth
From: Rob Herring @ 2017-04-16  1:56 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Tony Lindgren, open list:BLUETOOTH DRIVERS,
	linux-kernel@vger.kernel.org, linux-omap
In-Reply-To: <20170415221832.16175-1-sre@kernel.org>

On Sat, Apr 15, 2017 at 5:18 PM, Sebastian Reichel <sre@kernel.org> wrote:
> Droid 4 has wl1835 connected to the OMAP's UART4 port, which is
> used for Bluetooth and most likely can also be used for controlling
> the FM radio and GPS receivers.
>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
> ---
> Hi,
>
> Thanks to the work of Rob adding Bluetooth support for Droid 4 was
> straight forward :) I did a short test scanning for available devices
> using bluetoothctl. For that I had to rebind the bluetooth device,
> since it has been initialized before rootfs/firmware was available
> (builtin driver):
>
> echo serial0-0 > /sys/bus/serial/drivers/hci-ti/unbind
> echo serial0-0 > /sys/bus/serial/drivers/hci-ti/bind
>
> According to my research the FM module should be functional on
> Droid 4 and the wl1835's GPS is also used. Rob, do you have a
> plans for supporting the extra resources?

I don't think the h/w I have can do FM or GPS. At least there's no
headphone jack to serve as the FM antenna. For GPS, it seems support
for that is not publicly available. Maybe an antenna is not needed to
get the control interface working. It would be nice to integrate
though and then we can kill off the shared transport driver. Marcel
had mentioned that the Intel BT driver provides a regmap interface to
its FM driver. Not sure if that would work for TI.

Rob

^ permalink raw reply

* [PATCH] ARM: dts: omap4-droid4: add bluetooth
From: Sebastian Reichel @ 2017-04-15 22:18 UTC (permalink / raw)
  To: Sebastian Reichel, Tony Lindgren
  Cc: Rob Herring, linux-bluetooth, linux-kernel, linux-omap

Droid 4 has wl1835 connected to the OMAP's UART4 port, which is
used for Bluetooth and most likely can also be used for controlling
the FM radio and GPS receivers.

Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
Hi,

Thanks to the work of Rob adding Bluetooth support for Droid 4 was
straight forward :) I did a short test scanning for available devices
using bluetoothctl. For that I had to rebind the bluetooth device,
since it has been initialized before rootfs/firmware was available
(builtin driver):

echo serial0-0 > /sys/bus/serial/drivers/hci-ti/unbind
echo serial0-0 > /sys/bus/serial/drivers/hci-ti/bind

According to my research the FM module should be functional on
Droid 4 and the wl1835's GPS is also used. Rob, do you have a
plans for supporting the extra resources?

-- Sebastian
---
 arch/arm/boot/dts/omap4-droid4-xt894.dts | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
index e0fdfe6cc78c..2495faf79a43 100644
--- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
+++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
@@ -395,6 +395,15 @@
 		>;
 	};
 
+	uart4_pins: pinmux_uart4_pins {
+		pinctrl-single,pins = <
+		OMAP4_IOPAD(0x15c, PIN_INPUT | MUX_MODE0)		/* uart4_rx */
+		OMAP4_IOPAD(0x15e, PIN_OUTPUT | MUX_MODE0)		/* uart4_tx */
+		OMAP4_IOPAD(0x110, PIN_INPUT_PULLUP | MUX_MODE5)	/* uart4_cts */
+		OMAP4_IOPAD(0x112, PIN_OUTPUT_PULLUP | MUX_MODE5)	/* uart4_rts */
+		>;
+	};
+
 	mcbsp2_pins: pinmux_mcbsp2_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x0f6, PIN_INPUT | MUX_MODE0)	/* abe_mcbsp2_clkx */
@@ -429,6 +438,17 @@
 			       &omap4_pmx_core 0x17c>;
 };
 
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins>;
+
+	bluetooth {
+		compatible = "ti,wl1835-st";
+		enable-gpios = <&gpio6 14 GPIO_ACTIVE_HIGH>; /* gpio 174 */
+		max-speed = <3686400>;
+	};
+};
+
 &usbhsehci {
 	phys = <&hsusb1_phy>;
 };
-- 
2.11.0


^ permalink raw reply related

* [PATCH] Bluetooth: hci_ll: Fix NULL pointer deref on FW upload failure
From: Sebastian Reichel @ 2017-04-15 21:54 UTC (permalink / raw)
  To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan, Rob Herring
  Cc: linux-bluetooth, linux-kernel
In-Reply-To: <20170415194854.byado7bxupbdhivp@earth>

Avoid NULL pointer dereference occurring due to freeing
skb containing an error pointer. It can easily be triggered
by using the driver with broken uart (i.e. due to misconfigured
pinmuxing).

Fixes: 371805522f87 ("bluetooth: hci_uart: add LL protocol serdev driver support")
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
 drivers/bluetooth/hci_ll.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
index 485e8eb04542..adc444f309a3 100644
--- a/drivers/bluetooth/hci_ll.c
+++ b/drivers/bluetooth/hci_ll.c
@@ -537,8 +537,7 @@ static int read_local_version(struct hci_dev *hdev)
 	if (IS_ERR(skb)) {
 		bt_dev_err(hdev, "Reading TI version information failed (%ld)",
 			   PTR_ERR(skb));
-		err = PTR_ERR(skb);
-		goto out;
+		return PTR_ERR(skb);
 	}
 	if (skb->len != sizeof(*ver)) {
 		err = -EILSEQ;
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH v3 3/4] bluetooth: hci_uart: add LL protocol serdev driver support
From: Sebastian Reichel @ 2017-04-15 19:48 UTC (permalink / raw)
  To: Rob Herring
  Cc: Marcel Holtmann, linux-bluetooth, linux-arm-kernel,
	Gustavo Padovan, Johan Hedberg, Mark Rutland, Wei Xu, Eyal Reizer,
	Satish Patel, netdev, devicetree
In-Reply-To: <20170413150353.7389-4-robh@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 1098 bytes --]

Hi,

On Thu, Apr 13, 2017 at 10:03:52AM -0500, Rob Herring wrote:
> +static int read_local_version(struct hci_dev *hdev)
> +{
> +	int err = 0;
> +	unsigned short version = 0;
> +	struct sk_buff *skb;
> +	struct hci_rp_read_local_version *ver;
> +
> +	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT);
> +	if (IS_ERR(skb)) {
> +		bt_dev_err(hdev, "Reading TI version information failed (%ld)",
> +			   PTR_ERR(skb));
> +		err = PTR_ERR(skb);
> +		goto out;

If __hci_cmd_sync() fails the code tries to kfree_skb() an error pointer
resulting in NULL pointer dereference warning + strack trace. This
can just return err instead.

> +	}
> +	if (skb->len != sizeof(*ver)) {
> +		err = -EILSEQ;
> +		goto out;
> +	}
> +
> +	ver = (struct hci_rp_read_local_version *)skb->data;
> +	if (le16_to_cpu(ver->manufacturer) != 13) {
> +		err = -ENODEV;
> +		goto out;
> +	}
> +
> +	version = le16_to_cpu(ver->lmp_subver);
> +
> +out:
> +	if (err) bt_dev_err(hdev, "Failed to read TI version info: %d", err);
> +	kfree_skb(skb);
> +	return err ? err : version;
> +}

-- Sebastian

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH v3 1/4] dt-bindings: net: Add TI WiLink shared transport binding
From: Sebastian Reichel @ 2017-04-15 19:38 UTC (permalink / raw)
  To: Rob Herring
  Cc: Marcel Holtmann, linux-bluetooth, linux-arm-kernel,
	Gustavo Padovan, Johan Hedberg, Mark Rutland, Wei Xu, Eyal Reizer,
	Satish Patel, netdev, devicetree
In-Reply-To: <20170413150353.7389-2-robh@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 2021 bytes --]

Hi,

On Thu, Apr 13, 2017 at 10:03:50AM -0500, Rob Herring wrote:
> Add serial slave device binding for the TI WiLink series of Bluetooth/FM/GPS
> devices.
> 
> Signed-off-by: Rob Herring <robh@kernel.org>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: netdev@vger.kernel.org
> Cc: devicetree@vger.kernel.org
> ---
> v3:
> - rebase on bluetooth-next
> 
>  .../devicetree/bindings/net/ti,wilink-st.txt       | 35 ++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/ti,wilink-st.txt
> 
> diff --git a/Documentation/devicetree/bindings/net/ti,wilink-st.txt b/Documentation/devicetree/bindings/net/ti,wilink-st.txt
> new file mode 100644
> index 000000000000..cbad73a84ac4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/ti,wilink-st.txt
> @@ -0,0 +1,35 @@
> +TI WiLink 7/8 (wl12xx/wl18xx) Shared Transport BT/FM/GPS devices
> +
> +TI WiLink devices have a UART interface for providing Bluetooth, FM radio,
> +and GPS over what's called "shared transport". The shared transport is
> +standard BT HCI protocol with additional channels for the other functions.
> +
> +These devices also have a separate WiFi interface as described in
> +wireless/ti,wlcore.txt.
> +
> +This bindings follows the UART slave device binding in
> +../serial/slave-device.txt.
> +
> +Required properties:
> + - compatible: should be one of the following:
> +    "ti,wl1271-st"
> +    "ti,wl1273-st"
> +    "ti,wl1831-st"
> +    "ti,wl1835-st"
> +    "ti,wl1837-st"
> +
> +Optional properties:
> + - enable-gpios : GPIO signal controlling enabling of BT. Active high.
> + - vio-supply : Vio input supply (1.8V)
> + - vbat-supply : Vbat input supply (2.9-4.8V)
> +
> +Example:
> +
> +&serial0 {
> +	compatible = "ns16550a";
> +	...
> +	bluetooth {
> +		compatible = "ti,wl1835-st";
> +		enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
> +	};
> +};

Reviewed-by: Sebastian Reichel <sre@kernel.org>

-- Sebastian

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox