Commit 89eb6e09 authored by David S. Miller's avatar David S. Miller

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2019-04-25

Here's the main bluetooth-next pull request for the 5.2 kernel.

 - Added support for Mediatek SDIO controllers
 - Added support for Broadcom BCM2076B1 UART controller
 - Added support for Marvel SD8987 chipset
 - Fix buffer overflow bug in hidp protocol
 - Various other smaller fixes & improvements

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8b448365 d5bb334a
...@@ -336,7 +336,7 @@ config BT_MRVL ...@@ -336,7 +336,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices. The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support This driver is required if you want to support
Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8977/8997. Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8977/8987/8997.
Say Y here to compile Marvell Bluetooth driver Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module. into the kernel or say M to compile it as module.
...@@ -350,7 +350,7 @@ config BT_MRVL_SDIO ...@@ -350,7 +350,7 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface. The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8977/SD8997 devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8977/SD8987/SD8997
chipsets are supported. chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver Say Y here to compile support for Marvell BT-over-SDIO driver
...@@ -379,6 +379,17 @@ config BT_WILINK ...@@ -379,6 +379,17 @@ config BT_WILINK
Say Y here to compile support for Texas Instrument's WiLink7 driver Say Y here to compile support for Texas Instrument's WiLink7 driver
into the kernel or say M to compile it as module (btwilink). into the kernel or say M to compile it as module (btwilink).
config BT_MTKSDIO
tristate "MediaTek HCI SDIO driver"
depends on MMC
help
MediaTek Bluetooth HCI SDIO driver.
This driver is required if you want to use MediaTek Bluetooth
with SDIO interface.
Say Y here to compile support for MediaTek Bluetooth SDIO devices
into the kernel or say M to compile it as module (btmtksdio).
config BT_MTKUART config BT_MTKUART
tristate "MediaTek HCI UART driver" tristate "MediaTek HCI UART driver"
depends on SERIAL_DEV_BUS depends on SERIAL_DEV_BUS
......
...@@ -20,6 +20,7 @@ obj-$(CONFIG_BT_ATH3K) += ath3k.o ...@@ -20,6 +20,7 @@ obj-$(CONFIG_BT_ATH3K) += ath3k.o
obj-$(CONFIG_BT_MRVL) += btmrvl.o obj-$(CONFIG_BT_MRVL) += btmrvl.o
obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o
obj-$(CONFIG_BT_WILINK) += btwilink.o obj-$(CONFIG_BT_WILINK) += btwilink.o
obj-$(CONFIG_BT_MTKSDIO) += btmtksdio.o
obj-$(CONFIG_BT_MTKUART) += btmtkuart.o obj-$(CONFIG_BT_MTKUART) += btmtkuart.o
obj-$(CONFIG_BT_QCOMSMD) += btqcomsmd.o obj-$(CONFIG_BT_QCOMSMD) += btqcomsmd.o
obj-$(CONFIG_BT_BCM) += btbcm.o obj-$(CONFIG_BT_BCM) += btbcm.o
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}}) #define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}})
#define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}}) #define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}})
#define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}}) #define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}})
#define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}})
int btbcm_check_bdaddr(struct hci_dev *hdev) int btbcm_check_bdaddr(struct hci_dev *hdev)
{ {
...@@ -82,7 +83,8 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) ...@@ -82,7 +83,8 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
!bacmp(&bda->bdaddr, BDADDR_BCM20702A1) || !bacmp(&bda->bdaddr, BDADDR_BCM20702A1) ||
!bacmp(&bda->bdaddr, BDADDR_BCM4324B3) || !bacmp(&bda->bdaddr, BDADDR_BCM4324B3) ||
!bacmp(&bda->bdaddr, BDADDR_BCM4330B1) || !bacmp(&bda->bdaddr, BDADDR_BCM4330B1) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43430A0)) { !bacmp(&bda->bdaddr, BDADDR_BCM43430A0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43341B)) {
bt_dev_info(hdev, "BCM: Using default device address (%pMR)", bt_dev_info(hdev, "BCM: Using default device address (%pMR)",
&bda->bdaddr); &bda->bdaddr);
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
...@@ -333,6 +335,7 @@ struct bcm_subver_table { ...@@ -333,6 +335,7 @@ struct bcm_subver_table {
static const struct bcm_subver_table bcm_uart_subver_table[] = { static const struct bcm_subver_table bcm_uart_subver_table[] = {
{ 0x4103, "BCM4330B1" }, /* 002.001.003 */ { 0x4103, "BCM4330B1" }, /* 002.001.003 */
{ 0x410e, "BCM43341B0" }, /* 002.001.014 */ { 0x410e, "BCM43341B0" }, /* 002.001.014 */
{ 0x4204, "BCM2076B1" }, /* 002.002.004 */
{ 0x4406, "BCM4324B3" }, /* 002.004.006 */ { 0x4406, "BCM4324B3" }, /* 002.004.006 */
{ 0x6109, "BCM4335C0" }, /* 003.001.009 */ { 0x6109, "BCM4335C0" }, /* 003.001.009 */
{ 0x610c, "BCM4354" }, /* 003.001.012 */ { 0x610c, "BCM4354" }, /* 003.001.012 */
......
...@@ -235,6 +235,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8977 = { ...@@ -235,6 +235,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8977 = {
.fw_dump_end = 0xf8, .fw_dump_end = 0xf8,
}; };
static const struct btmrvl_sdio_card_reg btmrvl_reg_8987 = {
.cfg = 0x00,
.host_int_mask = 0x08,
.host_intstatus = 0x0c,
.card_status = 0x5c,
.sq_read_base_addr_a0 = 0xf8,
.sq_read_base_addr_a1 = 0xf9,
.card_revision = 0xc8,
.card_fw_status0 = 0xe8,
.card_fw_status1 = 0xe9,
.card_rx_len = 0xea,
.card_rx_unit = 0xeb,
.io_port_0 = 0xe4,
.io_port_1 = 0xe5,
.io_port_2 = 0xe6,
.int_read_to_clear = true,
.host_int_rsr = 0x04,
.card_misc_cfg = 0xd8,
.fw_dump_ctrl = 0xf0,
.fw_dump_start = 0xf1,
.fw_dump_end = 0xf8,
};
static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = { static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = {
.cfg = 0x00, .cfg = 0x00,
.host_int_mask = 0x08, .host_int_mask = 0x08,
...@@ -312,6 +335,15 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = { ...@@ -312,6 +335,15 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = {
.supports_fw_dump = true, .supports_fw_dump = true,
}; };
static const struct btmrvl_sdio_device btmrvl_sdio_sd8987 = {
.helper = NULL,
.firmware = "mrvl/sd8987_uapsta.bin",
.reg = &btmrvl_reg_8987,
.support_pscan_win_report = true,
.sd_blksz_fw_dl = 256,
.supports_fw_dump = true,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8997_uapsta.bin", .firmware = "mrvl/sd8997_uapsta.bin",
...@@ -343,6 +375,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { ...@@ -343,6 +375,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8977 Bluetooth device */ /* Marvell SD8977 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9146), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9146),
.driver_data = (unsigned long)&btmrvl_sdio_sd8977 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8977 },
/* Marvell SD8987 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x914A),
.driver_data = (unsigned long)&btmrvl_sdio_sd8987 },
/* Marvell SD8997 Bluetooth device */ /* Marvell SD8997 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9142), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9142),
.driver_data = (unsigned long)&btmrvl_sdio_sd8997 }, .driver_data = (unsigned long)&btmrvl_sdio_sd8997 },
...@@ -1797,4 +1832,5 @@ MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); ...@@ -1797,4 +1832,5 @@ MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8977_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8977_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8987_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin");
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 MediaTek Inc.
/*
* Bluetooth support for MediaTek SDIO devices
*
* This file is written based on btsdio.c and btmtkuart.c.
*
* Author: Sean Wang <sean.wang@mediatek.com>
*
*/
#include <asm/unaligned.h>
#include <linux/atomic.h>
#include <linux/firmware.h>
#include <linux/init.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/skbuff.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "h4_recv.h"
#define VERSION "0.1"
#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"
#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
#define MTKBTSDIO_AUTOSUSPEND_DELAY 8000
static bool enable_autosuspend;
struct btmtksdio_data {
const char *fwname;
};
static const struct btmtksdio_data mt7663_data = {
.fwname = FIRMWARE_MT7663,
};
static const struct btmtksdio_data mt7668_data = {
.fwname = FIRMWARE_MT7668,
};
static const struct sdio_device_id btmtksdio_table[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7663),
.driver_data = (kernel_ulong_t)&mt7663_data },
{SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7668),
.driver_data = (kernel_ulong_t)&mt7668_data },
{ } /* Terminating entry */
};
#define MTK_REG_CHLPCR 0x4 /* W1S */
#define C_INT_EN_SET BIT(0)
#define C_INT_EN_CLR BIT(1)
#define C_FW_OWN_REQ_SET BIT(8) /* For write */
#define C_COM_DRV_OWN BIT(8) /* For read */
#define C_FW_OWN_REQ_CLR BIT(9)
#define MTK_REG_CSDIOCSR 0x8
#define SDIO_RE_INIT_EN BIT(0)
#define SDIO_INT_CTL BIT(2)
#define MTK_REG_CHCR 0xc
#define C_INT_CLR_CTRL BIT(1)
/* CHISR have the same bits field definition with CHIER */
#define MTK_REG_CHISR 0x10
#define MTK_REG_CHIER 0x14
#define FW_OWN_BACK_INT BIT(0)
#define RX_DONE_INT BIT(1)
#define TX_EMPTY BIT(2)
#define TX_FIFO_OVERFLOW BIT(8)
#define RX_PKT_LEN GENMASK(31, 16)
#define MTK_REG_CTDR 0x18
#define MTK_REG_CRDR 0x1c
#define MTK_SDIO_BLOCK_SIZE 256
#define BTMTKSDIO_TX_WAIT_VND_EVT 1
enum {
MTK_WMT_PATCH_DWNLD = 0x1,
MTK_WMT_TEST = 0x2,
MTK_WMT_WAKEUP = 0x3,
MTK_WMT_HIF = 0x4,
MTK_WMT_FUNC_CTRL = 0x6,
MTK_WMT_RST = 0x7,
MTK_WMT_SEMAPHORE = 0x17,
};
enum {
BTMTK_WMT_INVALID,
BTMTK_WMT_PATCH_UNDONE,
BTMTK_WMT_PATCH_DONE,
BTMTK_WMT_ON_UNDONE,
BTMTK_WMT_ON_DONE,
BTMTK_WMT_ON_PROGRESS,
};
struct mtkbtsdio_hdr {
__le16 len;
__le16 reserved;
u8 bt_type;
} __packed;
struct mtk_wmt_hdr {
u8 dir;
u8 op;
__le16 dlen;
u8 flag;
} __packed;
struct mtk_hci_wmt_cmd {
struct mtk_wmt_hdr hdr;
u8 data[256];
} __packed;
struct btmtk_hci_wmt_evt {
struct hci_event_hdr hhdr;
struct mtk_wmt_hdr whdr;
} __packed;
struct btmtk_hci_wmt_evt_funcc {
struct btmtk_hci_wmt_evt hwhdr;
__be16 status;
} __packed;
struct btmtk_tci_sleep {
u8 mode;
__le16 duration;
__le16 host_duration;
u8 host_wakeup_pin;
u8 time_compensation;
} __packed;
struct btmtk_hci_wmt_params {
u8 op;
u8 flag;
u16 dlen;
const void *data;
u32 *status;
};
struct btmtksdio_dev {
struct hci_dev *hdev;
struct sdio_func *func;
struct device *dev;
struct work_struct tx_work;
unsigned long tx_state;
struct sk_buff_head txq;
struct sk_buff *evt_skb;
const struct btmtksdio_data *data;
};
static int mtk_hci_wmt_sync(struct hci_dev *hdev,
struct btmtk_hci_wmt_params *wmt_params)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
u32 hlen, status = BTMTK_WMT_INVALID;
struct btmtk_hci_wmt_evt *wmt_evt;
struct mtk_hci_wmt_cmd wc;
struct mtk_wmt_hdr *hdr;
int err;
hlen = sizeof(*hdr) + wmt_params->dlen;
if (hlen > 255)
return -EINVAL;
hdr = (struct mtk_wmt_hdr *)&wc;
hdr->dir = 1;
hdr->op = wmt_params->op;
hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
hdr->flag = wmt_params->flag;
memcpy(wc.data, wmt_params->data, wmt_params->dlen);
set_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state);
err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc);
if (err < 0) {
clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state);
return err;
}
/* The vendor specific WMT commands are all answered by a vendor
* specific event and will not have the Command Status or Command
* Complete as with usual HCI command flow control.
*
* After sending the command, wait for BTMTKSDIO_TX_WAIT_VND_EVT
* state to be cleared. The driver specific event receive routine
* will clear that state and with that indicate completion of the
* WMT command.
*/
err = wait_on_bit_timeout(&bdev->tx_state, BTMTKSDIO_TX_WAIT_VND_EVT,
TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT);
if (err == -EINTR) {
bt_dev_err(hdev, "Execution of wmt command interrupted");
clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state);
return err;
}
if (err) {
bt_dev_err(hdev, "Execution of wmt command timed out");
clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state);
return -ETIMEDOUT;
}
/* Parse and handle the return WMT event */
wmt_evt = (struct btmtk_hci_wmt_evt *)bdev->evt_skb->data;
if (wmt_evt->whdr.op != hdr->op) {
bt_dev_err(hdev, "Wrong op received %d expected %d",
wmt_evt->whdr.op, hdr->op);
err = -EIO;
goto err_free_skb;
}
switch (wmt_evt->whdr.op) {
case MTK_WMT_SEMAPHORE:
if (wmt_evt->whdr.flag == 2)
status = BTMTK_WMT_PATCH_UNDONE;
else
status = BTMTK_WMT_PATCH_DONE;
break;
case MTK_WMT_FUNC_CTRL:
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
status = BTMTK_WMT_ON_DONE;
else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
status = BTMTK_WMT_ON_PROGRESS;
else
status = BTMTK_WMT_ON_UNDONE;
break;
}
if (wmt_params->status)
*wmt_params->status = status;
err_free_skb:
kfree_skb(bdev->evt_skb);
bdev->evt_skb = NULL;
return err;
}
static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
struct sk_buff *skb)
{
struct mtkbtsdio_hdr *sdio_hdr;
int err;
/* Make sure that there are enough rooms for SDIO header */
if (unlikely(skb_headroom(skb) < sizeof(*sdio_hdr))) {
err = pskb_expand_head(skb, sizeof(*sdio_hdr), 0,
GFP_ATOMIC);
if (err < 0)
return err;
}
/* Prepend MediaTek SDIO Specific Header */
skb_push(skb, sizeof(*sdio_hdr));
sdio_hdr = (void *)skb->data;
sdio_hdr->len = cpu_to_le16(skb->len);
sdio_hdr->reserved = cpu_to_le16(0);
sdio_hdr->bt_type = hci_skb_pkt_type(skb);
err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data,
round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
if (err < 0)
goto err_skb_pull;
bdev->hdev->stat.byte_tx += skb->len;
kfree_skb(skb);
return 0;
err_skb_pull:
skb_pull(skb, sizeof(*sdio_hdr));
return err;
}
static u32 btmtksdio_drv_own_query(struct btmtksdio_dev *bdev)
{
return sdio_readl(bdev->func, MTK_REG_CHLPCR, NULL);
}
static void btmtksdio_tx_work(struct work_struct *work)
{
struct btmtksdio_dev *bdev = container_of(work, struct btmtksdio_dev,
tx_work);
struct sk_buff *skb;
int err;
pm_runtime_get_sync(bdev->dev);
sdio_claim_host(bdev->func);
while ((skb = skb_dequeue(&bdev->txq))) {
err = btmtksdio_tx_packet(bdev, skb);
if (err < 0) {
bdev->hdev->stat.err_tx++;
skb_queue_head(&bdev->txq, skb);
break;
}
}
sdio_release_host(bdev->func);
pm_runtime_mark_last_busy(bdev->dev);
pm_runtime_put_autosuspend(bdev->dev);
}
static int btmtksdio_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
struct hci_event_hdr *hdr = (void *)skb->data;
int err;
/* Fix up the vendor event id with 0xff for vendor specific instead
* of 0xe4 so that event send via monitoring socket can be parsed
* properly.
*/
if (hdr->evt == 0xe4)
hdr->evt = HCI_EV_VENDOR;
/* When someone waits for the WMT event, the skb is being cloned
* and being processed the events from there then.
*/
if (test_bit(BTMTKSDIO_TX_WAIT_VND_EVT, &bdev->tx_state)) {
bdev->evt_skb = skb_clone(skb, GFP_KERNEL);
if (!bdev->evt_skb) {
err = -ENOMEM;
goto err_out;
}
}
err = hci_recv_frame(hdev, skb);
if (err < 0)
goto err_free_skb;
if (hdr->evt == HCI_EV_VENDOR) {
if (test_and_clear_bit(BTMTKSDIO_TX_WAIT_VND_EVT,
&bdev->tx_state)) {
/* Barrier to sync with other CPUs */
smp_mb__after_atomic();
wake_up_bit(&bdev->tx_state, BTMTKSDIO_TX_WAIT_VND_EVT);
}
}
return 0;
err_free_skb:
kfree_skb(bdev->evt_skb);
bdev->evt_skb = NULL;
err_out:
return err;
}
static const struct h4_recv_pkt mtk_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = btmtksdio_recv_event },
};
static int btmtksdio_rx_packet(struct btmtksdio_dev *bdev, u16 rx_size)
{
const struct h4_recv_pkt *pkts = mtk_recv_pkts;
int pkts_count = ARRAY_SIZE(mtk_recv_pkts);
struct mtkbtsdio_hdr *sdio_hdr;
int err, i, pad_size;
struct sk_buff *skb;
u16 dlen;
if (rx_size < sizeof(*sdio_hdr))
return -EILSEQ;
/* A SDIO packet is exactly containing a Bluetooth packet */
skb = bt_skb_alloc(rx_size, GFP_KERNEL);
if (!skb)
return -ENOMEM;
skb_put(skb, rx_size);
err = sdio_readsb(bdev->func, skb->data, MTK_REG_CRDR, rx_size);
if (err < 0)
goto err_kfree_skb;
sdio_hdr = (void *)skb->data;
/* We assume the default error as -EILSEQ simply to make the error path
* be cleaner.
*/
err = -EILSEQ;
if (rx_size != le16_to_cpu(sdio_hdr->len)) {
bt_dev_err(bdev->hdev, "Rx size in sdio header is mismatched ");
goto err_kfree_skb;
}
hci_skb_pkt_type(skb) = sdio_hdr->bt_type;
/* Remove MediaTek SDIO header */
skb_pull(skb, sizeof(*sdio_hdr));
/* We have to dig into the packet to get payload size and then know how
* many padding bytes at the tail, these padding bytes should be removed
* before the packet is indicated to the core layer.
*/
for (i = 0; i < pkts_count; i++) {
if (sdio_hdr->bt_type == (&pkts[i])->type)
break;
}
if (i >= pkts_count) {
bt_dev_err(bdev->hdev, "Invalid bt type 0x%02x",
sdio_hdr->bt_type);
goto err_kfree_skb;
}
/* Remaining bytes cannot hold a header*/
if (skb->len < (&pkts[i])->hlen) {
bt_dev_err(bdev->hdev, "The size of bt header is mismatched");
goto err_kfree_skb;
}
switch ((&pkts[i])->lsize) {
case 1:
dlen = skb->data[(&pkts[i])->loff];
break;
case 2:
dlen = get_unaligned_le16(skb->data +
(&pkts[i])->loff);
break;
default:
goto err_kfree_skb;
}
pad_size = skb->len - (&pkts[i])->hlen - dlen;
/* Remaining bytes cannot hold a payload */
if (pad_size < 0) {
bt_dev_err(bdev->hdev, "The size of bt payload is mismatched");
goto err_kfree_skb;
}
/* Remove padding bytes */
skb_trim(skb, skb->len - pad_size);
/* Complete frame */
(&pkts[i])->recv(bdev->hdev, skb);
bdev->hdev->stat.byte_rx += rx_size;
return 0;
err_kfree_skb:
kfree_skb(skb);
return err;
}
static void btmtksdio_interrupt(struct sdio_func *func)
{
struct btmtksdio_dev *bdev = sdio_get_drvdata(func);
u32 int_status;
u16 rx_size;
/* It is required that the host gets ownership from the device before
* accessing any register, however, if SDIO host is not being released,
* a potential deadlock probably happens in a circular wait between SDIO
* IRQ work and PM runtime work. So, we have to explicitly release SDIO
* host here and claim again after the PM runtime work is all done.
*/
sdio_release_host(bdev->func);
pm_runtime_get_sync(bdev->dev);
sdio_claim_host(bdev->func);
/* Disable interrupt */
sdio_writel(func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
int_status = sdio_readl(func, MTK_REG_CHISR, NULL);
/* Ack an interrupt as soon as possible before any operation on
* hardware.
*
* Note that we don't ack any status during operations to avoid race
* condition between the host and the device such as it's possible to
* mistakenly ack RX_DONE for the next packet and then cause interrupts
* not be raised again but there is still pending data in the hardware
* FIFO.
*/
sdio_writel(func, int_status, MTK_REG_CHISR, NULL);
if (unlikely(!int_status))
bt_dev_err(bdev->hdev, "CHISR is 0");
if (int_status & FW_OWN_BACK_INT)
bt_dev_dbg(bdev->hdev, "Get fw own back");
if (int_status & TX_EMPTY)
schedule_work(&bdev->tx_work);
else if (unlikely(int_status & TX_FIFO_OVERFLOW))
bt_dev_warn(bdev->hdev, "Tx fifo overflow");
if (int_status & RX_DONE_INT) {
rx_size = (int_status & RX_PKT_LEN) >> 16;
if (btmtksdio_rx_packet(bdev, rx_size) < 0)
bdev->hdev->stat.err_rx++;
}
/* Enable interrupt */
sdio_writel(func, C_INT_EN_SET, MTK_REG_CHLPCR, 0);
pm_runtime_mark_last_busy(bdev->dev);
pm_runtime_put_autosuspend(bdev->dev);
}
static int btmtksdio_open(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
int err;
u32 status;
sdio_claim_host(bdev->func);
err = sdio_enable_func(bdev->func);
if (err < 0)
goto err_release_host;
/* Get ownership from the device */
sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err);
if (err < 0)
goto err_disable_func;
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
status & C_COM_DRV_OWN, 2000, 1000000);
if (err < 0) {
bt_dev_err(bdev->hdev, "Cannot get ownership from device");
goto err_disable_func;
}
/* Disable interrupt & mask out all interrupt sources */
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, &err);
if (err < 0)
goto err_disable_func;
sdio_writel(bdev->func, 0, MTK_REG_CHIER, &err);
if (err < 0)
goto err_disable_func;
err = sdio_claim_irq(bdev->func, btmtksdio_interrupt);
if (err < 0)
goto err_disable_func;
err = sdio_set_block_size(bdev->func, MTK_SDIO_BLOCK_SIZE);
if (err < 0)
goto err_release_irq;
/* SDIO CMD 5 allows the SDIO device back to idle state an
* synchronous interrupt is supported in SDIO 4-bit mode
*/
sdio_writel(bdev->func, SDIO_INT_CTL | SDIO_RE_INIT_EN,
MTK_REG_CSDIOCSR, &err);
if (err < 0)
goto err_release_irq;
/* Setup write-1-clear for CHISR register */
sdio_writel(bdev->func, C_INT_CLR_CTRL, MTK_REG_CHCR, &err);
if (err < 0)
goto err_release_irq;
/* Setup interrupt sources */
sdio_writel(bdev->func, RX_DONE_INT | TX_EMPTY | TX_FIFO_OVERFLOW,
MTK_REG_CHIER, &err);
if (err < 0)
goto err_release_irq;
/* Enable interrupt */
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, &err);
if (err < 0)
goto err_release_irq;
sdio_release_host(bdev->func);
return 0;
err_release_irq:
sdio_release_irq(bdev->func);
err_disable_func:
sdio_disable_func(bdev->func);
err_release_host:
sdio_release_host(bdev->func);
return err;
}
static int btmtksdio_close(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
u32 status;
int err;
sdio_claim_host(bdev->func);
/* Disable interrupt */
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
sdio_release_irq(bdev->func);
/* Return ownership to the device */
sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, NULL);
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
!(status & C_COM_DRV_OWN), 2000, 1000000);
if (err < 0)
bt_dev_err(bdev->hdev, "Cannot return ownership to device");
sdio_disable_func(bdev->func);
sdio_release_host(bdev->func);
return 0;
}
static int btmtksdio_flush(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
skb_queue_purge(&bdev->txq);
cancel_work_sync(&bdev->tx_work);
return 0;
}
static int btmtksdio_func_query(struct hci_dev *hdev)
{
struct btmtk_hci_wmt_params wmt_params;
int status, err;
u8 param = 0;
/* Query whether the function is enabled */
wmt_params.op = MTK_WMT_FUNC_CTRL;
wmt_params.flag = 4;
wmt_params.dlen = sizeof(param);
wmt_params.data = &param;
wmt_params.status = &status;
err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to query function status (%d)", err);
return err;
}
return status;
}
static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname)
{
struct btmtk_hci_wmt_params wmt_params;
const struct firmware *fw;
const u8 *fw_ptr;
size_t fw_size;
int err, dlen;
u8 flag;
err = request_firmware(&fw, fwname, &hdev->dev);
if (err < 0) {
bt_dev_err(hdev, "Failed to load firmware file (%d)", err);
return err;
}
fw_ptr = fw->data;
fw_size = fw->size;
/* The size of patch header is 30 bytes, should be skip */
if (fw_size < 30) {
err = -EINVAL;
goto free_fw;
}
fw_size -= 30;
fw_ptr += 30;
flag = 1;
wmt_params.op = MTK_WMT_PATCH_DWNLD;
wmt_params.status = NULL;
while (fw_size > 0) {
dlen = min_t(int, 250, fw_size);
/* Tell device the position in sequence */
if (fw_size - dlen <= 0)
flag = 3;
else if (fw_size < fw->size - 30)
flag = 2;
wmt_params.flag = flag;
wmt_params.dlen = dlen;
wmt_params.data = fw_ptr;
err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
err);
goto free_fw;
}
fw_size -= dlen;
fw_ptr += dlen;
}
wmt_params.op = MTK_WMT_RST;
wmt_params.flag = 4;
wmt_params.dlen = 0;
wmt_params.data = NULL;
wmt_params.status = NULL;
/* Activate funciton the firmware providing to */
err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
goto free_fw;
}
/* Wait a few moments for firmware activation done */
usleep_range(10000, 12000);
free_fw:
release_firmware(fw);
return err;
}
static int btmtksdio_setup(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
struct btmtk_hci_wmt_params wmt_params;
ktime_t calltime, delta, rettime;
struct btmtk_tci_sleep tci_sleep;
unsigned long long duration;
struct sk_buff *skb;
int err, status;
u8 param = 0x1;
calltime = ktime_get();
/* Query whether the firmware is already download */
wmt_params.op = MTK_WMT_SEMAPHORE;
wmt_params.flag = 1;
wmt_params.dlen = 0;
wmt_params.data = NULL;
wmt_params.status = &status;
err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
return err;
}
if (status == BTMTK_WMT_PATCH_DONE) {
bt_dev_info(hdev, "Firmware already downloaded");
goto ignore_setup_fw;
}
/* Setup a firmware which the device definitely requires */
err = mtk_setup_firmware(hdev, bdev->data->fwname);
if (err < 0)
return err;
ignore_setup_fw:
/* Query whether the device is already enabled */
err = readx_poll_timeout(btmtksdio_func_query, hdev, status,
status < 0 || status != BTMTK_WMT_ON_PROGRESS,
2000, 5000000);
/* -ETIMEDOUT happens */
if (err < 0)
return err;
/* The other errors happen in btusb_mtk_func_query */
if (status < 0)
return status;
if (status == BTMTK_WMT_ON_DONE) {
bt_dev_info(hdev, "function already on");
goto ignore_func_on;
}
/* Enable Bluetooth protocol */
wmt_params.op = MTK_WMT_FUNC_CTRL;
wmt_params.flag = 0;
wmt_params.dlen = sizeof(param);
wmt_params.data = &param;
wmt_params.status = NULL;
err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
return err;
}
ignore_func_on:
/* Apply the low power environment setup */
tci_sleep.mode = 0x5;
tci_sleep.duration = cpu_to_le16(0x640);
tci_sleep.host_duration = cpu_to_le16(0x640);
tci_sleep.host_wakeup_pin = 0;
tci_sleep.time_compensation = 0;
skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(hdev, "Failed to apply low power setting (%d)", err);
return err;
}
kfree_skb(skb);
rettime = ktime_get();
delta = ktime_sub(rettime, calltime);
duration = (unsigned long long)ktime_to_ns(delta) >> 10;
pm_runtime_set_autosuspend_delay(bdev->dev,
MTKBTSDIO_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(bdev->dev);
err = pm_runtime_set_active(bdev->dev);
if (err < 0)
return err;
/* Default forbid runtime auto suspend, that can be allowed by
* enable_autosuspend flag or the PM runtime entry under sysfs.
*/
pm_runtime_forbid(bdev->dev);
pm_runtime_enable(bdev->dev);
if (enable_autosuspend)
pm_runtime_allow(bdev->dev);
bt_dev_info(hdev, "Device setup in %llu usecs", duration);
return 0;
}
static int btmtksdio_shutdown(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
struct btmtk_hci_wmt_params wmt_params;
u8 param = 0x0;
int err;
/* Get back the state to be consistent with the state
* in btmtksdio_setup.
*/
pm_runtime_get_sync(bdev->dev);
/* Disable the device */
wmt_params.op = MTK_WMT_FUNC_CTRL;
wmt_params.flag = 0;
wmt_params.dlen = sizeof(param);
wmt_params.data = &param;
wmt_params.status = NULL;
err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
return err;
}
pm_runtime_put_noidle(bdev->dev);
pm_runtime_disable(bdev->dev);
return 0;
}
static int btmtksdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
switch (hci_skb_pkt_type(skb)) {
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;
default:
return -EILSEQ;
}
skb_queue_tail(&bdev->txq, skb);
schedule_work(&bdev->tx_work);
return 0;
}
static int btmtksdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
struct btmtksdio_dev *bdev;
struct hci_dev *hdev;
int err;
bdev = devm_kzalloc(&func->dev, sizeof(*bdev), GFP_KERNEL);
if (!bdev)
return -ENOMEM;
bdev->data = (void *)id->driver_data;
if (!bdev->data)
return -ENODEV;
bdev->dev = &func->dev;
bdev->func = func;
INIT_WORK(&bdev->tx_work, btmtksdio_tx_work);
skb_queue_head_init(&bdev->txq);
/* Initialize and register HCI device */
hdev = hci_alloc_dev();
if (!hdev) {
dev_err(&func->dev, "Can't allocate HCI device\n");
return -ENOMEM;
}
bdev->hdev = hdev;
hdev->bus = HCI_SDIO;
hci_set_drvdata(hdev, bdev);
hdev->open = btmtksdio_open;
hdev->close = btmtksdio_close;
hdev->flush = btmtksdio_flush;
hdev->setup = btmtksdio_setup;
hdev->shutdown = btmtksdio_shutdown;
hdev->send = btmtksdio_send_frame;
SET_HCIDEV_DEV(hdev, &func->dev);
hdev->manufacturer = 70;
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
err = hci_register_dev(hdev);
if (err < 0) {
dev_err(&func->dev, "Can't register HCI device\n");
hci_free_dev(hdev);
return err;
}
sdio_set_drvdata(func, bdev);
/* pm_runtime_enable would be done after the firmware is being
* downloaded because the core layer probably already enables
* runtime PM for this func such as the case host->caps &
* MMC_CAP_POWER_OFF_CARD.
*/
if (pm_runtime_enabled(bdev->dev))
pm_runtime_disable(bdev->dev);
/* As explaination in drivers/mmc/core/sdio_bus.c tells us:
* Unbound SDIO functions are always suspended.
* During probe, the function is set active and the usage count
* is incremented. If the driver supports runtime PM,
* it should call pm_runtime_put_noidle() in its probe routine and
* pm_runtime_get_noresume() in its remove routine.
*
* So, put a pm_runtime_put_noidle here !
*/
pm_runtime_put_noidle(bdev->dev);
return 0;
}
static void btmtksdio_remove(struct sdio_func *func)
{
struct btmtksdio_dev *bdev = sdio_get_drvdata(func);
struct hci_dev *hdev;
if (!bdev)
return;
/* Be consistent the state in btmtksdio_probe */
pm_runtime_get_noresume(bdev->dev);
hdev = bdev->hdev;
sdio_set_drvdata(func, NULL);
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
#ifdef CONFIG_PM
static int btmtksdio_runtime_suspend(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
struct btmtksdio_dev *bdev;
u32 status;
int err;
bdev = sdio_get_drvdata(func);
if (!bdev)
return 0;
sdio_claim_host(bdev->func);
sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, &err);
if (err < 0)
goto out;
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
!(status & C_COM_DRV_OWN), 2000, 1000000);
out:
bt_dev_info(bdev->hdev, "status (%d) return ownership to device", err);
sdio_release_host(bdev->func);
return err;
}
static int btmtksdio_runtime_resume(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
struct btmtksdio_dev *bdev;
u32 status;
int err;
bdev = sdio_get_drvdata(func);
if (!bdev)
return 0;
sdio_claim_host(bdev->func);
sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err);
if (err < 0)
goto out;
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
status & C_COM_DRV_OWN, 2000, 1000000);
out:
bt_dev_info(bdev->hdev, "status (%d) get ownership from device", err);
sdio_release_host(bdev->func);
return err;
}
static UNIVERSAL_DEV_PM_OPS(btmtksdio_pm_ops, btmtksdio_runtime_suspend,
btmtksdio_runtime_resume, NULL);
#define BTMTKSDIO_PM_OPS (&btmtksdio_pm_ops)
#else /* CONFIG_PM */
#define BTMTKSDIO_PM_OPS NULL
#endif /* CONFIG_PM */
static struct sdio_driver btmtksdio_driver = {
.name = "btmtksdio",
.probe = btmtksdio_probe,
.remove = btmtksdio_remove,
.id_table = btmtksdio_table,
.drv = {
.owner = THIS_MODULE,
.pm = BTMTKSDIO_PM_OPS,
}
};
module_sdio_driver(btmtksdio_driver);
module_param(enable_autosuspend, bool, 0644);
MODULE_PARM_DESC(enable_autosuspend, "Enable autosuspend by default");
MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
MODULE_DESCRIPTION("MediaTek Bluetooth SDIO driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_MT7663);
MODULE_FIRMWARE(FIRMWARE_MT7668);
...@@ -661,7 +661,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev) ...@@ -661,7 +661,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev)
{ {
struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
struct btmtk_hci_wmt_params wmt_params; struct btmtk_hci_wmt_params wmt_params;
u32 baudrate; __le32 baudrate;
u8 param; u8 param;
int err; int err;
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#define QCA_WCN3990_POWERON_PULSE 0xFC #define QCA_WCN3990_POWERON_PULSE 0xFC
#define QCA_WCN3990_POWEROFF_PULSE 0xC0 #define QCA_WCN3990_POWEROFF_PULSE 0xC0
enum qca_bardrate { enum qca_baudrate {
QCA_BAUDRATE_115200 = 0, QCA_BAUDRATE_115200 = 0,
QCA_BAUDRATE_57600, QCA_BAUDRATE_57600,
QCA_BAUDRATE_38400, QCA_BAUDRATE_38400,
......
...@@ -376,20 +376,7 @@ static struct sdio_driver btsdio_driver = { ...@@ -376,20 +376,7 @@ static struct sdio_driver btsdio_driver = {
.id_table = btsdio_table, .id_table = btsdio_table,
}; };
static int __init btsdio_init(void) module_sdio_driver(btsdio_driver);
{
BT_INFO("Generic Bluetooth SDIO driver ver %s", VERSION);
return sdio_register_driver(&btsdio_driver);
}
static void __exit btsdio_exit(void)
{
sdio_unregister_driver(&btsdio_driver);
}
module_init(btsdio_init);
module_exit(btsdio_exit);
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Generic Bluetooth SDIO driver ver " VERSION); MODULE_DESCRIPTION("Generic Bluetooth SDIO driver ver " VERSION);
......
...@@ -228,9 +228,15 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered) ...@@ -228,9 +228,15 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
int err; int err;
if (powered && !dev->res_enabled) { if (powered && !dev->res_enabled) {
err = regulator_bulk_enable(BCM_NUM_SUPPLIES, dev->supplies); /* Intel Macs use bcm_apple_get_resources() and don't
if (err) * have regulator supplies configured.
return err; */
if (dev->supplies[0].supply) {
err = regulator_bulk_enable(BCM_NUM_SUPPLIES,
dev->supplies);
if (err)
return err;
}
/* LPO clock needs to be 32.768 kHz */ /* LPO clock needs to be 32.768 kHz */
err = clk_set_rate(dev->lpo_clk, 32768); err = clk_set_rate(dev->lpo_clk, 32768);
...@@ -259,7 +265,13 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered) ...@@ -259,7 +265,13 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
if (!powered && dev->res_enabled) { if (!powered && dev->res_enabled) {
clk_disable_unprepare(dev->txco_clk); clk_disable_unprepare(dev->txco_clk);
clk_disable_unprepare(dev->lpo_clk); clk_disable_unprepare(dev->lpo_clk);
regulator_bulk_disable(BCM_NUM_SUPPLIES, dev->supplies);
/* Intel Macs use bcm_apple_get_resources() and don't
* have regulator supplies configured.
*/
if (dev->supplies[0].supply)
regulator_bulk_disable(BCM_NUM_SUPPLIES,
dev->supplies);
} }
/* wait for device to power on and come out of reset */ /* wait for device to power on and come out of reset */
......
...@@ -536,7 +536,7 @@ static void h5_unslip_one_byte(struct h5 *h5, unsigned char c) ...@@ -536,7 +536,7 @@ static void h5_unslip_one_byte(struct h5 *h5, unsigned char c)
skb_put_data(h5->rx_skb, byte, 1); skb_put_data(h5->rx_skb, byte, 1);
h5->rx_pending--; h5->rx_pending--;
BT_DBG("unsliped 0x%02hhx, rx_pending %zu", *byte, h5->rx_pending); BT_DBG("unslipped 0x%02hhx, rx_pending %zu", *byte, h5->rx_pending);
} }
static void h5_reset_rx(struct h5 *h5) static void h5_reset_rx(struct h5 *h5)
......
...@@ -174,6 +174,21 @@ static int qca_power_setup(struct hci_uart *hu, bool on); ...@@ -174,6 +174,21 @@ static int qca_power_setup(struct hci_uart *hu, bool on);
static void qca_power_shutdown(struct hci_uart *hu); static void qca_power_shutdown(struct hci_uart *hu);
static int qca_power_off(struct hci_dev *hdev); static int qca_power_off(struct hci_dev *hdev);
static enum qca_btsoc_type qca_soc_type(struct hci_uart *hu)
{
enum qca_btsoc_type soc_type;
if (hu->serdev) {
struct qca_serdev *qsd = serdev_device_get_drvdata(hu->serdev);
soc_type = qsd->btsoc_type;
} else {
soc_type = QCA_ROME;
}
return soc_type;
}
static void __serial_clock_on(struct tty_struct *tty) static void __serial_clock_on(struct tty_struct *tty)
{ {
/* TODO: Some chipset requires to enable UART clock on client /* TODO: Some chipset requires to enable UART clock on client
...@@ -508,6 +523,8 @@ static int qca_open(struct hci_uart *hu) ...@@ -508,6 +523,8 @@ static int qca_open(struct hci_uart *hu)
qcadev = serdev_device_get_drvdata(hu->serdev); qcadev = serdev_device_get_drvdata(hu->serdev);
if (qcadev->btsoc_type != QCA_WCN3990) { if (qcadev->btsoc_type != QCA_WCN3990) {
gpiod_set_value_cansleep(qcadev->bt_en, 1); gpiod_set_value_cansleep(qcadev->bt_en, 1);
/* Controller needs time to bootup. */
msleep(150);
} else { } else {
hu->init_speed = qcadev->init_speed; hu->init_speed = qcadev->init_speed;
hu->oper_speed = qcadev->oper_speed; hu->oper_speed = qcadev->oper_speed;
...@@ -963,7 +980,6 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) ...@@ -963,7 +980,6 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
{ {
struct hci_uart *hu = hci_get_drvdata(hdev); struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv; struct qca_data *qca = hu->priv;
struct qca_serdev *qcadev;
struct sk_buff *skb; struct sk_buff *skb;
u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 }; u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 };
...@@ -985,18 +1001,17 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) ...@@ -985,18 +1001,17 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
skb_queue_tail(&qca->txq, skb); skb_queue_tail(&qca->txq, skb);
hci_uart_tx_wakeup(hu); hci_uart_tx_wakeup(hu);
qcadev = serdev_device_get_drvdata(hu->serdev);
/* Wait for the baudrate change request to be sent */ /* Wait for the baudrate change request to be sent */
while (!skb_queue_empty(&qca->txq)) while (!skb_queue_empty(&qca->txq))
usleep_range(100, 200); usleep_range(100, 200);
serdev_device_wait_until_sent(hu->serdev, if (hu->serdev)
serdev_device_wait_until_sent(hu->serdev,
msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
/* Give the controller time to process the request */ /* Give the controller time to process the request */
if (qcadev->btsoc_type == QCA_WCN3990) if (qca_soc_type(hu) == QCA_WCN3990)
msleep(10); msleep(10);
else else
msleep(300); msleep(300);
...@@ -1072,10 +1087,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu, ...@@ -1072,10 +1087,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu,
static int qca_check_speeds(struct hci_uart *hu) static int qca_check_speeds(struct hci_uart *hu)
{ {
struct qca_serdev *qcadev; if (qca_soc_type(hu) == QCA_WCN3990) {
qcadev = serdev_device_get_drvdata(hu->serdev);
if (qcadev->btsoc_type == QCA_WCN3990) {
if (!qca_get_speed(hu, QCA_INIT_SPEED) && if (!qca_get_speed(hu, QCA_INIT_SPEED) &&
!qca_get_speed(hu, QCA_OPER_SPEED)) !qca_get_speed(hu, QCA_OPER_SPEED))
return -EINVAL; return -EINVAL;
...@@ -1091,7 +1103,6 @@ static int qca_check_speeds(struct hci_uart *hu) ...@@ -1091,7 +1103,6 @@ static int qca_check_speeds(struct hci_uart *hu)
static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
{ {
unsigned int speed, qca_baudrate; unsigned int speed, qca_baudrate;
struct qca_serdev *qcadev;
int ret = 0; int ret = 0;
if (speed_type == QCA_INIT_SPEED) { if (speed_type == QCA_INIT_SPEED) {
...@@ -1099,6 +1110,8 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) ...@@ -1099,6 +1110,8 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
if (speed) if (speed)
host_set_baudrate(hu, speed); host_set_baudrate(hu, speed);
} else { } else {
enum qca_btsoc_type soc_type = qca_soc_type(hu);
speed = qca_get_speed(hu, QCA_OPER_SPEED); speed = qca_get_speed(hu, QCA_OPER_SPEED);
if (!speed) if (!speed)
return 0; return 0;
...@@ -1106,8 +1119,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) ...@@ -1106,8 +1119,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
/* Disable flow control for wcn3990 to deassert RTS while /* Disable flow control for wcn3990 to deassert RTS while
* changing the baudrate of chip and host. * changing the baudrate of chip and host.
*/ */
qcadev = serdev_device_get_drvdata(hu->serdev); if (soc_type == QCA_WCN3990)
if (qcadev->btsoc_type == QCA_WCN3990)
hci_uart_set_flow_control(hu, true); hci_uart_set_flow_control(hu, true);
qca_baudrate = qca_get_baudrate_value(speed); qca_baudrate = qca_get_baudrate_value(speed);
...@@ -1119,7 +1131,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) ...@@ -1119,7 +1131,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
host_set_baudrate(hu, speed); host_set_baudrate(hu, speed);
error: error:
if (qcadev->btsoc_type == QCA_WCN3990) if (soc_type == QCA_WCN3990)
hci_uart_set_flow_control(hu, false); hci_uart_set_flow_control(hu, false);
} }
...@@ -1181,12 +1193,10 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1181,12 +1193,10 @@ static int qca_setup(struct hci_uart *hu)
struct hci_dev *hdev = hu->hdev; struct hci_dev *hdev = hu->hdev;
struct qca_data *qca = hu->priv; struct qca_data *qca = hu->priv;
unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200; unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200;
struct qca_serdev *qcadev; enum qca_btsoc_type soc_type = qca_soc_type(hu);
int ret; int ret;
int soc_ver = 0; int soc_ver = 0;
qcadev = serdev_device_get_drvdata(hu->serdev);
ret = qca_check_speeds(hu); ret = qca_check_speeds(hu);
if (ret) if (ret)
return ret; return ret;
...@@ -1194,7 +1204,7 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1194,7 +1204,7 @@ static int qca_setup(struct hci_uart *hu)
/* Patch downloading has to be done without IBS mode */ /* Patch downloading has to be done without IBS mode */
clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
if (qcadev->btsoc_type == QCA_WCN3990) { if (soc_type == QCA_WCN3990) {
bt_dev_info(hdev, "setting up wcn3990"); bt_dev_info(hdev, "setting up wcn3990");
/* Enable NON_PERSISTENT_SETUP QUIRK to ensure to execute /* Enable NON_PERSISTENT_SETUP QUIRK to ensure to execute
...@@ -1225,7 +1235,7 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1225,7 +1235,7 @@ static int qca_setup(struct hci_uart *hu)
qca_baudrate = qca_get_baudrate_value(speed); qca_baudrate = qca_get_baudrate_value(speed);
} }
if (qcadev->btsoc_type != QCA_WCN3990) { if (soc_type != QCA_WCN3990) {
/* Get QCA version information */ /* Get QCA version information */
ret = qca_read_soc_version(hdev, &soc_ver); ret = qca_read_soc_version(hdev, &soc_ver);
if (ret) if (ret)
...@@ -1234,7 +1244,7 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1234,7 +1244,7 @@ static int qca_setup(struct hci_uart *hu)
bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver); bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver);
/* Setup patch / NVM configurations */ /* Setup patch / NVM configurations */
ret = qca_uart_setup(hdev, qca_baudrate, qcadev->btsoc_type, soc_ver); ret = qca_uart_setup(hdev, qca_baudrate, soc_type, soc_ver);
if (!ret) { if (!ret) {
set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
qca_debugfs_init(hdev); qca_debugfs_init(hdev);
...@@ -1250,7 +1260,7 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1250,7 +1260,7 @@ static int qca_setup(struct hci_uart *hu)
} }
/* Setup bdaddr */ /* Setup bdaddr */
if (qcadev->btsoc_type == QCA_WCN3990) if (soc_type == QCA_WCN3990)
hu->hdev->set_bdaddr = qca_set_bdaddr; hu->hdev->set_bdaddr = qca_set_bdaddr;
else else
hu->hdev->set_bdaddr = qca_set_bdaddr_rome; hu->hdev->set_bdaddr = qca_set_bdaddr_rome;
......
...@@ -111,6 +111,18 @@ struct sdio_driver { ...@@ -111,6 +111,18 @@ struct sdio_driver {
extern int sdio_register_driver(struct sdio_driver *); extern int sdio_register_driver(struct sdio_driver *);
extern void sdio_unregister_driver(struct sdio_driver *); extern void sdio_unregister_driver(struct sdio_driver *);
/**
* module_sdio_driver() - Helper macro for registering a SDIO driver
* @__sdio_driver: sdio_driver struct
*
* Helper macro for SDIO drivers which do not do anything special in module
* init/exit. This eliminates a lot of boilerplate. Each module may only
* use this macro once, and calling it replaces module_init() and module_exit()
*/
#define module_sdio_driver(__sdio_driver) \
module_driver(__sdio_driver, sdio_register_driver, \
sdio_unregister_driver)
/* /*
* SDIO I/O operations * SDIO I/O operations
*/ */
......
...@@ -59,6 +59,8 @@ ...@@ -59,6 +59,8 @@
#define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128 #define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128
#define SDIO_DEVICE_ID_MARVELL_8887WLAN 0x9134 #define SDIO_DEVICE_ID_MARVELL_8887WLAN 0x9134
#define SDIO_VENDOR_ID_MEDIATEK 0x037a
#define SDIO_VENDOR_ID_SIANO 0x039a #define SDIO_VENDOR_ID_SIANO 0x039a
#define SDIO_DEVICE_ID_SIANO_NOVA_B0 0x0201 #define SDIO_DEVICE_ID_SIANO_NOVA_B0 0x0201
#define SDIO_DEVICE_ID_SIANO_NICE 0x0202 #define SDIO_DEVICE_ID_SIANO_NICE 0x0202
......
...@@ -190,6 +190,9 @@ struct adv_info { ...@@ -190,6 +190,9 @@ struct adv_info {
#define HCI_MAX_SHORT_NAME_LENGTH 10 #define HCI_MAX_SHORT_NAME_LENGTH 10
/* Min encryption key size to match with SMP */
#define HCI_MIN_ENC_KEY_SIZE 7
/* Default LE RPA expiry time, 15 minutes */ /* Default LE RPA expiry time, 15 minutes */
#define HCI_DEFAULT_RPA_TIMEOUT (15 * 60) #define HCI_DEFAULT_RPA_TIMEOUT (15 * 60)
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include "nhc.h" #include "nhc.h"
static struct rb_root rb_root = RB_ROOT; static struct rb_root rb_root = RB_ROOT;
static struct lowpan_nhc *lowpan_nexthdr_nhcs[NEXTHDR_MAX]; static struct lowpan_nhc *lowpan_nexthdr_nhcs[NEXTHDR_MAX + 1];
static DEFINE_SPINLOCK(lowpan_nhc_lock); static DEFINE_SPINLOCK(lowpan_nhc_lock);
static int lowpan_nhc_insert(struct lowpan_nhc *nhc) static int lowpan_nhc_insert(struct lowpan_nhc *nhc)
......
...@@ -1276,6 +1276,14 @@ int hci_conn_check_link_mode(struct hci_conn *conn) ...@@ -1276,6 +1276,14 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
!test_bit(HCI_CONN_ENCRYPT, &conn->flags)) !test_bit(HCI_CONN_ENCRYPT, &conn->flags))
return 0; return 0;
/* The minimum encryption key size needs to be enforced by the
* host stack before establishing any L2CAP connections. The
* specification in theory allows a minimum of 1, but to align
* BR/EDR and LE transports, a minimum of 7 is chosen.
*/
if (conn->enc_key_size < HCI_MIN_ENC_KEY_SIZE)
return 0;
return 1; return 1;
} }
......
...@@ -1460,8 +1460,6 @@ static int hci_dev_do_open(struct hci_dev *hdev) ...@@ -1460,8 +1460,6 @@ static int hci_dev_do_open(struct hci_dev *hdev)
hdev->set_bdaddr) hdev->set_bdaddr)
ret = hdev->set_bdaddr(hdev, ret = hdev->set_bdaddr(hdev,
&hdev->public_addr); &hdev->public_addr);
else
ret = -EADDRNOTAVAIL;
} }
setup_failed: setup_failed:
......
...@@ -5433,7 +5433,7 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -5433,7 +5433,7 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
ev->data, ev->length); ev->data, ev->length);
} }
ptr += sizeof(*ev) + ev->length + 1; ptr += sizeof(*ev) + ev->length;
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
......
...@@ -75,6 +75,7 @@ static int do_hidp_sock_ioctl(struct socket *sock, unsigned int cmd, void __user ...@@ -75,6 +75,7 @@ static int do_hidp_sock_ioctl(struct socket *sock, unsigned int cmd, void __user
sockfd_put(csock); sockfd_put(csock);
return err; return err;
} }
ca.name[sizeof(ca.name)-1] = 0;
err = hidp_connection_add(&ca, csock, isock); err = hidp_connection_add(&ca, csock, isock);
if (!err && copy_to_user(argp, &ca, sizeof(ca))) if (!err && copy_to_user(argp, &ca, sizeof(ca)))
......
...@@ -510,12 +510,12 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan) ...@@ -510,12 +510,12 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
} }
EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults); EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
static void l2cap_le_flowctl_init(struct l2cap_chan *chan) static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
{ {
chan->sdu = NULL; chan->sdu = NULL;
chan->sdu_last_frag = NULL; chan->sdu_last_frag = NULL;
chan->sdu_len = 0; chan->sdu_len = 0;
chan->tx_credits = 0; chan->tx_credits = tx_credits;
/* Derive MPS from connection MTU to stop HCI fragmentation */ /* Derive MPS from connection MTU to stop HCI fragmentation */
chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE); chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
/* Give enough credits for a full packet */ /* Give enough credits for a full packet */
...@@ -1281,7 +1281,7 @@ static void l2cap_le_connect(struct l2cap_chan *chan) ...@@ -1281,7 +1281,7 @@ static void l2cap_le_connect(struct l2cap_chan *chan)
if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
return; return;
l2cap_le_flowctl_init(chan); l2cap_le_flowctl_init(chan, 0);
req.psm = chan->psm; req.psm = chan->psm;
req.scid = cpu_to_le16(chan->scid); req.scid = cpu_to_le16(chan->scid);
...@@ -5532,11 +5532,10 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, ...@@ -5532,11 +5532,10 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
chan->dcid = scid; chan->dcid = scid;
chan->omtu = mtu; chan->omtu = mtu;
chan->remote_mps = mps; chan->remote_mps = mps;
chan->tx_credits = __le16_to_cpu(req->credits);
__l2cap_chan_add(conn, chan); __l2cap_chan_add(conn, chan);
l2cap_le_flowctl_init(chan); l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
dcid = chan->scid; dcid = chan->scid;
credits = chan->rx_credits; credits = chan->rx_credits;
......
...@@ -791,10 +791,13 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -791,10 +791,13 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
conn = chan->conn; conn = chan->conn;
/*change security for LE channels */ /* change security for LE channels */
if (chan->scid == L2CAP_CID_ATT) { if (chan->scid == L2CAP_CID_ATT) {
if (smp_conn_security(conn->hcon, sec.level)) if (smp_conn_security(conn->hcon, sec.level)) {
err = -EINVAL;
break; break;
}
set_bit(FLAG_PENDING_SECURITY, &chan->flags); set_bit(FLAG_PENDING_SECURITY, &chan->flags);
sk->sk_state = BT_CONFIG; sk->sk_state = BT_CONFIG;
chan->state = BT_CONFIG; chan->state = BT_CONFIG;
......
...@@ -2301,8 +2301,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2301,8 +2301,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
expected_len = sizeof(*cp) + key_count * expected_len = struct_size(cp, keys, key_count);
sizeof(struct mgmt_link_key_info);
if (expected_len != len) { if (expected_len != len) {
bt_dev_err(hdev, "load_link_keys: expected %u bytes, got %u bytes", bt_dev_err(hdev, "load_link_keys: expected %u bytes, got %u bytes",
expected_len, len); expected_len, len);
...@@ -5030,7 +5029,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, ...@@ -5030,7 +5029,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info); expected_len = struct_size(cp, irks, irk_count);
if (expected_len != len) { if (expected_len != len) {
bt_dev_err(hdev, "load_irks: expected %u bytes, got %u bytes", bt_dev_err(hdev, "load_irks: expected %u bytes, got %u bytes",
expected_len, len); expected_len, len);
...@@ -5112,8 +5111,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, ...@@ -5112,8 +5111,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
expected_len = sizeof(*cp) + key_count * expected_len = struct_size(cp, keys, key_count);
sizeof(struct mgmt_ltk_info);
if (expected_len != len) { if (expected_len != len) {
bt_dev_err(hdev, "load_keys: expected %u bytes, got %u bytes", bt_dev_err(hdev, "load_keys: expected %u bytes, got %u bytes",
expected_len, len); expected_len, len);
...@@ -5847,8 +5845,7 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5847,8 +5845,7 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
} }
expected_len = sizeof(*cp) + param_count * expected_len = struct_size(cp, params, param_count);
sizeof(struct mgmt_conn_param);
if (expected_len != len) { if (expected_len != len) {
bt_dev_err(hdev, "load_conn_param: expected %u bytes, got %u bytes", bt_dev_err(hdev, "load_conn_param: expected %u bytes, got %u bytes",
expected_len, len); expected_len, len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment