Commit 19ab5f40 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-05-05

Here's one more bluetooth-next pull request for 5.2:

 - Fixed Command Complete event handling check for matching opcode
 - Added support for Qualcomm WCN3998 controller, along with DT bindings
 - Added default address for Broadcom BCM2076B1 controllers

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d1f5050b 62a91990
...@@ -11,20 +11,21 @@ Required properties: ...@@ -11,20 +11,21 @@ Required properties:
- compatible: should contain one of the following: - compatible: should contain one of the following:
* "qcom,qca6174-bt" * "qcom,qca6174-bt"
* "qcom,wcn3990-bt" * "qcom,wcn3990-bt"
* "qcom,wcn3998-bt"
Optional properties for compatible string qcom,qca6174-bt: Optional properties for compatible string qcom,qca6174-bt:
- enable-gpios: gpio specifier used to enable chip - enable-gpios: gpio specifier used to enable chip
- clocks: clock provided to the controller (SUSCLK_32KHZ) - clocks: clock provided to the controller (SUSCLK_32KHZ)
Required properties for compatible string qcom,wcn3990-bt: Required properties for compatible string qcom,wcn399x-bt:
- vddio-supply: VDD_IO supply regulator handle. - vddio-supply: VDD_IO supply regulator handle.
- vddxo-supply: VDD_XO supply regulator handle. - vddxo-supply: VDD_XO supply regulator handle.
- vddrf-supply: VDD_RF supply regulator handle. - vddrf-supply: VDD_RF supply regulator handle.
- vddch0-supply: VDD_CH0 supply regulator handle. - vddch0-supply: VDD_CH0 supply regulator handle.
Optional properties for compatible string qcom,wcn3990-bt: Optional properties for compatible string qcom,wcn399x-bt:
- max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt - max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) #define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
#define BDADDR_BCM20702A1 (&(bdaddr_t) {{0x00, 0x00, 0xa0, 0x02, 0x70, 0x20}}) #define BDADDR_BCM20702A1 (&(bdaddr_t) {{0x00, 0x00, 0xa0, 0x02, 0x70, 0x20}})
#define BDADDR_BCM2076B1 (&(bdaddr_t) {{0x79, 0x56, 0x00, 0xa0, 0x76, 0x20}})
#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}})
...@@ -70,6 +71,9 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) ...@@ -70,6 +71,9 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
* The address 20:70:02:A0:00:00 indicates a BCM20702A1 controller * The address 20:70:02:A0:00:00 indicates a BCM20702A1 controller
* with no configured address. * with no configured address.
* *
* The address 20:76:A0:00:56:79 indicates a BCM2076B1 controller
* with no configured address.
*
* The address 43:24:B3:00:00:00 indicates a BCM4324B3 controller * The address 43:24:B3:00:00:00 indicates a BCM4324B3 controller
* with waiting for configuration state. * with waiting for configuration state.
* *
...@@ -81,6 +85,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) ...@@ -81,6 +85,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
*/ */
if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) || if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM20702A1) || !bacmp(&bda->bdaddr, BDADDR_BCM20702A1) ||
!bacmp(&bda->bdaddr, BDADDR_BCM2076B1) ||
!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) ||
......
...@@ -336,7 +336,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, ...@@ -336,7 +336,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
{ {
struct rome_config config; struct rome_config config;
int err; int err;
u8 rom_ver; u8 rom_ver = 0;
bt_dev_dbg(hdev, "QCA setup on UART"); bt_dev_dbg(hdev, "QCA setup on UART");
...@@ -344,7 +344,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, ...@@ -344,7 +344,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
/* Download rampatch file */ /* Download rampatch file */
config.type = TLV_TYPE_PATCH; config.type = TLV_TYPE_PATCH;
if (soc_type == QCA_WCN3990) { if (qca_is_wcn399x(soc_type)) {
/* Firmware files to download are based on ROM version. /* Firmware files to download are based on ROM version.
* ROM version is derived from last two bytes of soc_ver. * ROM version is derived from last two bytes of soc_ver.
*/ */
...@@ -365,7 +365,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, ...@@ -365,7 +365,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
/* Download NVM configuration */ /* Download NVM configuration */
config.type = TLV_TYPE_NVM; config.type = TLV_TYPE_NVM;
if (soc_type == QCA_WCN3990) if (qca_is_wcn399x(soc_type))
snprintf(config.fwname, sizeof(config.fwname), snprintf(config.fwname, sizeof(config.fwname),
"qca/crnv%02x.bin", rom_ver); "qca/crnv%02x.bin", rom_ver);
else else
...@@ -410,6 +410,7 @@ int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) ...@@ -410,6 +410,7 @@ int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
} }
EXPORT_SYMBOL_GPL(qca_set_bdaddr); EXPORT_SYMBOL_GPL(qca_set_bdaddr);
MODULE_AUTHOR("Ben Young Tae Kim <ytkim@qca.qualcomm.com>"); MODULE_AUTHOR("Ben Young Tae Kim <ytkim@qca.qualcomm.com>");
MODULE_DESCRIPTION("Bluetooth support for Qualcomm Atheros family ver " VERSION); MODULE_DESCRIPTION("Bluetooth support for Qualcomm Atheros family ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
......
...@@ -132,7 +132,8 @@ enum qca_btsoc_type { ...@@ -132,7 +132,8 @@ enum qca_btsoc_type {
QCA_INVALID = -1, QCA_INVALID = -1,
QCA_AR3002, QCA_AR3002,
QCA_ROME, QCA_ROME,
QCA_WCN3990 QCA_WCN3990,
QCA_WCN3998,
}; };
#if IS_ENABLED(CONFIG_BT_QCA) #if IS_ENABLED(CONFIG_BT_QCA)
...@@ -142,6 +143,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, ...@@ -142,6 +143,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
enum qca_btsoc_type soc_type, u32 soc_ver); enum qca_btsoc_type soc_type, u32 soc_ver);
int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version); int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version);
int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
{
return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3998;
}
#else #else
static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
...@@ -165,4 +170,8 @@ static inline int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) ...@@ -165,4 +170,8 @@ static inline int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
{
return false;
}
#endif #endif
...@@ -54,9 +54,6 @@ ...@@ -54,9 +54,6 @@
#define HCI_IBS_WAKE_ACK 0xFC #define HCI_IBS_WAKE_ACK 0xFC
#define HCI_MAX_IBS_SIZE 10 #define HCI_MAX_IBS_SIZE 10
/* Controller states */
#define STATE_IN_BAND_SLEEP_ENABLED 1
#define IBS_WAKE_RETRANS_TIMEOUT_MS 100 #define IBS_WAKE_RETRANS_TIMEOUT_MS 100
#define IBS_TX_IDLE_TIMEOUT_MS 2000 #define IBS_TX_IDLE_TIMEOUT_MS 2000
#define CMD_TRANS_TIMEOUT_MS 100 #define CMD_TRANS_TIMEOUT_MS 100
...@@ -67,6 +64,10 @@ ...@@ -67,6 +64,10 @@
/* Controller debug log header */ /* Controller debug log header */
#define QCA_DEBUG_HANDLE 0x2EDC #define QCA_DEBUG_HANDLE 0x2EDC
enum qca_flags {
QCA_IBS_ENABLED,
};
/* HCI_IBS transmit side sleep protocol states */ /* HCI_IBS transmit side sleep protocol states */
enum tx_ibs_states { enum tx_ibs_states {
HCI_IBS_TX_ASLEEP, HCI_IBS_TX_ASLEEP,
...@@ -521,7 +522,7 @@ static int qca_open(struct hci_uart *hu) ...@@ -521,7 +522,7 @@ static int qca_open(struct hci_uart *hu)
if (hu->serdev) { if (hu->serdev) {
qcadev = serdev_device_get_drvdata(hu->serdev); qcadev = serdev_device_get_drvdata(hu->serdev);
if (qcadev->btsoc_type != QCA_WCN3990) { if (!qca_is_wcn399x(qcadev->btsoc_type)) {
gpiod_set_value_cansleep(qcadev->bt_en, 1); gpiod_set_value_cansleep(qcadev->bt_en, 1);
/* Controller needs time to bootup. */ /* Controller needs time to bootup. */
msleep(150); msleep(150);
...@@ -629,7 +630,7 @@ static int qca_close(struct hci_uart *hu) ...@@ -629,7 +630,7 @@ static int qca_close(struct hci_uart *hu)
if (hu->serdev) { if (hu->serdev) {
qcadev = serdev_device_get_drvdata(hu->serdev); qcadev = serdev_device_get_drvdata(hu->serdev);
if (qcadev->btsoc_type == QCA_WCN3990) if (qca_is_wcn399x(qcadev->btsoc_type))
qca_power_shutdown(hu); qca_power_shutdown(hu);
else else
gpiod_set_value_cansleep(qcadev->bt_en, 0); gpiod_set_value_cansleep(qcadev->bt_en, 0);
...@@ -792,7 +793,7 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb) ...@@ -792,7 +793,7 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb)
/* Don't go to sleep in middle of patch download or /* Don't go to sleep in middle of patch download or
* Out-Of-Band(GPIOs control) sleep is selected. * Out-Of-Band(GPIOs control) sleep is selected.
*/ */
if (!test_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags)) { if (!test_bit(QCA_IBS_ENABLED, &qca->flags)) {
skb_queue_tail(&qca->txq, skb); skb_queue_tail(&qca->txq, skb);
spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
return 0; return 0;
...@@ -1011,7 +1012,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) ...@@ -1011,7 +1012,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
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 (qca_soc_type(hu) == QCA_WCN3990) if (qca_is_wcn399x(qca_soc_type(hu)))
msleep(10); msleep(10);
else else
msleep(300); msleep(300);
...@@ -1087,7 +1088,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu, ...@@ -1087,7 +1088,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)
{ {
if (qca_soc_type(hu) == QCA_WCN3990) { if (qca_is_wcn399x(qca_soc_type(hu))) {
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;
...@@ -1119,7 +1120,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) ...@@ -1119,7 +1120,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.
*/ */
if (soc_type == QCA_WCN3990) if (qca_is_wcn399x(soc_type))
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);
...@@ -1131,7 +1132,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) ...@@ -1131,7 +1132,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 (soc_type == QCA_WCN3990) if (qca_is_wcn399x(soc_type))
hci_uart_set_flow_control(hu, false); hci_uart_set_flow_control(hu, false);
} }
...@@ -1202,9 +1203,9 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1202,9 +1203,9 @@ static int qca_setup(struct hci_uart *hu)
return ret; return ret;
/* 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(QCA_IBS_ENABLED, &qca->flags);
if (soc_type == QCA_WCN3990) { if (qca_is_wcn399x(soc_type)) {
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
...@@ -1235,7 +1236,7 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1235,7 +1236,7 @@ static int qca_setup(struct hci_uart *hu)
qca_baudrate = qca_get_baudrate_value(speed); qca_baudrate = qca_get_baudrate_value(speed);
} }
if (soc_type != QCA_WCN3990) { if (!qca_is_wcn399x(soc_type)) {
/* 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)
...@@ -1246,7 +1247,7 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1246,7 +1247,7 @@ static int qca_setup(struct hci_uart *hu)
/* Setup patch / NVM configurations */ /* Setup patch / NVM configurations */
ret = qca_uart_setup(hdev, qca_baudrate, soc_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(QCA_IBS_ENABLED, &qca->flags);
qca_debugfs_init(hdev); qca_debugfs_init(hdev);
} else if (ret == -ENOENT) { } else if (ret == -ENOENT) {
/* No patch/nvm-config found, run with original fw/config */ /* No patch/nvm-config found, run with original fw/config */
...@@ -1260,7 +1261,7 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1260,7 +1261,7 @@ static int qca_setup(struct hci_uart *hu)
} }
/* Setup bdaddr */ /* Setup bdaddr */
if (soc_type == QCA_WCN3990) if (qca_is_wcn399x(soc_type))
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;
...@@ -1283,7 +1284,7 @@ static struct hci_uart_proto qca_proto = { ...@@ -1283,7 +1284,7 @@ static struct hci_uart_proto qca_proto = {
.dequeue = qca_dequeue, .dequeue = qca_dequeue,
}; };
static const struct qca_vreg_data qca_soc_data = { static const struct qca_vreg_data qca_soc_data_wcn3990 = {
.soc_type = QCA_WCN3990, .soc_type = QCA_WCN3990,
.vregs = (struct qca_vreg []) { .vregs = (struct qca_vreg []) {
{ "vddio", 1800000, 1900000, 15000 }, { "vddio", 1800000, 1900000, 15000 },
...@@ -1294,6 +1295,17 @@ static const struct qca_vreg_data qca_soc_data = { ...@@ -1294,6 +1295,17 @@ static const struct qca_vreg_data qca_soc_data = {
.num_vregs = 4, .num_vregs = 4,
}; };
static const struct qca_vreg_data qca_soc_data_wcn3998 = {
.soc_type = QCA_WCN3998,
.vregs = (struct qca_vreg []) {
{ "vddio", 1800000, 1900000, 10000 },
{ "vddxo", 1800000, 1900000, 80000 },
{ "vddrf", 1300000, 1352000, 300000 },
{ "vddch0", 3300000, 3300000, 450000 },
},
.num_vregs = 4,
};
static void qca_power_shutdown(struct hci_uart *hu) static void qca_power_shutdown(struct hci_uart *hu)
{ {
struct qca_data *qca = hu->priv; struct qca_data *qca = hu->priv;
...@@ -1304,7 +1316,7 @@ static void qca_power_shutdown(struct hci_uart *hu) ...@@ -1304,7 +1316,7 @@ static void qca_power_shutdown(struct hci_uart *hu)
* data in skb's. * data in skb's.
*/ */
spin_lock_irqsave(&qca->hci_ibs_lock, flags); spin_lock_irqsave(&qca->hci_ibs_lock, flags);
clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); clear_bit(QCA_IBS_ENABLED, &qca->flags);
qca_flush(hu); qca_flush(hu);
spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
...@@ -1427,8 +1439,8 @@ static int qca_serdev_probe(struct serdev_device *serdev) ...@@ -1427,8 +1439,8 @@ static int qca_serdev_probe(struct serdev_device *serdev)
qcadev->serdev_hu.serdev = serdev; qcadev->serdev_hu.serdev = serdev;
data = of_device_get_match_data(&serdev->dev); data = of_device_get_match_data(&serdev->dev);
serdev_device_set_drvdata(serdev, qcadev); serdev_device_set_drvdata(serdev, qcadev);
if (data && data->soc_type == QCA_WCN3990) { if (data && qca_is_wcn399x(data->soc_type)) {
qcadev->btsoc_type = QCA_WCN3990; qcadev->btsoc_type = data->soc_type;
qcadev->bt_power = devm_kzalloc(&serdev->dev, qcadev->bt_power = devm_kzalloc(&serdev->dev,
sizeof(struct qca_power), sizeof(struct qca_power),
GFP_KERNEL); GFP_KERNEL);
...@@ -1492,7 +1504,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) ...@@ -1492,7 +1504,7 @@ static void qca_serdev_remove(struct serdev_device *serdev)
{ {
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
if (qcadev->btsoc_type == QCA_WCN3990) if (qca_is_wcn399x(qcadev->btsoc_type))
qca_power_shutdown(&qcadev->serdev_hu); qca_power_shutdown(&qcadev->serdev_hu);
else else
clk_disable_unprepare(qcadev->susclk); clk_disable_unprepare(qcadev->susclk);
...@@ -1502,7 +1514,8 @@ static void qca_serdev_remove(struct serdev_device *serdev) ...@@ -1502,7 +1514,8 @@ static void qca_serdev_remove(struct serdev_device *serdev)
static const struct of_device_id qca_bluetooth_of_match[] = { static const struct of_device_id qca_bluetooth_of_match[] = {
{ .compatible = "qcom,qca6174-bt" }, { .compatible = "qcom,qca6174-bt" },
{ .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data}, { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990},
{ .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998},
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match);
......
...@@ -282,6 +282,7 @@ enum { ...@@ -282,6 +282,7 @@ enum {
HCI_FORCE_BREDR_SMP, HCI_FORCE_BREDR_SMP,
HCI_FORCE_STATIC_ADDR, HCI_FORCE_STATIC_ADDR,
HCI_LL_RPA_RESOLUTION, HCI_LL_RPA_RESOLUTION,
HCI_CMD_PENDING,
__HCI_NUM_FLAGS, __HCI_NUM_FLAGS,
}; };
......
...@@ -4381,6 +4381,9 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status, ...@@ -4381,6 +4381,9 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
return; return;
} }
/* If we reach this point this event matches the last command sent */
hci_dev_clear_flag(hdev, HCI_CMD_PENDING);
/* If the command succeeded and there's still more commands in /* If the command succeeded and there's still more commands in
* this request the request is not yet complete. * this request the request is not yet complete.
*/ */
...@@ -4491,6 +4494,8 @@ static void hci_cmd_work(struct work_struct *work) ...@@ -4491,6 +4494,8 @@ static void hci_cmd_work(struct work_struct *work)
hdev->sent_cmd = skb_clone(skb, GFP_KERNEL); hdev->sent_cmd = skb_clone(skb, GFP_KERNEL);
if (hdev->sent_cmd) { if (hdev->sent_cmd) {
if (hci_req_status_pend(hdev))
hci_dev_set_flag(hdev, HCI_CMD_PENDING);
atomic_dec(&hdev->cmd_cnt); atomic_dec(&hdev->cmd_cnt);
hci_send_frame(hdev, skb); hci_send_frame(hdev, skb);
if (test_bit(HCI_RESET, &hdev->flags)) if (test_bit(HCI_RESET, &hdev->flags))
......
...@@ -3404,6 +3404,12 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, ...@@ -3404,6 +3404,12 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
hci_req_cmd_complete(hdev, *opcode, *status, req_complete, hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
req_complete_skb); req_complete_skb);
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
bt_dev_err(hdev,
"unexpected event for opcode 0x%4.4x", *opcode);
return;
}
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q)) if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
queue_work(hdev->workqueue, &hdev->cmd_work); queue_work(hdev->workqueue, &hdev->cmd_work);
} }
...@@ -3511,6 +3517,12 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb, ...@@ -3511,6 +3517,12 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete, hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
req_complete_skb); req_complete_skb);
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
bt_dev_err(hdev,
"unexpected event for opcode 0x%4.4x", *opcode);
return;
}
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q)) if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
queue_work(hdev->workqueue, &hdev->cmd_work); queue_work(hdev->workqueue, &hdev->cmd_work);
} }
......
...@@ -46,6 +46,11 @@ void hci_req_purge(struct hci_request *req) ...@@ -46,6 +46,11 @@ void hci_req_purge(struct hci_request *req)
skb_queue_purge(&req->cmd_q); skb_queue_purge(&req->cmd_q);
} }
bool hci_req_status_pend(struct hci_dev *hdev)
{
return hdev->req_status == HCI_REQ_PEND;
}
static int req_run(struct hci_request *req, hci_req_complete_t complete, static int req_run(struct hci_request *req, hci_req_complete_t complete,
hci_req_complete_skb_t complete_skb) hci_req_complete_skb_t complete_skb)
{ {
......
...@@ -37,6 +37,7 @@ struct hci_request { ...@@ -37,6 +37,7 @@ struct hci_request {
void hci_req_init(struct hci_request *req, struct hci_dev *hdev); void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
void hci_req_purge(struct hci_request *req); void hci_req_purge(struct hci_request *req);
bool hci_req_status_pend(struct hci_dev *hdev);
int hci_req_run(struct hci_request *req, hci_req_complete_t complete); int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
int hci_req_run_skb(struct hci_request *req, hci_req_complete_skb_t complete); int hci_req_run_skb(struct hci_request *req, hci_req_complete_skb_t complete);
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,
......
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