2015-04-05 02:13:02 +03:00
/*
*
* Bluetooth HCI UART driver for Intel devices
*
* Copyright ( C ) 2015 Intel Corporation
*
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/skbuff.h>
2015-07-01 13:20:26 +03:00
# include <linux/firmware.h>
2015-08-27 08:21:51 +03:00
# include <linux/module.h>
2015-07-01 13:20:26 +03:00
# include <linux/wait.h>
2015-08-27 08:21:51 +03:00
# include <linux/tty.h>
# include <linux/platform_device.h>
# include <linux/gpio/consumer.h>
# include <linux/acpi.h>
2015-08-29 14:38:18 +03:00
# include <linux/interrupt.h>
2015-09-02 13:04:13 +03:00
# include <linux/pm_runtime.h>
2015-04-05 02:13:02 +03:00
# include <net/bluetooth/bluetooth.h>
# include <net/bluetooth/hci_core.h>
# include "hci_uart.h"
2015-07-01 13:20:26 +03:00
# include "btintel.h"
# define STATE_BOOTLOADER 0
# define STATE_DOWNLOADING 1
# define STATE_FIRMWARE_LOADED 2
# define STATE_FIRMWARE_FAILED 3
# define STATE_BOOTING 4
2015-08-29 14:38:19 +03:00
# define STATE_LPM_ENABLED 5
# define STATE_TX_ACTIVE 6
2015-09-02 13:04:11 +03:00
# define STATE_SUSPENDED 7
# define STATE_LPM_TRANSACTION 8
2015-08-29 14:38:19 +03:00
2015-09-02 13:04:11 +03:00
# define HCI_LPM_WAKE_PKT 0xf0
2015-08-29 14:38:19 +03:00
# define HCI_LPM_PKT 0xf1
# define HCI_LPM_MAX_SIZE 10
# define HCI_LPM_HDR_SIZE HCI_EVENT_HDR_SIZE
# define LPM_OP_TX_NOTIFY 0x00
2015-09-02 13:04:11 +03:00
# define LPM_OP_SUSPEND_ACK 0x02
# define LPM_OP_RESUME_ACK 0x03
2015-08-29 14:38:19 +03:00
2015-09-02 13:04:13 +03:00
# define LPM_SUSPEND_DELAY_MS 1000
2015-08-29 14:38:19 +03:00
struct hci_lpm_pkt {
__u8 opcode ;
__u8 dlen ;
__u8 data [ 0 ] ;
} __packed ;
2015-07-01 13:20:26 +03:00
2015-08-27 08:21:51 +03:00
struct intel_device {
struct list_head list ;
struct platform_device * pdev ;
struct gpio_desc * reset ;
2015-09-02 13:04:12 +03:00
struct hci_uart * hu ;
struct mutex hu_lock ;
2015-08-29 14:38:18 +03:00
int irq ;
2015-08-27 08:21:51 +03:00
} ;
static LIST_HEAD ( intel_device_list ) ;
2015-08-31 19:34:31 +03:00
static DEFINE_MUTEX ( intel_device_list_lock ) ;
2015-08-27 08:21:51 +03:00
2015-07-01 13:20:26 +03:00
struct intel_data {
struct sk_buff * rx_skb ;
struct sk_buff_head txq ;
2015-09-02 13:04:13 +03:00
struct work_struct busy_work ;
struct hci_uart * hu ;
2015-07-01 13:20:26 +03:00
unsigned long flags ;
} ;
2015-08-25 18:55:44 +03:00
static u8 intel_convert_speed ( unsigned int speed )
{
switch ( speed ) {
case 9600 :
return 0x00 ;
case 19200 :
return 0x01 ;
case 38400 :
return 0x02 ;
case 57600 :
return 0x03 ;
case 115200 :
return 0x04 ;
case 230400 :
return 0x05 ;
case 460800 :
return 0x06 ;
case 921600 :
return 0x07 ;
case 1843200 :
return 0x08 ;
case 3250000 :
return 0x09 ;
case 2000000 :
return 0x0a ;
case 3000000 :
return 0x0b ;
default :
return 0xff ;
}
}
2015-08-27 08:21:51 +03:00
static int intel_wait_booting ( struct hci_uart * hu )
{
struct intel_data * intel = hu - > priv ;
int err ;
err = wait_on_bit_timeout ( & intel - > flags , STATE_BOOTING ,
TASK_INTERRUPTIBLE ,
msecs_to_jiffies ( 1000 ) ) ;
2016-08-12 02:02:44 +03:00
if ( err = = - EINTR ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hu - > hdev , " Device boot interrupted " ) ;
2015-08-27 08:21:51 +03:00
return - EINTR ;
}
if ( err ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hu - > hdev , " Device boot timeout " ) ;
2015-08-27 08:21:51 +03:00
return - ETIMEDOUT ;
}
return err ;
}
2015-09-04 18:39:25 +03:00
# ifdef CONFIG_PM
2015-09-02 13:04:11 +03:00
static int intel_wait_lpm_transaction ( struct hci_uart * hu )
{
struct intel_data * intel = hu - > priv ;
int err ;
err = wait_on_bit_timeout ( & intel - > flags , STATE_LPM_TRANSACTION ,
TASK_INTERRUPTIBLE ,
msecs_to_jiffies ( 1000 ) ) ;
2016-08-12 02:02:44 +03:00
if ( err = = - EINTR ) {
2015-09-02 13:04:11 +03:00
bt_dev_err ( hu - > hdev , " LPM transaction interrupted " ) ;
return - EINTR ;
}
if ( err ) {
bt_dev_err ( hu - > hdev , " LPM transaction timeout " ) ;
return - ETIMEDOUT ;
}
return err ;
}
static int intel_lpm_suspend ( struct hci_uart * hu )
{
static const u8 suspend [ ] = { 0x01 , 0x01 , 0x01 } ;
struct intel_data * intel = hu - > priv ;
struct sk_buff * skb ;
if ( ! test_bit ( STATE_LPM_ENABLED , & intel - > flags ) | |
test_bit ( STATE_SUSPENDED , & intel - > flags ) )
return 0 ;
if ( test_bit ( STATE_TX_ACTIVE , & intel - > flags ) )
return - EAGAIN ;
bt_dev_dbg ( hu - > hdev , " Suspending " ) ;
skb = bt_skb_alloc ( sizeof ( suspend ) , GFP_KERNEL ) ;
if ( ! skb ) {
bt_dev_err ( hu - > hdev , " Failed to alloc memory for LPM packet " ) ;
return - ENOMEM ;
}
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
skb_put_data ( skb , suspend , sizeof ( suspend ) ) ;
2015-11-05 09:33:56 +03:00
hci_skb_pkt_type ( skb ) = HCI_LPM_PKT ;
2015-09-02 13:04:11 +03:00
set_bit ( STATE_LPM_TRANSACTION , & intel - > flags ) ;
2015-09-09 20:08:02 +03:00
/* LPM flow is a priority, enqueue packet at list head */
skb_queue_head ( & intel - > txq , skb ) ;
2015-09-02 13:04:11 +03:00
hci_uart_tx_wakeup ( hu ) ;
intel_wait_lpm_transaction ( hu ) ;
/* Even in case of failure, continue and test the suspended flag */
clear_bit ( STATE_LPM_TRANSACTION , & intel - > flags ) ;
if ( ! test_bit ( STATE_SUSPENDED , & intel - > flags ) ) {
bt_dev_err ( hu - > hdev , " Device suspend error " ) ;
return - EINVAL ;
}
bt_dev_dbg ( hu - > hdev , " Suspended " ) ;
hci_uart_set_flow_control ( hu , true ) ;
return 0 ;
}
static int intel_lpm_resume ( struct hci_uart * hu )
{
struct intel_data * intel = hu - > priv ;
struct sk_buff * skb ;
if ( ! test_bit ( STATE_LPM_ENABLED , & intel - > flags ) | |
! test_bit ( STATE_SUSPENDED , & intel - > flags ) )
return 0 ;
bt_dev_dbg ( hu - > hdev , " Resuming " ) ;
hci_uart_set_flow_control ( hu , false ) ;
skb = bt_skb_alloc ( 0 , GFP_KERNEL ) ;
if ( ! skb ) {
bt_dev_err ( hu - > hdev , " Failed to alloc memory for LPM packet " ) ;
return - ENOMEM ;
}
2015-11-05 09:33:56 +03:00
hci_skb_pkt_type ( skb ) = HCI_LPM_WAKE_PKT ;
2015-09-02 13:04:11 +03:00
set_bit ( STATE_LPM_TRANSACTION , & intel - > flags ) ;
2015-09-09 20:08:02 +03:00
/* LPM flow is a priority, enqueue packet at list head */
skb_queue_head ( & intel - > txq , skb ) ;
2015-09-02 13:04:11 +03:00
hci_uart_tx_wakeup ( hu ) ;
intel_wait_lpm_transaction ( hu ) ;
/* Even in case of failure, continue and test the suspended flag */
clear_bit ( STATE_LPM_TRANSACTION , & intel - > flags ) ;
if ( test_bit ( STATE_SUSPENDED , & intel - > flags ) ) {
bt_dev_err ( hu - > hdev , " Device resume error " ) ;
return - EINVAL ;
}
bt_dev_dbg ( hu - > hdev , " Resumed " ) ;
return 0 ;
}
2015-09-04 18:39:25 +03:00
# endif /* CONFIG_PM */
2015-09-02 13:04:11 +03:00
static int intel_lpm_host_wake ( struct hci_uart * hu )
{
static const u8 lpm_resume_ack [ ] = { LPM_OP_RESUME_ACK , 0x00 } ;
struct intel_data * intel = hu - > priv ;
struct sk_buff * skb ;
hci_uart_set_flow_control ( hu , false ) ;
clear_bit ( STATE_SUSPENDED , & intel - > flags ) ;
skb = bt_skb_alloc ( sizeof ( lpm_resume_ack ) , GFP_KERNEL ) ;
if ( ! skb ) {
bt_dev_err ( hu - > hdev , " Failed to alloc memory for LPM packet " ) ;
return - ENOMEM ;
}
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
skb_put_data ( skb , lpm_resume_ack , sizeof ( lpm_resume_ack ) ) ;
2015-11-05 09:33:56 +03:00
hci_skb_pkt_type ( skb ) = HCI_LPM_PKT ;
2015-09-02 13:04:11 +03:00
2015-09-09 20:08:02 +03:00
/* LPM flow is a priority, enqueue packet at list head */
skb_queue_head ( & intel - > txq , skb ) ;
2015-09-02 13:04:11 +03:00
hci_uart_tx_wakeup ( hu ) ;
bt_dev_dbg ( hu - > hdev , " Resumed by controller " ) ;
return 0 ;
}
2015-08-29 14:38:18 +03:00
static irqreturn_t intel_irq ( int irq , void * dev_id )
{
struct intel_device * idev = dev_id ;
dev_info ( & idev - > pdev - > dev , " hci_intel irq \n " ) ;
2015-09-02 13:04:12 +03:00
mutex_lock ( & idev - > hu_lock ) ;
if ( idev - > hu )
intel_lpm_host_wake ( idev - > hu ) ;
mutex_unlock ( & idev - > hu_lock ) ;
2015-09-02 13:04:13 +03:00
/* Host/Controller are now LPM resumed, trigger a new delayed suspend */
pm_runtime_get ( & idev - > pdev - > dev ) ;
pm_runtime_mark_last_busy ( & idev - > pdev - > dev ) ;
pm_runtime_put_autosuspend ( & idev - > pdev - > dev ) ;
2015-08-29 14:38:18 +03:00
return IRQ_HANDLED ;
}
2015-08-27 08:21:51 +03:00
static int intel_set_power ( struct hci_uart * hu , bool powered )
{
struct list_head * p ;
int err = - ENODEV ;
2017-03-29 19:15:28 +03:00
if ( ! hu - > tty - > dev )
return err ;
2015-08-31 19:34:31 +03:00
mutex_lock ( & intel_device_list_lock ) ;
2015-08-27 08:21:51 +03:00
list_for_each ( p , & intel_device_list ) {
struct intel_device * idev = list_entry ( p , struct intel_device ,
list ) ;
/* tty device and pdev device should share the same parent
* which is the UART port .
*/
if ( hu - > tty - > dev - > parent ! = idev - > pdev - > dev . parent )
continue ;
if ( ! idev - > reset ) {
err = - ENOTSUPP ;
break ;
}
BT_INFO ( " hu %p, Switching compatible pm device (%s) to %u " ,
hu , dev_name ( & idev - > pdev - > dev ) , powered ) ;
gpiod_set_value ( idev - > reset , powered ) ;
2015-08-29 14:38:18 +03:00
2015-09-02 13:04:12 +03:00
/* Provide to idev a hu reference which is used to run LPM
* transactions ( lpm suspend / resume ) from PM callbacks .
* hu needs to be protected against concurrent removing during
* these PM ops .
*/
mutex_lock ( & idev - > hu_lock ) ;
idev - > hu = powered ? hu : NULL ;
mutex_unlock ( & idev - > hu_lock ) ;
2015-08-29 14:38:18 +03:00
if ( idev - > irq < 0 )
break ;
if ( powered & & device_can_wakeup ( & idev - > pdev - > dev ) ) {
err = devm_request_threaded_irq ( & idev - > pdev - > dev ,
idev - > irq , NULL ,
intel_irq ,
IRQF_ONESHOT ,
" bt-host-wake " , idev ) ;
if ( err ) {
BT_ERR ( " hu %p, unable to allocate irq-%d " ,
hu , idev - > irq ) ;
break ;
}
device_wakeup_enable ( & idev - > pdev - > dev ) ;
2015-09-02 13:04:13 +03:00
pm_runtime_set_active ( & idev - > pdev - > dev ) ;
pm_runtime_use_autosuspend ( & idev - > pdev - > dev ) ;
pm_runtime_set_autosuspend_delay ( & idev - > pdev - > dev ,
LPM_SUSPEND_DELAY_MS ) ;
pm_runtime_enable ( & idev - > pdev - > dev ) ;
2015-08-29 14:38:18 +03:00
} else if ( ! powered & & device_may_wakeup ( & idev - > pdev - > dev ) ) {
devm_free_irq ( & idev - > pdev - > dev , idev - > irq , idev ) ;
device_wakeup_disable ( & idev - > pdev - > dev ) ;
2015-09-02 13:04:13 +03:00
pm_runtime_disable ( & idev - > pdev - > dev ) ;
2015-08-29 14:38:18 +03:00
}
2015-08-27 08:21:51 +03:00
}
2015-08-31 19:34:31 +03:00
mutex_unlock ( & intel_device_list_lock ) ;
2015-08-27 08:21:51 +03:00
return err ;
}
2015-09-02 13:04:13 +03:00
static void intel_busy_work ( struct work_struct * work )
{
struct list_head * p ;
struct intel_data * intel = container_of ( work , struct intel_data ,
busy_work ) ;
2017-03-29 19:15:28 +03:00
if ( ! intel - > hu - > tty - > dev )
return ;
2015-09-02 13:04:13 +03:00
/* Link is busy, delay the suspend */
mutex_lock ( & intel_device_list_lock ) ;
list_for_each ( p , & intel_device_list ) {
struct intel_device * idev = list_entry ( p , struct intel_device ,
list ) ;
if ( intel - > hu - > tty - > dev - > parent = = idev - > pdev - > dev . parent ) {
pm_runtime_get ( & idev - > pdev - > dev ) ;
pm_runtime_mark_last_busy ( & idev - > pdev - > dev ) ;
pm_runtime_put_autosuspend ( & idev - > pdev - > dev ) ;
break ;
}
}
mutex_unlock ( & intel_device_list_lock ) ;
}
2015-07-01 13:20:26 +03:00
static int intel_open ( struct hci_uart * hu )
{
struct intel_data * intel ;
BT_DBG ( " hu %p " , hu ) ;
intel = kzalloc ( sizeof ( * intel ) , GFP_KERNEL ) ;
if ( ! intel )
return - ENOMEM ;
skb_queue_head_init ( & intel - > txq ) ;
2015-09-02 13:04:13 +03:00
INIT_WORK ( & intel - > busy_work , intel_busy_work ) ;
intel - > hu = hu ;
2015-07-01 13:20:26 +03:00
hu - > priv = intel ;
2015-08-27 08:21:51 +03:00
if ( ! intel_set_power ( hu , true ) )
set_bit ( STATE_BOOTING , & intel - > flags ) ;
2015-07-01 13:20:26 +03:00
return 0 ;
}
static int intel_close ( struct hci_uart * hu )
{
struct intel_data * intel = hu - > priv ;
BT_DBG ( " hu %p " , hu ) ;
2015-09-02 13:04:13 +03:00
cancel_work_sync ( & intel - > busy_work ) ;
2015-08-27 08:21:51 +03:00
intel_set_power ( hu , false ) ;
2015-07-01 13:20:26 +03:00
skb_queue_purge ( & intel - > txq ) ;
kfree_skb ( intel - > rx_skb ) ;
kfree ( intel ) ;
hu - > priv = NULL ;
return 0 ;
}
static int intel_flush ( struct hci_uart * hu )
{
struct intel_data * intel = hu - > priv ;
BT_DBG ( " hu %p " , hu ) ;
skb_queue_purge ( & intel - > txq ) ;
return 0 ;
}
static int inject_cmd_complete ( struct hci_dev * hdev , __u16 opcode )
{
struct sk_buff * skb ;
struct hci_event_hdr * hdr ;
struct hci_ev_cmd_complete * evt ;
skb = bt_skb_alloc ( sizeof ( * hdr ) + sizeof ( * evt ) + 1 , GFP_ATOMIC ) ;
if ( ! skb )
return - ENOMEM ;
networking: make skb_put & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions (skb_put, __skb_put and pskb_put) return void *
and remove all the casts across the tree, adding a (u8 *) cast only
where the unsigned char pointer was used directly, all done with the
following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_put, __skb_put };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_put, __skb_put };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
which actually doesn't cover pskb_put since there are only three
users overall.
A handful of stragglers were converted manually, notably a macro in
drivers/isdn/i4l/isdn_bsdcomp.c and, oddly enough, one of the many
instances in net/bluetooth/hci_sock.c. In the former file, I also
had to fix one whitespace problem spatch introduced.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:21 +03:00
hdr = skb_put ( skb , sizeof ( * hdr ) ) ;
2015-07-01 13:20:26 +03:00
hdr - > evt = HCI_EV_CMD_COMPLETE ;
hdr - > plen = sizeof ( * evt ) + 1 ;
networking: make skb_put & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions (skb_put, __skb_put and pskb_put) return void *
and remove all the casts across the tree, adding a (u8 *) cast only
where the unsigned char pointer was used directly, all done with the
following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_put, __skb_put };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_put, __skb_put };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
which actually doesn't cover pskb_put since there are only three
users overall.
A handful of stragglers were converted manually, notably a macro in
drivers/isdn/i4l/isdn_bsdcomp.c and, oddly enough, one of the many
instances in net/bluetooth/hci_sock.c. In the former file, I also
had to fix one whitespace problem spatch introduced.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:21 +03:00
evt = skb_put ( skb , sizeof ( * evt ) ) ;
2015-07-01 13:20:26 +03:00
evt - > ncmd = 0x01 ;
evt - > opcode = cpu_to_le16 ( opcode ) ;
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
skb_put_u8 ( skb , 0x00 ) ;
2015-07-01 13:20:26 +03:00
2015-11-05 09:33:56 +03:00
hci_skb_pkt_type ( skb ) = HCI_EVENT_PKT ;
2015-07-01 13:20:26 +03:00
return hci_recv_frame ( hdev , skb ) ;
}
2015-08-25 18:55:44 +03:00
static int intel_set_baudrate ( struct hci_uart * hu , unsigned int speed )
{
struct intel_data * intel = hu - > priv ;
struct hci_dev * hdev = hu - > hdev ;
u8 speed_cmd [ ] = { 0x06 , 0xfc , 0x01 , 0x00 } ;
struct sk_buff * skb ;
2015-08-27 08:21:51 +03:00
int err ;
/* This can be the first command sent to the chip, check
* that the controller is ready .
*/
err = intel_wait_booting ( hu ) ;
clear_bit ( STATE_BOOTING , & intel - > flags ) ;
/* In case of timeout, try to continue anyway */
2016-02-10 20:22:54 +03:00
if ( err & & err ! = - ETIMEDOUT )
2015-08-27 08:21:51 +03:00
return err ;
2015-08-25 18:55:44 +03:00
2015-08-31 19:34:30 +03:00
bt_dev_info ( hdev , " Change controller speed to %d " , speed ) ;
2015-08-25 18:55:44 +03:00
speed_cmd [ 3 ] = intel_convert_speed ( speed ) ;
if ( speed_cmd [ 3 ] = = 0xff ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Unsupported speed " ) ;
2015-08-25 18:55:44 +03:00
return - EINVAL ;
}
/* Device will not accept speed change if Intel version has not been
* previously requested .
*/
2015-11-27 21:55:59 +03:00
skb = __hci_cmd_sync ( hdev , 0xfc05 , 0 , NULL , HCI_CMD_TIMEOUT ) ;
2015-08-25 18:55:44 +03:00
if ( IS_ERR ( skb ) ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Reading Intel version information failed (%ld) " ,
PTR_ERR ( skb ) ) ;
2015-08-25 18:55:44 +03:00
return PTR_ERR ( skb ) ;
}
kfree_skb ( skb ) ;
skb = bt_skb_alloc ( sizeof ( speed_cmd ) , GFP_KERNEL ) ;
if ( ! skb ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Failed to alloc memory for baudrate packet " ) ;
2015-08-25 18:55:44 +03:00
return - ENOMEM ;
}
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
skb_put_data ( skb , speed_cmd , sizeof ( speed_cmd ) ) ;
2015-11-05 09:33:56 +03:00
hci_skb_pkt_type ( skb ) = HCI_COMMAND_PKT ;
2015-08-25 18:55:44 +03:00
hci_uart_set_flow_control ( hu , true ) ;
skb_queue_tail ( & intel - > txq , skb ) ;
hci_uart_tx_wakeup ( hu ) ;
/* wait 100ms to change baudrate on controller side */
msleep ( 100 ) ;
hci_uart_set_baudrate ( hu , speed ) ;
hci_uart_set_flow_control ( hu , false ) ;
return 0 ;
}
2015-07-01 13:20:26 +03:00
static int intel_setup ( struct hci_uart * hu )
{
struct intel_data * intel = hu - > priv ;
struct hci_dev * hdev = hu - > hdev ;
struct sk_buff * skb ;
2015-12-06 18:18:34 +03:00
struct intel_version ver ;
2018-01-24 20:19:20 +03:00
struct intel_boot_params params ;
2015-08-29 14:38:19 +03:00
struct list_head * p ;
2015-07-01 13:20:26 +03:00
const struct firmware * fw ;
char fwname [ 64 ] ;
2018-01-24 20:19:18 +03:00
u32 boot_param ;
2015-07-01 13:20:26 +03:00
ktime_t calltime , delta , rettime ;
unsigned long long duration ;
2015-08-25 18:55:44 +03:00
unsigned int init_speed , oper_speed ;
int speed_change = 0 ;
2015-07-01 13:20:26 +03:00
int err ;
2015-08-31 19:34:30 +03:00
bt_dev_dbg ( hdev , " start intel_setup " ) ;
2015-07-01 13:20:26 +03:00
2015-10-09 15:42:08 +03:00
hu - > hdev - > set_diag = btintel_set_diag ;
2015-07-05 15:37:40 +03:00
hu - > hdev - > set_bdaddr = btintel_set_bdaddr ;
2018-01-24 20:19:19 +03:00
/* Set the default boot parameter to 0x0 and it is updated to
* SKU specific boot parameter after reading Intel_Write_Boot_Params
* command while downloading the firmware .
*/
boot_param = 0x00000000 ;
2018-01-24 20:19:18 +03:00
2015-07-01 13:20:26 +03:00
calltime = ktime_get ( ) ;
2015-08-25 18:55:44 +03:00
if ( hu - > init_speed )
init_speed = hu - > init_speed ;
else
init_speed = hu - > proto - > init_speed ;
if ( hu - > oper_speed )
oper_speed = hu - > oper_speed ;
else
oper_speed = hu - > proto - > oper_speed ;
if ( oper_speed & & init_speed & & oper_speed ! = init_speed )
speed_change = 1 ;
2015-08-27 08:21:51 +03:00
/* Check that the controller is ready */
err = intel_wait_booting ( hu ) ;
clear_bit ( STATE_BOOTING , & intel - > flags ) ;
/* In case of timeout, try to continue anyway */
2016-02-10 20:22:54 +03:00
if ( err & & err ! = - ETIMEDOUT )
2015-08-27 08:21:51 +03:00
return err ;
2015-07-01 13:20:26 +03:00
set_bit ( STATE_BOOTLOADER , & intel - > flags ) ;
/* Read the Intel version information to determine if the device
* is in bootloader mode or if it already has operational firmware
* loaded .
*/
2015-12-06 18:18:34 +03:00
err = btintel_read_version ( hdev , & ver ) ;
if ( err )
2015-07-01 13:20:26 +03:00
return err ;
/* The hardware platform number has a fixed value of 0x37 and
* for now only accept this single value .
*/
2015-12-06 18:18:34 +03:00
if ( ver . hw_platform ! = 0x37 ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Unsupported Intel hardware platform (%u) " ,
2015-12-06 18:18:34 +03:00
ver . hw_platform ) ;
2015-07-01 13:20:26 +03:00
return - EINVAL ;
}
2017-03-07 02:38:26 +03:00
/* Check for supported iBT hardware variants of this firmware
* loading method .
*
* This check has been put in place to ensure correct forward
* compatibility options when newer hardware variants come along .
*/
switch ( ver . hw_variant ) {
case 0x0b : /* LnP */
case 0x0c : /* WsP */
2017-03-07 02:38:35 +03:00
case 0x12 : /* ThP */
2017-03-07 02:38:26 +03:00
break ;
default :
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Unsupported Intel hardware variant (%u) " ,
2015-12-06 18:18:34 +03:00
ver . hw_variant ) ;
2015-07-01 13:20:26 +03:00
return - EINVAL ;
}
2015-12-06 18:18:34 +03:00
btintel_version_info ( hdev , & ver ) ;
2015-07-01 13:20:26 +03:00
/* The firmware variant determines if the device is in bootloader
* mode or is running operational firmware . The value 0x06 identifies
* the bootloader and the value 0x23 identifies the operational
* firmware .
*
* When the operational firmware is already present , then only
* the check for valid Bluetooth device address is needed . This
* determines if the device will be added as configured or
* unconfigured controller .
*
* It is not possible to use the Secure Boot Parameters in this
* case since that command is only available in bootloader mode .
*/
2015-12-06 18:18:34 +03:00
if ( ver . fw_variant = = 0x23 ) {
2015-07-01 13:20:26 +03:00
clear_bit ( STATE_BOOTLOADER , & intel - > flags ) ;
btintel_check_bdaddr ( hdev ) ;
return 0 ;
}
/* If the device is not in bootloader mode, then the only possible
* choice is to return an error and abort the device initialization .
*/
2015-12-06 18:18:34 +03:00
if ( ver . fw_variant ! = 0x06 ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Unsupported Intel firmware variant (%u) " ,
2015-12-06 18:18:34 +03:00
ver . fw_variant ) ;
2015-07-01 13:20:26 +03:00
return - ENODEV ;
}
/* Read the secure boot parameters to identify the operating
* details of the bootloader .
*/
2018-01-24 20:19:20 +03:00
err = btintel_read_boot_params ( hdev , & params ) ;
if ( err )
2015-07-01 13:20:26 +03:00
return err ;
/* It is required that every single firmware fragment is acknowledged
* with a command complete event . If the boot parameters indicate
* that this bootloader does not send them , then abort the setup .
*/
2018-01-24 20:19:20 +03:00
if ( params . limited_cce ! = 0x00 ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Unsupported Intel firmware loading method (%u) " ,
2018-01-24 20:19:20 +03:00
params . limited_cce ) ;
2015-07-01 13:20:26 +03:00
return - EINVAL ;
}
/* If the OTP has no valid Bluetooth device address, then there will
* also be no valid address for the operational firmware .
*/
2018-01-24 20:19:20 +03:00
if ( ! bacmp ( & params . otp_bdaddr , BDADDR_ANY ) ) {
2015-08-31 19:34:30 +03:00
bt_dev_info ( hdev , " No device address configured " ) ;
2015-07-01 13:20:26 +03:00
set_bit ( HCI_QUIRK_INVALID_BDADDR , & hdev - > quirks ) ;
}
/* With this Intel bootloader only the hardware variant and device
2018-01-24 20:19:17 +03:00
* revision information are used to select the right firmware for SfP
* and WsP .
2015-07-01 13:20:26 +03:00
*
2017-03-07 02:38:32 +03:00
* The firmware filename is ibt - < hw_variant > - < dev_revid > . sfi .
*
* Currently the supported hardware variants are :
* 11 ( 0x0b ) for iBT 3.0 ( LnP / SfP )
2018-01-24 20:19:17 +03:00
* 12 ( 0x0c ) for iBT 3.5 ( WsP )
*
* For ThP / JfP and for future SKU ' s , the FW name varies based on HW
* variant , HW revision and FW revision , as these are dependent on CNVi
* and RF Combination .
*
* 18 ( 0x12 ) for iBT3 .5 ( ThP / JfP )
*
* The firmware file name for these will be
* ibt - < hw_variant > - < hw_revision > - < fw_revision > . sfi .
*
2015-07-01 13:20:26 +03:00
*/
2018-01-24 20:19:17 +03:00
switch ( ver . hw_variant ) {
case 0x0b : /* SfP */
case 0x0c : /* WsP */
snprintf ( fwname , sizeof ( fwname ) , " intel/ibt-%u-%u.sfi " ,
le16_to_cpu ( ver . hw_variant ) ,
2018-01-24 20:19:20 +03:00
le16_to_cpu ( params . dev_revid ) ) ;
2018-01-24 20:19:17 +03:00
break ;
case 0x12 : /* ThP */
snprintf ( fwname , sizeof ( fwname ) , " intel/ibt-%u-%u-%u.sfi " ,
le16_to_cpu ( ver . hw_variant ) ,
le16_to_cpu ( ver . hw_revision ) ,
le16_to_cpu ( ver . fw_revision ) ) ;
break ;
default :
bt_dev_err ( hdev , " Unsupported Intel hardware variant (%u) " ,
ver . hw_variant ) ;
return - EINVAL ;
}
2015-07-01 13:20:26 +03:00
err = request_firmware ( & fw , fwname , & hdev - > dev ) ;
if ( err < 0 ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Failed to load Intel firmware file (%d) " ,
err ) ;
2015-07-01 13:20:26 +03:00
return err ;
}
2015-08-31 19:34:30 +03:00
bt_dev_info ( hdev , " Found device firmware: %s " , fwname ) ;
2015-07-01 13:20:26 +03:00
2015-09-04 18:54:35 +03:00
/* Save the DDC file name for later */
2018-01-24 20:19:17 +03:00
switch ( ver . hw_variant ) {
case 0x0b : /* SfP */
case 0x0c : /* WsP */
snprintf ( fwname , sizeof ( fwname ) , " intel/ibt-%u-%u.ddc " ,
le16_to_cpu ( ver . hw_variant ) ,
2018-01-24 20:19:20 +03:00
le16_to_cpu ( params . dev_revid ) ) ;
2018-01-24 20:19:17 +03:00
break ;
case 0x12 : /* ThP */
snprintf ( fwname , sizeof ( fwname ) , " intel/ibt-%u-%u-%u.ddc " ,
le16_to_cpu ( ver . hw_variant ) ,
le16_to_cpu ( ver . hw_revision ) ,
le16_to_cpu ( ver . fw_revision ) ) ;
break ;
default :
bt_dev_err ( hdev , " Unsupported Intel hardware variant (%u) " ,
ver . hw_variant ) ;
return - EINVAL ;
}
2015-09-04 18:54:35 +03:00
2015-07-01 13:20:26 +03:00
if ( fw - > size < 644 ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Invalid size of firmware file (%zu) " ,
fw - > size ) ;
2015-07-01 13:20:26 +03:00
err = - EBADF ;
goto done ;
}
set_bit ( STATE_DOWNLOADING , & intel - > flags ) ;
2018-01-24 20:19:21 +03:00
/* Start firmware downloading and get boot parameter */
err = btintel_download_firmware ( hdev , fw , & boot_param ) ;
if ( err < 0 )
2015-07-01 13:20:26 +03:00
goto done ;
set_bit ( STATE_FIRMWARE_LOADED , & intel - > flags ) ;
2015-08-31 19:34:30 +03:00
bt_dev_info ( hdev , " Waiting for firmware download to complete " ) ;
2015-07-01 13:20:26 +03:00
/* Before switching the device into operational mode and with that
* booting the loaded firmware , wait for the bootloader notification
* that all fragments have been successfully received .
*
* When the event processing receives the notification , then the
* STATE_DOWNLOADING flag will be cleared .
*
* The firmware loading should not take longer than 5 seconds
* and thus just timeout if that happens and fail the setup
* of this device .
*/
err = wait_on_bit_timeout ( & intel - > flags , STATE_DOWNLOADING ,
TASK_INTERRUPTIBLE ,
msecs_to_jiffies ( 5000 ) ) ;
2016-08-12 02:02:44 +03:00
if ( err = = - EINTR ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Firmware loading interrupted " ) ;
2015-07-01 13:20:26 +03:00
err = - EINTR ;
goto done ;
}
if ( err ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Firmware loading timeout " ) ;
2015-07-01 13:20:26 +03:00
err = - ETIMEDOUT ;
goto done ;
}
if ( test_bit ( STATE_FIRMWARE_FAILED , & intel - > flags ) ) {
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Firmware loading failed " ) ;
2015-07-01 13:20:26 +03:00
err = - ENOEXEC ;
goto done ;
}
rettime = ktime_get ( ) ;
delta = ktime_sub ( rettime , calltime ) ;
duration = ( unsigned long long ) ktime_to_ns ( delta ) > > 10 ;
2015-08-31 19:34:30 +03:00
bt_dev_info ( hdev , " Firmware loaded in %llu usecs " , duration ) ;
2015-07-01 13:20:26 +03:00
done :
release_firmware ( fw ) ;
if ( err < 0 )
return err ;
2015-08-25 18:55:44 +03:00
/* We need to restore the default speed before Intel reset */
if ( speed_change ) {
err = intel_set_baudrate ( hu , init_speed ) ;
if ( err )
return err ;
}
2015-07-01 13:20:26 +03:00
calltime = ktime_get ( ) ;
set_bit ( STATE_BOOTING , & intel - > flags ) ;
2018-01-24 20:19:18 +03:00
err = btintel_send_intel_reset ( hdev , boot_param ) ;
if ( err )
return err ;
2015-07-01 13:20:26 +03:00
/* The bootloader will not indicate when the device is ready. This
* is done by the operational firmware sending bootup notification .
*
* Booting into operational firmware should not take longer than
* 1 second . However if that happens , then just fail the setup
* since something went wrong .
*/
2015-08-31 19:34:30 +03:00
bt_dev_info ( hdev , " Waiting for device to boot " ) ;
2015-07-01 13:20:26 +03:00
2015-08-27 08:21:51 +03:00
err = intel_wait_booting ( hu ) ;
if ( err )
return err ;
2015-07-01 13:20:26 +03:00
2015-08-27 08:21:51 +03:00
clear_bit ( STATE_BOOTING , & intel - > flags ) ;
2015-07-01 13:20:26 +03:00
rettime = ktime_get ( ) ;
delta = ktime_sub ( rettime , calltime ) ;
duration = ( unsigned long long ) ktime_to_ns ( delta ) > > 10 ;
2015-08-31 19:34:30 +03:00
bt_dev_info ( hdev , " Device booted in %llu usecs " , duration ) ;
2015-07-01 13:20:26 +03:00
2016-07-11 22:55:36 +03:00
/* Enable LPM if matching pdev with wakeup enabled, set TX active
* until further LPM TX notification .
*/
2015-08-31 19:34:31 +03:00
mutex_lock ( & intel_device_list_lock ) ;
2015-08-29 14:38:19 +03:00
list_for_each ( p , & intel_device_list ) {
struct intel_device * dev = list_entry ( p , struct intel_device ,
list ) ;
2017-03-29 19:15:28 +03:00
if ( ! hu - > tty - > dev )
break ;
2015-08-29 14:38:19 +03:00
if ( hu - > tty - > dev - > parent = = dev - > pdev - > dev . parent ) {
2016-07-11 22:55:36 +03:00
if ( device_may_wakeup ( & dev - > pdev - > dev ) ) {
set_bit ( STATE_LPM_ENABLED , & intel - > flags ) ;
set_bit ( STATE_TX_ACTIVE , & intel - > flags ) ;
}
2015-08-29 14:38:19 +03:00
break ;
}
}
2015-08-31 19:34:31 +03:00
mutex_unlock ( & intel_device_list_lock ) ;
2015-08-29 14:38:19 +03:00
2015-09-04 18:54:35 +03:00
/* Ignore errors, device can work without DDC parameters */
btintel_load_ddc_config ( hdev , fwname ) ;
2015-08-25 18:55:44 +03:00
skb = __hci_cmd_sync ( hdev , HCI_OP_RESET , 0 , NULL , HCI_CMD_TIMEOUT ) ;
if ( IS_ERR ( skb ) )
return PTR_ERR ( skb ) ;
kfree_skb ( skb ) ;
if ( speed_change ) {
err = intel_set_baudrate ( hu , oper_speed ) ;
if ( err )
return err ;
}
2015-08-31 19:34:30 +03:00
bt_dev_info ( hdev , " Setup complete " ) ;
2015-08-25 18:55:44 +03:00
2015-07-01 13:20:26 +03:00
clear_bit ( STATE_BOOTLOADER , & intel - > flags ) ;
return 0 ;
}
static int intel_recv_event ( struct hci_dev * hdev , struct sk_buff * skb )
{
struct hci_uart * hu = hci_get_drvdata ( hdev ) ;
struct intel_data * intel = hu - > priv ;
struct hci_event_hdr * hdr ;
2015-08-27 08:21:51 +03:00
if ( ! test_bit ( STATE_BOOTLOADER , & intel - > flags ) & &
! test_bit ( STATE_BOOTING , & intel - > flags ) )
2015-07-01 13:20:26 +03:00
goto recv ;
hdr = ( void * ) skb - > data ;
/* When the firmware loading completes the device sends
* out a vendor specific event indicating the result of
* the firmware loading .
*/
if ( skb - > len = = 7 & & hdr - > evt = = 0xff & & hdr - > plen = = 0x05 & &
skb - > data [ 2 ] = = 0x06 ) {
if ( skb - > data [ 3 ] ! = 0x00 )
set_bit ( STATE_FIRMWARE_FAILED , & intel - > flags ) ;
if ( test_and_clear_bit ( STATE_DOWNLOADING , & intel - > flags ) & &
test_bit ( STATE_FIRMWARE_LOADED , & intel - > flags ) ) {
smp_mb__after_atomic ( ) ;
wake_up_bit ( & intel - > flags , STATE_DOWNLOADING ) ;
}
/* When switching to the operational firmware the device
* sends a vendor specific event indicating that the bootup
* completed .
*/
} else if ( skb - > len = = 9 & & hdr - > evt = = 0xff & & hdr - > plen = = 0x07 & &
skb - > data [ 2 ] = = 0x02 ) {
if ( test_and_clear_bit ( STATE_BOOTING , & intel - > flags ) ) {
smp_mb__after_atomic ( ) ;
wake_up_bit ( & intel - > flags , STATE_BOOTING ) ;
}
}
recv :
return hci_recv_frame ( hdev , skb ) ;
}
2015-08-29 14:38:19 +03:00
static void intel_recv_lpm_notify ( struct hci_dev * hdev , int value )
{
struct hci_uart * hu = hci_get_drvdata ( hdev ) ;
struct intel_data * intel = hu - > priv ;
2015-08-31 19:34:30 +03:00
bt_dev_dbg ( hdev , " TX idle notification (%d) " , value ) ;
2015-08-29 14:38:19 +03:00
2015-09-02 13:04:13 +03:00
if ( value ) {
2015-08-29 14:38:19 +03:00
set_bit ( STATE_TX_ACTIVE , & intel - > flags ) ;
2015-09-02 13:04:13 +03:00
schedule_work ( & intel - > busy_work ) ;
} else {
2015-08-29 14:38:19 +03:00
clear_bit ( STATE_TX_ACTIVE , & intel - > flags ) ;
2015-09-02 13:04:13 +03:00
}
2015-08-29 14:38:19 +03:00
}
static int intel_recv_lpm ( struct hci_dev * hdev , struct sk_buff * skb )
{
struct hci_lpm_pkt * lpm = ( void * ) skb - > data ;
2015-09-02 13:04:11 +03:00
struct hci_uart * hu = hci_get_drvdata ( hdev ) ;
struct intel_data * intel = hu - > priv ;
2015-08-29 14:38:19 +03:00
switch ( lpm - > opcode ) {
case LPM_OP_TX_NOTIFY :
2015-09-02 13:04:14 +03:00
if ( lpm - > dlen < 1 ) {
bt_dev_err ( hu - > hdev , " Invalid LPM notification packet " ) ;
break ;
}
intel_recv_lpm_notify ( hdev , lpm - > data [ 0 ] ) ;
2015-08-29 14:38:19 +03:00
break ;
2015-09-02 13:04:11 +03:00
case LPM_OP_SUSPEND_ACK :
set_bit ( STATE_SUSPENDED , & intel - > flags ) ;
if ( test_and_clear_bit ( STATE_LPM_TRANSACTION , & intel - > flags ) ) {
smp_mb__after_atomic ( ) ;
wake_up_bit ( & intel - > flags , STATE_LPM_TRANSACTION ) ;
}
break ;
case LPM_OP_RESUME_ACK :
clear_bit ( STATE_SUSPENDED , & intel - > flags ) ;
if ( test_and_clear_bit ( STATE_LPM_TRANSACTION , & intel - > flags ) ) {
smp_mb__after_atomic ( ) ;
wake_up_bit ( & intel - > flags , STATE_LPM_TRANSACTION ) ;
}
break ;
2015-08-29 14:38:19 +03:00
default :
2015-08-31 19:34:30 +03:00
bt_dev_err ( hdev , " Unknown LPM opcode (%02x) " , lpm - > opcode ) ;
2015-08-29 14:38:19 +03:00
break ;
}
kfree_skb ( skb ) ;
return 0 ;
}
# define INTEL_RECV_LPM \
. type = HCI_LPM_PKT , \
. hlen = HCI_LPM_HDR_SIZE , \
. loff = 1 , \
. lsize = 1 , \
. maxlen = HCI_LPM_MAX_SIZE
2015-07-01 13:20:26 +03:00
static const struct h4_recv_pkt intel_recv_pkts [ ] = {
2015-08-29 14:38:19 +03:00
{ H4_RECV_ACL , . recv = hci_recv_frame } ,
{ H4_RECV_SCO , . recv = hci_recv_frame } ,
{ H4_RECV_EVENT , . recv = intel_recv_event } ,
{ INTEL_RECV_LPM , . recv = intel_recv_lpm } ,
2015-07-01 13:20:26 +03:00
} ;
static int intel_recv ( struct hci_uart * hu , const void * data , int count )
{
struct intel_data * intel = hu - > priv ;
if ( ! test_bit ( HCI_UART_REGISTERED , & hu - > flags ) )
return - EUNATCH ;
intel - > rx_skb = h4_recv_buf ( hu - > hdev , intel - > rx_skb , data , count ,
intel_recv_pkts ,
ARRAY_SIZE ( intel_recv_pkts ) ) ;
if ( IS_ERR ( intel - > rx_skb ) ) {
int err = PTR_ERR ( intel - > rx_skb ) ;
2015-08-31 19:34:30 +03:00
bt_dev_err ( hu - > hdev , " Frame reassembly failed (%d) " , err ) ;
2015-07-01 13:20:26 +03:00
intel - > rx_skb = NULL ;
return err ;
}
return count ;
}
static int intel_enqueue ( struct hci_uart * hu , struct sk_buff * skb )
{
struct intel_data * intel = hu - > priv ;
2015-09-02 13:04:13 +03:00
struct list_head * p ;
2015-07-01 13:20:26 +03:00
BT_DBG ( " hu %p skb %p " , hu , skb ) ;
2017-03-29 19:15:28 +03:00
if ( ! hu - > tty - > dev )
goto out_enqueue ;
2015-09-02 13:04:13 +03:00
/* Be sure our controller is resumed and potential LPM transaction
* completed before enqueuing any packet .
*/
mutex_lock ( & intel_device_list_lock ) ;
list_for_each ( p , & intel_device_list ) {
struct intel_device * idev = list_entry ( p , struct intel_device ,
list ) ;
if ( hu - > tty - > dev - > parent = = idev - > pdev - > dev . parent ) {
pm_runtime_get_sync ( & idev - > pdev - > dev ) ;
pm_runtime_mark_last_busy ( & idev - > pdev - > dev ) ;
pm_runtime_put_autosuspend ( & idev - > pdev - > dev ) ;
break ;
}
}
mutex_unlock ( & intel_device_list_lock ) ;
2017-03-29 19:15:28 +03:00
out_enqueue :
2015-07-01 13:20:26 +03:00
skb_queue_tail ( & intel - > txq , skb ) ;
return 0 ;
}
static struct sk_buff * intel_dequeue ( struct hci_uart * hu )
{
struct intel_data * intel = hu - > priv ;
struct sk_buff * skb ;
skb = skb_dequeue ( & intel - > txq ) ;
if ( ! skb )
return skb ;
if ( test_bit ( STATE_BOOTLOADER , & intel - > flags ) & &
2015-11-05 09:33:56 +03:00
( hci_skb_pkt_type ( skb ) = = HCI_COMMAND_PKT ) ) {
2015-07-01 13:20:26 +03:00
struct hci_command_hdr * cmd = ( void * ) skb - > data ;
__u16 opcode = le16_to_cpu ( cmd - > opcode ) ;
/* When the 0xfc01 command is issued to boot into
* the operational firmware , it will actually not
* send a command complete event . To keep the flow
* control working inject that event here .
*/
if ( opcode = = 0xfc01 )
inject_cmd_complete ( hu - > hdev , opcode ) ;
}
/* Prepend skb with frame type */
2015-11-05 09:33:56 +03:00
memcpy ( skb_push ( skb , 1 ) , & hci_skb_pkt_type ( skb ) , 1 ) ;
2015-07-01 13:20:26 +03:00
return skb ;
}
static const struct hci_uart_proto intel_proto = {
. id = HCI_UART_INTEL ,
. name = " Intel " ,
2015-10-20 22:30:45 +03:00
. manufacturer = 2 ,
2015-07-01 13:20:26 +03:00
. init_speed = 115200 ,
2015-08-25 18:55:44 +03:00
. oper_speed = 3000000 ,
2015-07-01 13:20:26 +03:00
. open = intel_open ,
. close = intel_close ,
. flush = intel_flush ,
. setup = intel_setup ,
2015-08-25 18:55:44 +03:00
. set_baudrate = intel_set_baudrate ,
2015-07-01 13:20:26 +03:00
. recv = intel_recv ,
. enqueue = intel_enqueue ,
. dequeue = intel_dequeue ,
} ;
2015-08-27 08:21:51 +03:00
# ifdef CONFIG_ACPI
static const struct acpi_device_id intel_acpi_match [ ] = {
{ " INT33E1 " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( acpi , intel_acpi_match ) ;
# endif
2015-09-02 13:04:13 +03:00
# ifdef CONFIG_PM
2015-09-09 22:04:15 +03:00
static int intel_suspend_device ( struct device * dev )
2015-09-02 13:04:12 +03:00
{
struct intel_device * idev = dev_get_drvdata ( dev ) ;
mutex_lock ( & idev - > hu_lock ) ;
if ( idev - > hu )
intel_lpm_suspend ( idev - > hu ) ;
mutex_unlock ( & idev - > hu_lock ) ;
return 0 ;
}
2015-09-09 22:04:15 +03:00
static int intel_resume_device ( struct device * dev )
2015-09-02 13:04:12 +03:00
{
struct intel_device * idev = dev_get_drvdata ( dev ) ;
mutex_lock ( & idev - > hu_lock ) ;
if ( idev - > hu )
intel_lpm_resume ( idev - > hu ) ;
mutex_unlock ( & idev - > hu_lock ) ;
return 0 ;
}
# endif
2015-09-09 22:04:15 +03:00
# ifdef CONFIG_PM_SLEEP
static int intel_suspend ( struct device * dev )
{
struct intel_device * idev = dev_get_drvdata ( dev ) ;
if ( device_may_wakeup ( dev ) )
enable_irq_wake ( idev - > irq ) ;
return intel_suspend_device ( dev ) ;
}
static int intel_resume ( struct device * dev )
{
struct intel_device * idev = dev_get_drvdata ( dev ) ;
if ( device_may_wakeup ( dev ) )
disable_irq_wake ( idev - > irq ) ;
return intel_resume_device ( dev ) ;
}
# endif
2015-09-02 13:04:12 +03:00
static const struct dev_pm_ops intel_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS ( intel_suspend , intel_resume )
2015-09-09 22:04:15 +03:00
SET_RUNTIME_PM_OPS ( intel_suspend_device , intel_resume_device , NULL )
2015-09-02 13:04:12 +03:00
} ;
2017-06-06 17:47:18 +03:00
static const struct acpi_gpio_params reset_gpios = { 0 , 0 , false } ;
static const struct acpi_gpio_params host_wake_gpios = { 1 , 0 , false } ;
static const struct acpi_gpio_mapping acpi_hci_intel_gpios [ ] = {
{ " reset-gpios " , & reset_gpios , 1 } ,
{ " host-wake-gpios " , & host_wake_gpios , 1 } ,
{ } ,
} ;
2015-08-27 08:21:51 +03:00
static int intel_probe ( struct platform_device * pdev )
{
struct intel_device * idev ;
2017-06-06 17:47:18 +03:00
int ret ;
2015-08-27 08:21:51 +03:00
idev = devm_kzalloc ( & pdev - > dev , sizeof ( * idev ) , GFP_KERNEL ) ;
if ( ! idev )
return - ENOMEM ;
2015-09-02 13:04:12 +03:00
mutex_init ( & idev - > hu_lock ) ;
2015-08-27 08:21:51 +03:00
idev - > pdev = pdev ;
2017-06-06 17:47:18 +03:00
ret = devm_acpi_dev_add_driver_gpios ( & pdev - > dev , acpi_hci_intel_gpios ) ;
if ( ret )
dev_dbg ( & pdev - > dev , " Unable to add GPIO mapping table \n " ) ;
2016-04-28 19:48:25 +03:00
idev - > reset = devm_gpiod_get ( & pdev - > dev , " reset " , GPIOD_OUT_LOW ) ;
2015-08-27 08:21:51 +03:00
if ( IS_ERR ( idev - > reset ) ) {
dev_err ( & pdev - > dev , " Unable to retrieve gpio \n " ) ;
return PTR_ERR ( idev - > reset ) ;
}
2015-08-29 14:38:18 +03:00
idev - > irq = platform_get_irq ( pdev , 0 ) ;
if ( idev - > irq < 0 ) {
struct gpio_desc * host_wake ;
dev_err ( & pdev - > dev , " No IRQ, falling back to gpio-irq \n " ) ;
2016-04-28 19:48:25 +03:00
host_wake = devm_gpiod_get ( & pdev - > dev , " host-wake " , GPIOD_IN ) ;
2015-08-29 14:38:18 +03:00
if ( IS_ERR ( host_wake ) ) {
dev_err ( & pdev - > dev , " Unable to retrieve IRQ \n " ) ;
goto no_irq ;
}
idev - > irq = gpiod_to_irq ( host_wake ) ;
if ( idev - > irq < 0 ) {
dev_err ( & pdev - > dev , " No corresponding irq for gpio \n " ) ;
goto no_irq ;
}
}
/* Only enable wake-up/irq when controller is powered */
device_set_wakeup_capable ( & pdev - > dev , true ) ;
device_wakeup_disable ( & pdev - > dev ) ;
no_irq :
2015-08-27 08:21:51 +03:00
platform_set_drvdata ( pdev , idev ) ;
/* Place this instance on the device list */
2015-08-31 19:34:31 +03:00
mutex_lock ( & intel_device_list_lock ) ;
2015-08-27 08:21:51 +03:00
list_add_tail ( & idev - > list , & intel_device_list ) ;
2015-08-31 19:34:31 +03:00
mutex_unlock ( & intel_device_list_lock ) ;
2015-08-27 08:21:51 +03:00
2015-08-29 14:38:18 +03:00
dev_info ( & pdev - > dev , " registered, gpio(%d)/irq(%d). \n " ,
desc_to_gpio ( idev - > reset ) , idev - > irq ) ;
2015-08-27 08:21:51 +03:00
return 0 ;
}
static int intel_remove ( struct platform_device * pdev )
{
struct intel_device * idev = platform_get_drvdata ( pdev ) ;
2015-08-29 14:38:18 +03:00
device_wakeup_disable ( & pdev - > dev ) ;
2015-08-31 19:34:31 +03:00
mutex_lock ( & intel_device_list_lock ) ;
2015-08-27 08:21:51 +03:00
list_del ( & idev - > list ) ;
2015-08-31 19:34:31 +03:00
mutex_unlock ( & intel_device_list_lock ) ;
2015-08-27 08:21:51 +03:00
dev_info ( & pdev - > dev , " unregistered. \n " ) ;
return 0 ;
}
static struct platform_driver intel_driver = {
. probe = intel_probe ,
. remove = intel_remove ,
. driver = {
. name = " hci_intel " ,
. acpi_match_table = ACPI_PTR ( intel_acpi_match ) ,
2015-09-02 13:04:12 +03:00
. pm = & intel_pm_ops ,
2015-08-27 08:21:51 +03:00
} ,
} ;
2015-07-01 13:20:26 +03:00
int __init intel_init ( void )
{
2015-08-27 08:21:51 +03:00
platform_driver_register ( & intel_driver ) ;
2015-07-01 13:20:26 +03:00
return hci_uart_register_proto ( & intel_proto ) ;
}
int __exit intel_deinit ( void )
{
2015-08-27 08:21:51 +03:00
platform_driver_unregister ( & intel_driver ) ;
2015-07-01 13:20:26 +03:00
return hci_uart_unregister_proto ( & intel_proto ) ;
}