Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for-net-2025-06-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth

Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

- L2CAP: Fix L2CAP MTU negotiation
- hci_core: Fix use-after-free in vhci_flush()
- btintel_pcie: Fix potential race condition in firmware download
- hci_qca: fix unable to load the BT driver

* tag 'for-net-2025-06-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
Bluetooth: hci_core: Fix use-after-free in vhci_flush()
driver: bluetooth: hci_qca:fix unable to load the BT driver
Bluetooth: L2CAP: Fix L2CAP MTU negotiation
Bluetooth: btintel_pcie: Fix potential race condition in firmware download
====================

Link: https://patch.msgid.link/20250623165405.227619-1-luiz.dentz@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+81 -10
+31 -2
drivers/bluetooth/btintel_pcie.c
··· 2033 2033 data->hdev = NULL; 2034 2034 } 2035 2035 2036 + static void btintel_pcie_disable_interrupts(struct btintel_pcie_data *data) 2037 + { 2038 + spin_lock(&data->irq_lock); 2039 + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, data->fh_init_mask); 2040 + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, data->hw_init_mask); 2041 + spin_unlock(&data->irq_lock); 2042 + } 2043 + 2044 + static void btintel_pcie_enable_interrupts(struct btintel_pcie_data *data) 2045 + { 2046 + spin_lock(&data->irq_lock); 2047 + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, ~data->fh_init_mask); 2048 + btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, ~data->hw_init_mask); 2049 + spin_unlock(&data->irq_lock); 2050 + } 2051 + 2052 + static void btintel_pcie_synchronize_irqs(struct btintel_pcie_data *data) 2053 + { 2054 + for (int i = 0; i < data->alloc_vecs; i++) 2055 + synchronize_irq(data->msix_entries[i].vector); 2056 + } 2057 + 2036 2058 static int btintel_pcie_setup_internal(struct hci_dev *hdev) 2037 2059 { 2038 2060 struct btintel_pcie_data *data = hci_get_drvdata(hdev); ··· 2174 2152 bt_dev_err(hdev, "Firmware download retry count: %d", 2175 2153 fw_dl_retry); 2176 2154 btintel_pcie_dump_debug_registers(hdev); 2155 + btintel_pcie_disable_interrupts(data); 2156 + btintel_pcie_synchronize_irqs(data); 2177 2157 err = btintel_pcie_reset_bt(data); 2178 2158 if (err) { 2179 2159 bt_dev_err(hdev, "Failed to do shr reset: %d", err); ··· 2183 2159 } 2184 2160 usleep_range(10000, 12000); 2185 2161 btintel_pcie_reset_ia(data); 2162 + btintel_pcie_enable_interrupts(data); 2186 2163 btintel_pcie_config_msix(data); 2187 2164 err = btintel_pcie_enable_bt(data); 2188 2165 if (err) { ··· 2316 2291 2317 2292 data = pci_get_drvdata(pdev); 2318 2293 2294 + btintel_pcie_disable_interrupts(data); 2295 + 2296 + btintel_pcie_synchronize_irqs(data); 2297 + 2298 + flush_work(&data->rx_work); 2299 + 2319 2300 btintel_pcie_reset_bt(data); 2320 2301 for (int i = 0; i < data->alloc_vecs; i++) { 2321 2302 struct msix_entry *msix_entry; ··· 2333 2302 pci_free_irq_vectors(pdev); 2334 2303 2335 2304 btintel_pcie_release_hdev(data); 2336 - 2337 - flush_work(&data->rx_work); 2338 2305 2339 2306 destroy_workqueue(data->workqueue); 2340 2307
+10 -3
drivers/bluetooth/hci_qca.c
··· 2392 2392 */ 2393 2393 qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev, 2394 2394 "bluetooth"); 2395 - if (IS_ERR(qcadev->bt_power->pwrseq)) 2396 - return PTR_ERR(qcadev->bt_power->pwrseq); 2397 2395 2398 - break; 2396 + /* 2397 + * Some modules have BT_EN enabled via a hardware pull-up, 2398 + * meaning it is not defined in the DTS and is not controlled 2399 + * through the power sequence. In such cases, fall through 2400 + * to follow the legacy flow. 2401 + */ 2402 + if (IS_ERR(qcadev->bt_power->pwrseq)) 2403 + qcadev->bt_power->pwrseq = NULL; 2404 + else 2405 + break; 2399 2406 } 2400 2407 fallthrough; 2401 2408 case QCA_WCN3950:
+2
include/net/bluetooth/hci_core.h
··· 29 29 #include <linux/idr.h> 30 30 #include <linux/leds.h> 31 31 #include <linux/rculist.h> 32 + #include <linux/srcu.h> 32 33 33 34 #include <net/bluetooth/hci.h> 34 35 #include <net/bluetooth/hci_drv.h> ··· 348 347 349 348 struct hci_dev { 350 349 struct list_head list; 350 + struct srcu_struct srcu; 351 351 struct mutex lock; 352 352 353 353 struct ida unset_handle_ida;
+30 -4
net/bluetooth/hci_core.c
··· 64 64 65 65 /* Get HCI device by index. 66 66 * Device is held on return. */ 67 - struct hci_dev *hci_dev_get(int index) 67 + static struct hci_dev *__hci_dev_get(int index, int *srcu_index) 68 68 { 69 69 struct hci_dev *hdev = NULL, *d; 70 70 ··· 77 77 list_for_each_entry(d, &hci_dev_list, list) { 78 78 if (d->id == index) { 79 79 hdev = hci_dev_hold(d); 80 + if (srcu_index) 81 + *srcu_index = srcu_read_lock(&d->srcu); 80 82 break; 81 83 } 82 84 } 83 85 read_unlock(&hci_dev_list_lock); 84 86 return hdev; 87 + } 88 + 89 + struct hci_dev *hci_dev_get(int index) 90 + { 91 + return __hci_dev_get(index, NULL); 92 + } 93 + 94 + static struct hci_dev *hci_dev_get_srcu(int index, int *srcu_index) 95 + { 96 + return __hci_dev_get(index, srcu_index); 97 + } 98 + 99 + static void hci_dev_put_srcu(struct hci_dev *hdev, int srcu_index) 100 + { 101 + srcu_read_unlock(&hdev->srcu, srcu_index); 102 + hci_dev_put(hdev); 85 103 } 86 104 87 105 /* ---- Inquiry support ---- */ ··· 586 568 int hci_dev_reset(__u16 dev) 587 569 { 588 570 struct hci_dev *hdev; 589 - int err; 571 + int err, srcu_index; 590 572 591 - hdev = hci_dev_get(dev); 573 + hdev = hci_dev_get_srcu(dev, &srcu_index); 592 574 if (!hdev) 593 575 return -ENODEV; 594 576 ··· 610 592 err = hci_dev_do_reset(hdev); 611 593 612 594 done: 613 - hci_dev_put(hdev); 595 + hci_dev_put_srcu(hdev, srcu_index); 614 596 return err; 615 597 } 616 598 ··· 2451 2433 if (!hdev) 2452 2434 return NULL; 2453 2435 2436 + if (init_srcu_struct(&hdev->srcu)) { 2437 + kfree(hdev); 2438 + return NULL; 2439 + } 2440 + 2454 2441 hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); 2455 2442 hdev->esco_type = (ESCO_HV1); 2456 2443 hdev->link_mode = (HCI_LM_ACCEPT); ··· 2700 2677 write_lock(&hci_dev_list_lock); 2701 2678 list_del(&hdev->list); 2702 2679 write_unlock(&hci_dev_list_lock); 2680 + 2681 + synchronize_srcu(&hdev->srcu); 2682 + cleanup_srcu_struct(&hdev->srcu); 2703 2683 2704 2684 disable_work_sync(&hdev->rx_work); 2705 2685 disable_work_sync(&hdev->cmd_work);
+8 -1
net/bluetooth/l2cap_core.c
··· 3415 3415 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; 3416 3416 struct l2cap_conf_efs efs; 3417 3417 u8 remote_efs = 0; 3418 - u16 mtu = L2CAP_DEFAULT_MTU; 3418 + u16 mtu = 0; 3419 3419 u16 result = L2CAP_CONF_SUCCESS; 3420 3420 u16 size; 3421 3421 ··· 3519 3519 if (result == L2CAP_CONF_SUCCESS) { 3520 3520 /* Configure output options and let the other side know 3521 3521 * which ones we don't like. */ 3522 + 3523 + /* If MTU is not provided in configure request, use the most recently 3524 + * explicitly or implicitly accepted value for the other direction, 3525 + * or the default value. 3526 + */ 3527 + if (mtu == 0) 3528 + mtu = chan->imtu ? chan->imtu : L2CAP_DEFAULT_MTU; 3522 3529 3523 3530 if (mtu < L2CAP_DEFAULT_MIN_MTU) 3524 3531 result = L2CAP_CONF_UNACCEPT;