summaryrefslogtreecommitdiff
path: root/drivers/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/btintel_pcie.c3
-rw-r--r--drivers/bluetooth/btmtksdio.c8
-rw-r--r--drivers/bluetooth/btnxpuart.c6
-rw-r--r--drivers/bluetooth/btqca.c58
-rw-r--r--drivers/bluetooth/btusb.c26
-rw-r--r--drivers/bluetooth/hci_bcm4377.c11
-rw-r--r--drivers/bluetooth/hci_intel.c10
-rw-r--r--drivers/bluetooth/hci_qca.c52
8 files changed, 109 insertions, 65 deletions
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 704767b334b9..eaf5de46a702 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -1190,8 +1190,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
skb = NULL; /* skb is freed in the callee */
exit_error:
- if (skb)
- kfree_skb(skb);
+ kfree_skb(skb);
if (ret)
hdev->stat.err_rx++;
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index fba3ab6d30a5..e986e5af51ae 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -1472,7 +1472,6 @@ static void btmtksdio_remove(struct sdio_func *func)
hci_free_dev(hdev);
}
-#ifdef CONFIG_PM
static int btmtksdio_runtime_suspend(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
@@ -1542,18 +1541,13 @@ static const struct dev_pm_ops btmtksdio_pm_ops = {
RUNTIME_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 = {
- .pm = BTMTKSDIO_PM_OPS,
+ .pm = pm_ptr(&btmtksdio_pm_ops),
}
};
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 3b1e9224e965..e7036a48ce48 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -1947,8 +1947,7 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
hci_free_dev(hdev);
}
-#ifdef CONFIG_PM_SLEEP
-static int nxp_serdev_suspend(struct device *dev)
+static int __maybe_unused nxp_serdev_suspend(struct device *dev)
{
struct btnxpuart_dev *nxpdev = dev_get_drvdata(dev);
struct ps_data *psdata = &nxpdev->psdata;
@@ -1962,7 +1961,7 @@ static int nxp_serdev_suspend(struct device *dev)
return 0;
}
-static int nxp_serdev_resume(struct device *dev)
+static int __maybe_unused nxp_serdev_resume(struct device *dev)
{
struct btnxpuart_dev *nxpdev = dev_get_drvdata(dev);
struct ps_data *psdata = &nxpdev->psdata;
@@ -1975,7 +1974,6 @@ static int nxp_serdev_resume(struct device *dev)
ps_control(psdata->hdev, PS_STATE_AWAKE);
return 0;
}
-#endif
#ifdef CONFIG_DEV_COREDUMP
static void nxp_serdev_coredump(struct device *dev)
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index 7c958d6065be..74f820e89655 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -581,28 +581,11 @@ static int qca_download_firmware(struct hci_dev *hdev,
ret = request_firmware(&fw, config->fwname, &hdev->dev);
if (ret) {
- /* For WCN6750, if mbn file is not present then check for
- * tlv file.
- */
- if (soc_type == QCA_WCN6750 && config->type == ELF_TYPE_PATCH) {
- bt_dev_dbg(hdev, "QCA Failed to request file: %s (%d)",
- config->fwname, ret);
- config->type = TLV_TYPE_PATCH;
- snprintf(config->fwname, sizeof(config->fwname),
- "qca/msbtfw%02x.tlv", rom_ver);
- bt_dev_info(hdev, "QCA Downloading %s", config->fwname);
- ret = request_firmware(&fw, config->fwname, &hdev->dev);
- if (ret) {
- bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
- config->fwname, ret);
- return ret;
- }
- }
/* If the board-specific file is missing, try loading the default
* one, unless that was attempted already.
*/
- else if (config->type == TLV_TYPE_NVM &&
- qca_get_alt_nvm_file(config->fwname, sizeof(config->fwname))) {
+ if (config->type == TLV_TYPE_NVM &&
+ qca_get_alt_nvm_file(config->fwname, sizeof(config->fwname))) {
bt_dev_info(hdev, "QCA Downloading %s", config->fwname);
ret = request_firmware(&fw, config->fwname, &hdev->dev);
if (ret) {
@@ -847,8 +830,12 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
"qca/msbtfw%02x.mbn", rom_ver);
break;
case QCA_WCN6855:
+ /* Due to historical reasons, WCN685x chip has been using firmware
+ * without the "wcn" prefix. The mapping between the chip and its
+ * corresponding firmware has now been corrected.
+ */
snprintf(config.fwname, sizeof(config.fwname),
- "qca/hpbtfw%02x.tlv", rom_ver);
+ "qca/wcnhpbtfw%02x.tlv", rom_ver);
break;
case QCA_WCN7850:
snprintf(config.fwname, sizeof(config.fwname),
@@ -861,8 +848,26 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
}
err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
+ /* For WCN6750, if mbn file is not present then check for
+ * tlv file.
+ */
+ if (err < 0 && soc_type == QCA_WCN6750) {
+ bt_dev_dbg(hdev, "QCA Failed to request file: %s (%d)",
+ config.fwname, err);
+ config.type = TLV_TYPE_PATCH;
+ snprintf(config.fwname, sizeof(config.fwname),
+ "qca/msbtfw%02x.tlv", rom_ver);
+ bt_dev_info(hdev, "QCA Downloading %s", config.fwname);
+ err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
+ } else if (err < 0 && !rampatch_name && soc_type == QCA_WCN6855) {
+ snprintf(config.fwname, sizeof(config.fwname),
+ "qca/hpbtfw%02x.tlv", rom_ver);
+ err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
+ }
+
if (err < 0) {
- bt_dev_err(hdev, "QCA Failed to download patch (%d)", err);
+ bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
+ config.fwname, err);
return err;
}
@@ -923,7 +928,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
case QCA_WCN6855:
qca_read_fw_board_id(hdev, &boardid);
qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
- "hpnv", soc_type, ver, rom_ver, boardid);
+ "wcnhpnv", soc_type, ver, rom_ver, boardid);
break;
case QCA_WCN7850:
qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
@@ -936,8 +941,15 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
}
err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
+ if (err < 0 && !firmware_name && soc_type == QCA_WCN6855) {
+ qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
+ "hpnv", soc_type, ver, rom_ver, boardid);
+ err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
+ }
+
if (err < 0) {
- bt_dev_err(hdev, "QCA Failed to download NVM (%d)", err);
+ bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
+ config.fwname, err);
return err;
}
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index ded09e94d296..fcec8e589e81 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -521,12 +521,16 @@ static const struct usb_device_id quirks_table[] = {
{ USB_DEVICE(0x0bda, 0xb850), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3600), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3601), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x0489, 0xe112), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
/* Realtek 8851BU Bluetooth devices */
{ USB_DEVICE(0x3625, 0x010b), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x2001, 0x332a), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x7392, 0xe611), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
/* Realtek 8852AE Bluetooth devices */
{ USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK |
@@ -557,6 +561,8 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x13d3, 0x3612), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe122), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
@@ -577,8 +583,6 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3591), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
- { USB_DEVICE(0x13d3, 0x3618), .driver_info = BTUSB_REALTEK |
- BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe123), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0489, 0xe125), .driver_info = BTUSB_REALTEK |
@@ -637,6 +641,8 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3622), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0489, 0xe158), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH },
/* Additional MediaTek MT7921 Bluetooth devices */
{ USB_DEVICE(0x0489, 0xe0c8), .driver_info = BTUSB_MEDIATEK |
@@ -773,6 +779,7 @@ static const struct usb_device_id quirks_table[] = {
/* Additional Realtek 8723BU Bluetooth devices */
{ USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x2c0a, 0x8761), .driver_info = BTUSB_REALTEK },
/* Additional Realtek 8723DE Bluetooth devices */
{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
@@ -4462,17 +4469,17 @@ static void btusb_disconnect(struct usb_interface *intf)
kfree(data);
}
-#ifdef CONFIG_PM
static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
{
struct btusb_data *data = usb_get_intfdata(intf);
BT_DBG("intf %p", intf);
- /* Don't auto-suspend if there are connections; external suspend calls
- * shall never fail.
+ /* Don't auto-suspend if there are connections or discovery in
+ * progress; external suspend calls shall never fail.
*/
- if (PMSG_IS_AUTO(message) && hci_conn_count(data->hdev))
+ if (PMSG_IS_AUTO(message) &&
+ (hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
return -EBUSY;
if (data->suspend_count++)
@@ -4616,7 +4623,6 @@ done:
return err;
}
-#endif
#ifdef CONFIG_DEV_COREDUMP
static void btusb_coredump(struct device *dev)
@@ -4633,10 +4639,8 @@ static struct usb_driver btusb_driver = {
.name = "btusb",
.probe = btusb_probe,
.disconnect = btusb_disconnect,
-#ifdef CONFIG_PM
- .suspend = btusb_suspend,
- .resume = btusb_resume,
-#endif
+ .suspend = pm_ptr(btusb_suspend),
+ .resume = pm_ptr(btusb_resume),
.id_table = btusb_table,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1,
diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c
index 45e6d84224ee..925d0a635945 100644
--- a/drivers/bluetooth/hci_bcm4377.c
+++ b/drivers/bluetooth/hci_bcm4377.c
@@ -2416,8 +2416,9 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hdev);
}
-static int bcm4377_suspend(struct pci_dev *pdev, pm_message_t state)
+static int bcm4377_suspend(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
struct bcm4377_data *bcm4377 = pci_get_drvdata(pdev);
int ret;
@@ -2431,8 +2432,9 @@ static int bcm4377_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
}
-static int bcm4377_resume(struct pci_dev *pdev)
+static int bcm4377_resume(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
struct bcm4377_data *bcm4377 = pci_get_drvdata(pdev);
iowrite32(BCM4377_BAR0_SLEEP_CONTROL_UNQUIESCE,
@@ -2441,6 +2443,8 @@ static int bcm4377_resume(struct pci_dev *pdev)
return hci_resume_dev(bcm4377->hdev);
}
+static DEFINE_SIMPLE_DEV_PM_OPS(bcm4377_ops, bcm4377_suspend, bcm4377_resume);
+
static const struct dmi_system_id bcm4377_dmi_board_table[] = {
{
.matches = {
@@ -2541,8 +2545,7 @@ static struct pci_driver bcm4377_pci_driver = {
.name = "hci_bcm4377",
.id_table = bcm4377_devid_table,
.probe = bcm4377_probe,
- .suspend = bcm4377_suspend,
- .resume = bcm4377_resume,
+ .driver.pm = &bcm4377_ops,
};
module_pci_driver(bcm4377_pci_driver);
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index 20baf2895dec..f7570c2eaa46 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -126,7 +126,6 @@ static int intel_wait_booting(struct hci_uart *hu)
return err;
}
-#ifdef CONFIG_PM
static int intel_wait_lpm_transaction(struct hci_uart *hu)
{
struct intel_data *intel = hu->priv;
@@ -237,7 +236,6 @@ static int intel_lpm_resume(struct hci_uart *hu)
return 0;
}
-#endif /* CONFIG_PM */
static int intel_lpm_host_wake(struct hci_uart *hu)
{
@@ -1066,7 +1064,6 @@ static const struct acpi_device_id intel_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, intel_acpi_match);
#endif
-#ifdef CONFIG_PM
static int intel_suspend_device(struct device *dev)
{
struct intel_device *idev = dev_get_drvdata(dev);
@@ -1090,10 +1087,8 @@ static int intel_resume_device(struct device *dev)
return 0;
}
-#endif
-#ifdef CONFIG_PM_SLEEP
-static int intel_suspend(struct device *dev)
+static int __maybe_unused intel_suspend(struct device *dev)
{
struct intel_device *idev = dev_get_drvdata(dev);
@@ -1103,7 +1098,7 @@ static int intel_suspend(struct device *dev)
return intel_suspend_device(dev);
}
-static int intel_resume(struct device *dev)
+static int __maybe_unused intel_resume(struct device *dev)
{
struct intel_device *idev = dev_get_drvdata(dev);
@@ -1112,7 +1107,6 @@ static int intel_resume(struct device *dev)
return intel_resume_device(dev);
}
-#endif
static const struct dev_pm_ops intel_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(intel_suspend, intel_resume)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 888176b0faa9..51309f5b5714 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -87,6 +87,7 @@ enum qca_flags {
enum qca_capabilities {
QCA_CAP_WIDEBAND_SPEECH = BIT(0),
QCA_CAP_VALID_LE_STATES = BIT(1),
+ QCA_CAP_HFP_HW_OFFLOAD = BIT(2),
};
/* HCI_IBS transmit side sleep protocol states */
@@ -229,6 +230,7 @@ struct qca_serdev {
u32 init_speed;
u32 oper_speed;
bool bdaddr_property_broken;
+ bool support_hfp_hw_offload;
const char *firmware_name[2];
};
@@ -1653,6 +1655,39 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
skb_queue_purge(&qca->rx_memdump_q);
}
+ /*
+ * If the BT chip's bt_en pin is connected to a 3.3V power supply via
+ * hardware and always stays high, driver cannot control the bt_en pin.
+ * As a result, during SSR (SubSystem Restart), QCA_SSR_TRIGGERED and
+ * QCA_IBS_DISABLED flags cannot be cleared, which leads to a reset
+ * command timeout.
+ * Add an msleep delay to ensure controller completes the SSR process.
+ *
+ * Host will not download the firmware after SSR, controller to remain
+ * in the IBS_WAKE state, and the host needs to synchronize with it
+ *
+ * Since the bluetooth chip has been reset, clear the memdump state.
+ */
+ if (!hci_test_quirk(hu->hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) {
+ /*
+ * When the SSR (SubSystem Restart) duration exceeds 2 seconds,
+ * it triggers host tx_idle_delay, which sets host TX state
+ * to sleep. Reset tx_idle_timer after SSR to prevent
+ * host enter TX IBS_Sleep mode.
+ */
+ mod_timer(&qca->tx_idle_timer, jiffies +
+ msecs_to_jiffies(qca->tx_idle_delay));
+
+ /* Controller reset completion time is 50ms */
+ msleep(50);
+
+ clear_bit(QCA_SSR_TRIGGERED, &qca->flags);
+ clear_bit(QCA_IBS_DISABLED, &qca->flags);
+
+ qca->tx_ibs_state = HCI_IBS_TX_AWAKE;
+ qca->memdump_state = QCA_MEMDUMP_IDLE;
+ }
+
clear_bit(QCA_HW_ERROR_EVENT, &qca->flags);
}
@@ -1879,7 +1914,7 @@ static int qca_setup(struct hci_uart *hu)
const char *rampatch_name = qca_get_rampatch_name(hu);
int ret;
struct qca_btsoc_version ver;
- struct qca_serdev *qcadev;
+ struct qca_serdev *qcadev = serdev_device_get_drvdata(hu->serdev);
const char *soc_name;
ret = qca_check_speeds(hu);
@@ -1943,7 +1978,6 @@ retry:
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
- qcadev = serdev_device_get_drvdata(hu->serdev);
if (qcadev->bdaddr_property_broken)
hci_set_quirk(hdev, HCI_QUIRK_BDADDR_PROPERTY_BROKEN);
@@ -2033,7 +2067,7 @@ out:
else
hu->hdev->set_bdaddr = qca_set_bdaddr;
- if (soc_type == QCA_QCA2066)
+ if (qcadev->support_hfp_hw_offload)
qca_configure_hfp_offload(hdev);
qca->fw_version = le16_to_cpu(ver.patch_ver);
@@ -2117,7 +2151,8 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = {
static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = {
.soc_type = QCA_QCA2066,
.num_vregs = 0,
- .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
+ .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES |
+ QCA_CAP_HFP_HW_OFFLOAD,
};
static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = {
@@ -2153,7 +2188,8 @@ static const struct qca_device_data qca_soc_data_wcn6855 __maybe_unused = {
{ "vddrfa1p2", 257000 },
},
.num_vregs = 6,
- .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
+ .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES |
+ QCA_CAP_HFP_HW_OFFLOAD,
};
static const struct qca_device_data qca_soc_data_wcn7850 __maybe_unused = {
@@ -2167,7 +2203,8 @@ static const struct qca_device_data qca_soc_data_wcn7850 __maybe_unused = {
{ "vddrfa1p9", 302000 },
},
.num_vregs = 6,
- .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
+ .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES |
+ QCA_CAP_HFP_HW_OFFLOAD,
};
static void qca_power_shutdown(struct hci_uart *hu)
@@ -2502,6 +2539,9 @@ static int qca_serdev_probe(struct serdev_device *serdev)
if (!(data->capabilities & QCA_CAP_VALID_LE_STATES))
hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES);
+
+ if (data->capabilities & QCA_CAP_HFP_HW_OFFLOAD)
+ qcadev->support_hfp_hw_offload = true;
}
return 0;