2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2017-03-28 18:59:35 +03:00
/*
* Bluetooth HCI serdev driver lib
*
* Copyright ( C ) 2017 Linaro , Ltd . , Rob Herring < robh @ kernel . org >
*
* Based on hci_ldisc . c :
*
* Copyright ( C ) 2000 - 2001 Qualcomm Incorporated
* Copyright ( C ) 2002 - 2003 Maxim Krasnyansky < maxk @ qualcomm . com >
* Copyright ( C ) 2004 - 2005 Marcel Holtmann < marcel @ holtmann . org >
*/
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/serdev.h>
# include <linux/skbuff.h>
# include <net/bluetooth/bluetooth.h>
# include <net/bluetooth/hci_core.h>
# include "hci_uart.h"
static inline void hci_uart_tx_complete ( struct hci_uart * hu , int pkt_type )
{
struct hci_dev * hdev = hu - > hdev ;
/* Update HCI stat counters */
switch ( pkt_type ) {
case HCI_COMMAND_PKT :
hdev - > stat . cmd_tx + + ;
break ;
case HCI_ACLDATA_PKT :
hdev - > stat . acl_tx + + ;
break ;
case HCI_SCODATA_PKT :
hdev - > stat . sco_tx + + ;
break ;
}
}
static inline struct sk_buff * hci_uart_dequeue ( struct hci_uart * hu )
{
struct sk_buff * skb = hu - > tx_skb ;
2018-08-22 15:04:12 +03:00
if ( ! skb ) {
if ( test_bit ( HCI_UART_PROTO_READY , & hu - > flags ) )
skb = hu - > proto - > dequeue ( hu ) ;
} else
2017-03-28 18:59:35 +03:00
hu - > tx_skb = NULL ;
return skb ;
}
static void hci_uart_write_work ( struct work_struct * work )
{
struct hci_uart * hu = container_of ( work , struct hci_uart , write_work ) ;
struct serdev_device * serdev = hu - > serdev ;
struct hci_dev * hdev = hu - > hdev ;
struct sk_buff * skb ;
/* REVISIT:
* should we cope with bad skbs or - > write ( ) returning an error value ?
*/
do {
clear_bit ( HCI_UART_TX_WAKEUP , & hu - > tx_state ) ;
while ( ( skb = hci_uart_dequeue ( hu ) ) ) {
int len ;
len = serdev_device_write_buf ( serdev ,
skb - > data , skb - > len ) ;
hdev - > stat . byte_tx + = len ;
skb_pull ( skb , len ) ;
if ( skb - > len ) {
hu - > tx_skb = skb ;
break ;
}
hci_uart_tx_complete ( hu , hci_skb_pkt_type ( skb ) ) ;
kfree_skb ( skb ) ;
}
2020-12-14 10:29:21 +03:00
clear_bit ( HCI_UART_SENDING , & hu - > tx_state ) ;
} while ( test_bit ( HCI_UART_TX_WAKEUP , & hu - > tx_state ) ) ;
2017-03-28 18:59:35 +03:00
}
/* ------- Interface to HCI layer ------ */
/* Reset device */
static int hci_uart_flush ( struct hci_dev * hdev )
{
struct hci_uart * hu = hci_get_drvdata ( hdev ) ;
BT_DBG ( " hdev %p serdev %p " , hdev , hu - > serdev ) ;
if ( hu - > tx_skb ) {
kfree_skb ( hu - > tx_skb ) ; hu - > tx_skb = NULL ;
}
/* Flush any pending characters in the driver and discipline. */
serdev_device_write_flush ( hu - > serdev ) ;
if ( test_bit ( HCI_UART_PROTO_READY , & hu - > flags ) )
hu - > proto - > flush ( hu ) ;
return 0 ;
}
2018-05-27 22:04:51 +03:00
/* Initialize device */
static int hci_uart_open ( struct hci_dev * hdev )
{
2020-09-10 13:30:42 +03:00
struct hci_uart * hu = hci_get_drvdata ( hdev ) ;
int err ;
2018-05-27 22:04:51 +03:00
BT_DBG ( " %s %p " , hdev - > name , hdev ) ;
2020-09-10 13:30:42 +03:00
/* When Quirk HCI_QUIRK_NON_PERSISTENT_SETUP is set by
* driver , BT SoC is completely turned OFF during
* BT OFF . Upon next BT ON UART port should be opened .
*/
if ( ! test_bit ( HCI_UART_PROTO_READY , & hu - > flags ) ) {
err = serdev_device_open ( hu - > serdev ) ;
if ( err )
return err ;
set_bit ( HCI_UART_PROTO_READY , & hu - > flags ) ;
}
2018-05-27 22:04:51 +03:00
/* Undo clearing this from hci_uart_close() */
hdev - > flush = hci_uart_flush ;
return 0 ;
}
2017-03-28 18:59:35 +03:00
/* Close device */
static int hci_uart_close ( struct hci_dev * hdev )
{
2020-09-10 13:30:42 +03:00
struct hci_uart * hu = hci_get_drvdata ( hdev ) ;
2017-03-28 18:59:35 +03:00
BT_DBG ( " hdev %p " , hdev ) ;
2020-09-10 13:30:42 +03:00
if ( ! test_bit ( HCI_UART_PROTO_READY , & hu - > flags ) )
return 0 ;
2017-03-28 18:59:35 +03:00
hci_uart_flush ( hdev ) ;
hdev - > flush = NULL ;
2020-09-10 13:30:42 +03:00
/* When QUIRK HCI_QUIRK_NON_PERSISTENT_SETUP is set by driver,
* BT SOC is completely powered OFF during BT OFF , holding port
* open may drain the battery .
*/
if ( test_bit ( HCI_QUIRK_NON_PERSISTENT_SETUP , & hdev - > quirks ) ) {
clear_bit ( HCI_UART_PROTO_READY , & hu - > flags ) ;
serdev_device_close ( hu - > serdev ) ;
}
2017-03-28 18:59:35 +03:00
return 0 ;
}
/* Send frames from HCI layer */
static int hci_uart_send_frame ( struct hci_dev * hdev , struct sk_buff * skb )
{
struct hci_uart * hu = hci_get_drvdata ( hdev ) ;
BT_DBG ( " %s: type %d len %d " , hdev - > name , hci_skb_pkt_type ( skb ) ,
skb - > len ) ;
hu - > proto - > enqueue ( hu , skb ) ;
hci_uart_tx_wakeup ( hu ) ;
return 0 ;
}
static int hci_uart_setup ( struct hci_dev * hdev )
{
struct hci_uart * hu = hci_get_drvdata ( hdev ) ;
struct hci_rp_read_local_version * ver ;
struct sk_buff * skb ;
unsigned int speed ;
int err ;
/* Init speed if any */
if ( hu - > init_speed )
speed = hu - > init_speed ;
else if ( hu - > proto - > init_speed )
speed = hu - > proto - > init_speed ;
else
speed = 0 ;
if ( speed )
serdev_device_set_baudrate ( hu - > serdev , speed ) ;
/* 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 ( hu - > proto - > set_baudrate & & speed ) {
err = hu - > proto - > set_baudrate ( hu , speed ) ;
if ( err )
2017-10-30 12:42:59 +03:00
bt_dev_err ( hdev , " Failed to set baudrate " ) ;
2017-03-28 18:59:35 +03:00
else
serdev_device_set_baudrate ( hu - > serdev , speed ) ;
}
if ( hu - > proto - > setup )
return hu - > proto - > setup ( hu ) ;
if ( ! test_bit ( HCI_UART_VND_DETECT , & hu - > hdev_flags ) )
return 0 ;
skb = __hci_cmd_sync ( hdev , HCI_OP_READ_LOCAL_VERSION , 0 , NULL ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
2017-10-30 12:42:59 +03:00
bt_dev_err ( hdev , " Reading local version info failed (%ld) " ,
PTR_ERR ( skb ) ) ;
2017-03-28 18:59:35 +03:00
return 0 ;
}
2018-05-15 00:38:47 +03:00
if ( skb - > len ! = sizeof ( * ver ) )
2017-10-30 12:42:59 +03:00
bt_dev_err ( hdev , " Event length mismatch for version info " ) ;
2017-03-28 18:59:35 +03:00
kfree_skb ( skb ) ;
return 0 ;
}
2022-07-04 13:33:24 +03:00
/* Check if the device is wakeable */
static bool hci_uart_wakeup ( struct hci_dev * hdev )
{
/* HCI UART devices are assumed to be wakeable by default.
* Implement wakeup callback to override this behavior .
*/
return true ;
}
2017-03-28 18:59:35 +03:00
/** hci_uart_write_wakeup - transmit buffer wakeup
* @ serdev : serial device
*
* This function is called by the serdev framework when it accepts
* more data being sent .
*/
static void hci_uart_write_wakeup ( struct serdev_device * serdev )
{
struct hci_uart * hu = serdev_device_get_drvdata ( serdev ) ;
BT_DBG ( " " ) ;
if ( ! hu | | serdev ! = hu - > serdev ) {
WARN_ON ( 1 ) ;
return ;
}
if ( test_bit ( HCI_UART_PROTO_READY , & hu - > flags ) )
hci_uart_tx_wakeup ( hu ) ;
}
/** hci_uart_receive_buf - receive buffer wakeup
* @ serdev : serial device
* @ data : pointer to received data
* @ count : count of received data in bytes
*
* This function is called by the serdev framework when it received data
* in the RX buffer .
*
* Return : number of processed bytes
*/
static int hci_uart_receive_buf ( struct serdev_device * serdev , const u8 * data ,
size_t count )
{
struct hci_uart * hu = serdev_device_get_drvdata ( serdev ) ;
if ( ! hu | | serdev ! = hu - > serdev ) {
WARN_ON ( 1 ) ;
return 0 ;
}
if ( ! test_bit ( HCI_UART_PROTO_READY , & hu - > flags ) )
return 0 ;
/* It does not need a lock here as it is already protected by a mutex in
* tty caller
*/
hu - > proto - > recv ( hu , data , count ) ;
if ( hu - > hdev )
hu - > hdev - > stat . byte_rx + = count ;
return count ;
}
2020-05-09 16:17:19 +03:00
static const struct serdev_device_ops hci_serdev_client_ops = {
2017-03-28 18:59:35 +03:00
. receive_buf = hci_uart_receive_buf ,
. write_wakeup = hci_uart_write_wakeup ,
} ;
int hci_uart_register_device ( struct hci_uart * hu ,
const struct hci_uart_proto * p )
{
int err ;
struct hci_dev * hdev ;
BT_DBG ( " " ) ;
2017-03-28 18:59:36 +03:00
serdev_device_set_client_ops ( hu - > serdev , & hci_serdev_client_ops ) ;
2022-08-29 17:58:12 +03:00
if ( percpu_init_rwsem ( & hu - > proto_lock ) )
return - ENOMEM ;
2018-05-27 22:04:52 +03:00
err = serdev_device_open ( hu - > serdev ) ;
2017-03-28 18:59:35 +03:00
if ( err )
2022-08-29 17:58:12 +03:00
goto err_rwsem ;
2022-01-13 16:27:04 +03:00
2018-05-27 22:04:52 +03:00
err = p - > open ( hu ) ;
if ( err )
goto err_open ;
2017-03-28 18:59:35 +03:00
hu - > proto = p ;
set_bit ( HCI_UART_PROTO_READY , & hu - > flags ) ;
/* Initialize and register HCI device */
hdev = hci_alloc_dev ( ) ;
if ( ! hdev ) {
BT_ERR ( " Can't allocate HCI device " ) ;
err = - ENOMEM ;
goto err_alloc ;
}
hu - > hdev = hdev ;
hdev - > bus = HCI_UART ;
hci_set_drvdata ( hdev , hu ) ;
2018-05-27 22:04:53 +03:00
INIT_WORK ( & hu - > init_ready , hci_uart_init_work ) ;
2017-03-28 18:59:35 +03:00
INIT_WORK ( & hu - > write_work , hci_uart_write_work ) ;
/* Only when vendor specific setup callback is provided, consider
* the manufacturer information valid . This avoids filling in the
* value for Ericsson when nothing is specified .
*/
if ( hu - > proto - > setup )
hdev - > manufacturer = hu - > proto - > manufacturer ;
hdev - > open = hci_uart_open ;
hdev - > close = hci_uart_close ;
hdev - > flush = hci_uart_flush ;
hdev - > send = hci_uart_send_frame ;
hdev - > setup = hci_uart_setup ;
2022-07-04 13:33:24 +03:00
if ( ! hdev - > wakeup )
hdev - > wakeup = hci_uart_wakeup ;
2017-03-28 18:59:35 +03:00
SET_HCIDEV_DEV ( hdev , & hu - > serdev - > dev ) ;
2021-06-29 22:59:07 +03:00
if ( test_bit ( HCI_UART_NO_SUSPEND_NOTIFIER , & hu - > flags ) )
set_bit ( HCI_QUIRK_NO_SUSPEND_NOTIFIER , & hdev - > quirks ) ;
2017-03-28 18:59:35 +03:00
if ( test_bit ( HCI_UART_RAW_DEVICE , & hu - > hdev_flags ) )
set_bit ( HCI_QUIRK_RAW_DEVICE , & hdev - > quirks ) ;
if ( test_bit ( HCI_UART_EXT_CONFIG , & hu - > hdev_flags ) )
set_bit ( HCI_QUIRK_EXTERNAL_CONFIG , & hdev - > quirks ) ;
if ( test_bit ( HCI_UART_CREATE_AMP , & hu - > hdev_flags ) )
hdev - > dev_type = HCI_AMP ;
else
hdev - > dev_type = HCI_PRIMARY ;
if ( test_bit ( HCI_UART_INIT_PENDING , & hu - > hdev_flags ) )
return 0 ;
if ( hci_register_dev ( hdev ) < 0 ) {
BT_ERR ( " Can't register HCI device " ) ;
err = - ENODEV ;
goto err_register ;
}
set_bit ( HCI_UART_REGISTERED , & hu - > flags ) ;
return 0 ;
err_register :
hci_free_dev ( hdev ) ;
err_alloc :
clear_bit ( HCI_UART_PROTO_READY , & hu - > flags ) ;
p - > close ( hu ) ;
2018-05-27 22:04:52 +03:00
err_open :
serdev_device_close ( hu - > serdev ) ;
2022-08-29 17:58:12 +03:00
err_rwsem :
percpu_free_rwsem ( & hu - > proto_lock ) ;
2017-03-28 18:59:35 +03:00
return err ;
}
2017-03-28 18:59:37 +03:00
EXPORT_SYMBOL_GPL ( hci_uart_register_device ) ;
2017-07-08 19:37:41 +03:00
void hci_uart_unregister_device ( struct hci_uart * hu )
{
struct hci_dev * hdev = hu - > hdev ;
2020-08-01 19:29:56 +03:00
cancel_work_sync ( & hu - > init_ready ) ;
2020-07-21 05:37:16 +03:00
if ( test_bit ( HCI_UART_REGISTERED , & hu - > flags ) )
hci_unregister_dev ( hdev ) ;
2017-07-08 19:37:41 +03:00
hci_free_dev ( hdev ) ;
cancel_work_sync ( & hu - > write_work ) ;
hu - > proto - > close ( hu ) ;
2020-09-10 13:30:42 +03:00
if ( test_bit ( HCI_UART_PROTO_READY , & hu - > flags ) ) {
clear_bit ( HCI_UART_PROTO_READY , & hu - > flags ) ;
serdev_device_close ( hu - > serdev ) ;
}
2022-08-29 17:58:12 +03:00
percpu_free_rwsem ( & hu - > proto_lock ) ;
2017-07-08 19:37:41 +03:00
}
EXPORT_SYMBOL_GPL ( hci_uart_unregister_device ) ;