mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
bluetooth pull request for net:
Core: - hci_sysfs: Fix NULL pointer dereference in device_del() - hci_sync: Fix not setting CE length properly - btqcomsmd: destroy RPMsg endpoints before freeing hci_dev Drivers: - btmtk: Declare MT7920 (MT7961 1a) Bluetooth firmware - btusb: mediatek: Fix leaked runtime PM reference in reset - btusb: Fix leaked runtime PM reference in btusb_reset - btusb: Fix UAF of btusb_data by rx_work - btusb: Properly disable remote wakeup for MT7922/MT7925 on Ryzen platform - btintel_pcie: validate packet_len before skb_put_data - btintel_pcie: fix tx_handle bounds off-by-one - btrtl: Don't leak return code when parsing firmware format v2 -----BEGIN PGP SIGNATURE----- iQJNBAABCgA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmqge+cZHGx1aXoudm9u LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKdY3EACTdTdiS8WX8MHynuHzdp/n QsB6nHnt9MFfFqNSngmP2GzHB3dS9fGBHu19by4fSM/5DPpjBNT9h2UB9jMKZ3Ps lg2sLYTBm/9y0HYVYKfsZKhTYWU790OlNfCHNzYze0qYgHG6JB3KY87Rfay/GAsK 4t2PCnRJNSq3O3QHsGmg8USo2Vz7xH0ucKBoblHHHWH90n9ZgTPATq0Pt9/9MwPa WxOcKbsgsGZ4ZeDbi+Tu5I9froR1bwh18q+c+f+0DXV75k8csJUy2Ro2G9GXXbW2 96K7BpVy9BWKNnoSxWMy+jFZZRd0WmWHy8IcunYV6c65LLRlDjyJJ9fjCCbhT+ej Rsu7Ows0iTaBs/eWBaMyDLU12eNh2Fr5uFKkZXzMCcTLkPJWYkvOdtRA502D3F4t /dnk6dME5btAvHS/47QSlQ3JmpHuM1VL5GynLhkeIw2td16gDh3l5VbtUsANNbMn w9jL+YGgGA7nMClfR8VwKueypHqIClLQohbz14uvlqaXbsM5vgP86IF6jmSLdX2q DUSXeuk+EhuD5keP5bDriMRJCEKNYNO4DKlcCAkMc6nZqGJRin9tix1r9q9fQf2t 0IQOXaHE9WRyqK3wbxVuOI8UaYRGB+DtoSWTJ4T0Rf8wo3oduMbGGRv3R9lnPjKA 1NNB9rCRO5PmHLHkGOihRA== =hxd3 -----END PGP SIGNATURE----- Merge tag 'for-net-2026-09-08' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: Core: - hci_sysfs: Fix NULL pointer dereference in device_del() - hci_sync: Fix not setting CE length properly - btqcomsmd: destroy RPMsg endpoints before freeing hci_dev Drivers: - btmtk: Declare MT7920 (MT7961 1a) Bluetooth firmware - btusb: mediatek: Fix leaked runtime PM reference in reset - btusb: Fix leaked runtime PM reference in btusb_reset - btusb: Fix UAF of btusb_data by rx_work - btusb: Properly disable remote wakeup for MT7922/MT7925 on Ryzen platform - btintel_pcie: validate packet_len before skb_put_data - btintel_pcie: fix tx_handle bounds off-by-one - btrtl: Don't leak return code when parsing firmware format v2 * tag 'for-net-2026-09-08' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: btusb: Fix leaked runtime PM reference in btusb_reset Bluetooth: btusb: mediatek: Fix leaked runtime PM reference in reset Bluetooth: btqcomsmd: destroy RPMsg endpoints before freeing hci_dev Bluetooth: hci_sysfs: Fix NULL pointer dereference in device_del() Bluetooth: btmtk: Declare MT7920 (MT7961 1a) Bluetooth firmware Bluetooth: hci_sync: Fix not setting CE length properly Bluetooth: btintel_pcie: fix tx_handle bounds off-by-one Bluetooth: btintel_pcie: validate packet_len before skb_put_data Bluetooth: btrtl: Don't leak return code when parsing firmware format v2 Bluetooth: btusb: Fix UAF of btusb_data by rx_work Bluetooth: Properly disable remote wakeup for MT7922/MT7925 on Ryzen platform ==================== Link: https://patch.msgid.link/20260908212127.1022197-1-luiz.dentz@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
bbee0759d3
|
|
@ -1099,7 +1099,7 @@ static void btintel_pcie_msix_tx_handle(struct btintel_pcie_data *data)
|
|||
|
||||
urbd0 = &txq->urbd0s[cr_tia];
|
||||
|
||||
if (urbd0->tfd_index > txq->count)
|
||||
if (urbd0->tfd_index >= txq->count)
|
||||
return;
|
||||
|
||||
cr_tia = (cr_tia + 1) % txq->count;
|
||||
|
|
@ -1599,7 +1599,9 @@ static int btintel_pcie_submit_rx_work(struct btintel_pcie_data *data, u8 status
|
|||
rfh_hdr = buf;
|
||||
|
||||
len = rfh_hdr->packet_len;
|
||||
if (len <= 0) {
|
||||
if (len == 0 || len > BTINTEL_PCIE_BUFFER_SIZE - sizeof(*rfh_hdr)) {
|
||||
bt_dev_err(data->hdev, "Invalid packet_len %d (max %zu)", len,
|
||||
BTINTEL_PCIE_BUFFER_SIZE - sizeof(*rfh_hdr));
|
||||
ret = -EINVAL;
|
||||
goto resubmit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1374,16 +1374,6 @@ int btmtk_usb_setup(struct hci_dev *hdev)
|
|||
break;
|
||||
case 0x7922:
|
||||
case 0x7925:
|
||||
/*
|
||||
* A remote wakeup could cause the device completely unresponsive, and
|
||||
* recovering from such a state needs a power cycle.
|
||||
*
|
||||
* Since the remote wakeup capability is super broken, just disable it
|
||||
* to get rid of the troubles. The device can still be autosuspended
|
||||
* when the bluetooth interface is closed.
|
||||
*/
|
||||
device_set_wakeup_capable(&btmtk_data->udev->dev, false);
|
||||
fallthrough;
|
||||
case 0x7961:
|
||||
case 0x7902:
|
||||
case 0x6639:
|
||||
|
|
@ -1587,5 +1577,6 @@ MODULE_FIRMWARE(FIRMWARE_MT7663);
|
|||
MODULE_FIRMWARE(FIRMWARE_MT7668);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7922);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7961);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7920);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7925);
|
||||
MODULE_FIRMWARE(FIRMWARE_MT7927);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define FIRMWARE_MT7922 "mediatek/BT_RAM_CODE_MT7922_1_1_hdr.bin"
|
||||
#define FIRMWARE_MT7902 "mediatek/BT_RAM_CODE_MT7902_1_1_hdr.bin"
|
||||
#define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
|
||||
#define FIRMWARE_MT7920 "mediatek/BT_RAM_CODE_MT7961_1a_2_hdr.bin"
|
||||
#define FIRMWARE_MT7925 "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin"
|
||||
#define FIRMWARE_MT7927 "mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin"
|
||||
|
||||
|
|
|
|||
|
|
@ -188,7 +188,10 @@ static int btqcomsmd_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
hci_free_dev:
|
||||
rpmsg_destroy_ept(btq->cmd_channel);
|
||||
rpmsg_destroy_ept(btq->acl_channel);
|
||||
hci_free_dev(hdev);
|
||||
return ret;
|
||||
destroy_cmd_channel:
|
||||
rpmsg_destroy_ept(btq->cmd_channel);
|
||||
destroy_acl_channel:
|
||||
|
|
@ -202,10 +205,11 @@ static void btqcomsmd_remove(struct platform_device *pdev)
|
|||
struct btqcomsmd *btq = platform_get_drvdata(pdev);
|
||||
|
||||
hci_unregister_dev(btq->hdev);
|
||||
hci_free_dev(btq->hdev);
|
||||
|
||||
rpmsg_destroy_ept(btq->cmd_channel);
|
||||
rpmsg_destroy_ept(btq->acl_channel);
|
||||
|
||||
hci_free_dev(btq->hdev);
|
||||
}
|
||||
|
||||
static const struct of_device_id btqcomsmd_of_match[] = {
|
||||
|
|
|
|||
|
|
@ -591,7 +591,7 @@ static int rtlbt_parse_firmware_v2(struct hci_dev *hdev,
|
|||
* headers.
|
||||
*/
|
||||
if (!key_id)
|
||||
break;
|
||||
continue;
|
||||
rc = btrtl_parse_section(hdev, btrtl_dev, opcode,
|
||||
ptr, section_len);
|
||||
break;
|
||||
|
|
@ -600,8 +600,7 @@ static int rtlbt_parse_firmware_v2(struct hci_dev *hdev,
|
|||
ptr, section_len);
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (rc < 0) {
|
||||
rtl_dev_err(hdev, "RTL: Parse section (%u) err %d",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
* Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
|
||||
*/
|
||||
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
|
@ -980,6 +981,8 @@ struct btqca_data {
|
|||
#define BTUSB_USE_ALT3_FOR_WBS 15
|
||||
#define BTUSB_ALT6_CONTINUOUS_TX 16
|
||||
#define BTUSB_HW_SSR_ACTIVE 17
|
||||
#define BTUSB_WAKEUP_BROKEN 18
|
||||
#define BTUSB_RESET 19
|
||||
|
||||
struct btusb_data {
|
||||
struct hci_dev *hdev;
|
||||
|
|
@ -1054,13 +1057,15 @@ static void btusb_reset(struct hci_dev *hdev)
|
|||
int err;
|
||||
|
||||
data = hci_get_drvdata(hdev);
|
||||
/* This is not an unbalanced PM reference since the device will reset */
|
||||
err = usb_autopm_get_interface(data->intf);
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_and_set_bit(BTUSB_RESET, &data->flags))
|
||||
usb_autopm_put_interface_no_suspend(data->intf);
|
||||
|
||||
bt_dev_err(hdev, "Resetting usb device.");
|
||||
usb_queue_reset_device(data->intf);
|
||||
}
|
||||
|
|
@ -2092,18 +2097,24 @@ static int btusb_close(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
cancel_delayed_work(&data->rx_work);
|
||||
cancel_work_sync(&data->work);
|
||||
cancel_work_sync(&data->waker);
|
||||
|
||||
skb_queue_purge(&data->acl_q);
|
||||
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
||||
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
|
||||
clear_bit(BTUSB_DIAG_RUNNING, &data->flags);
|
||||
|
||||
btusb_stop_traffic(data);
|
||||
|
||||
/* rx_work must only be canceled once the URBs that can rearm it are
|
||||
* gone, and it must be canceled synchronously since btusb_disconnect()
|
||||
* frees the btusb_data it dereferences right after hci_unregister_dev().
|
||||
*/
|
||||
cancel_delayed_work_sync(&data->rx_work);
|
||||
|
||||
skb_queue_purge(&data->acl_q);
|
||||
|
||||
btusb_free_frags(data);
|
||||
|
||||
err = usb_autopm_get_interface(data->intf);
|
||||
|
|
@ -2129,7 +2140,7 @@ static int btusb_flush(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
cancel_delayed_work(&data->rx_work);
|
||||
cancel_delayed_work_sync(&data->rx_work);
|
||||
|
||||
skb_queue_purge(&data->acl_q);
|
||||
|
||||
|
|
@ -2923,8 +2934,11 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
|
|||
}
|
||||
|
||||
err = usb_autopm_get_interface(data->intf);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err);
|
||||
clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Release MediaTek ISO data interface */
|
||||
btusb_mtk_release_iso_intf(hdev);
|
||||
|
|
@ -2946,6 +2960,11 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
|
|||
|
||||
err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id);
|
||||
|
||||
if (test_and_set_bit(BTUSB_RESET, &data->flags)) {
|
||||
bt_dev_err(hdev, "last usb reset failed? Resetting again");
|
||||
usb_autopm_put_interface_no_suspend(data->intf);
|
||||
}
|
||||
|
||||
usb_queue_reset_device(data->intf);
|
||||
clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
|
||||
|
||||
|
|
@ -2969,10 +2988,25 @@ static int btusb_send_frame_mtk(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
|
||||
static inline bool platform_is_ryzen(void)
|
||||
{
|
||||
#ifdef CONFIG_X86
|
||||
return boot_cpu_has(X86_FEATURE_ZEN);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool is_direct_child_of_root_hub(struct usb_device *udev)
|
||||
{
|
||||
return udev->parent == udev->bus->root_hub;
|
||||
}
|
||||
|
||||
static int btusb_mtk_setup(struct hci_dev *hdev)
|
||||
{
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
|
||||
int err;
|
||||
|
||||
/* MediaTek WMT vendor cmd requiring below USB resources to
|
||||
* complete the handshake.
|
||||
|
|
@ -2989,7 +3023,40 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
|
|||
btusb_mtk_claim_iso_intf(data);
|
||||
}
|
||||
|
||||
return btmtk_usb_setup(hdev);
|
||||
err = btmtk_usb_setup(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (btmtk_data->dev_id) {
|
||||
case 0x7922:
|
||||
case 0x7925:
|
||||
/*
|
||||
* All reports seen to be relevant to Ryzen-based laptops. These
|
||||
* NICs are usually used as OEM components thanks to some sort
|
||||
* of reference designs.
|
||||
*
|
||||
* Their popularity on other platforms is unclear. While there
|
||||
* is still a chance that the quirk may exist on other
|
||||
* platforms, be cautious and only apply the quirk to direct
|
||||
* children of Ryzen platforms's root hubs for the time being.
|
||||
*
|
||||
* In most cases the root hub is on the SoC or PCH, which needs
|
||||
* the quirk. Unfortunately, this can't distinguish root hubs on
|
||||
* PCIe add-in cards. Such roughness should be acceptable, as
|
||||
* PCIe USB controller add-in cards are less commonly used
|
||||
* nowadays. On the other hand, applying the quirk doesn't hurt
|
||||
* any functionalities either, as the device can still be used
|
||||
* as a wakeup source if desired.
|
||||
*
|
||||
* Theoretically, we could retrieve the root hub's PCI vendor ID
|
||||
* with some hierarchy magic, but that's too intrusive...
|
||||
*/
|
||||
if (platform_is_ryzen() && is_direct_child_of_root_hub(data->udev))
|
||||
set_bit(BTUSB_WAKEUP_BROKEN, &data->flags);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btusb_mtk_shutdown(struct hci_dev *hdev)
|
||||
|
|
@ -4540,6 +4607,9 @@ static void btusb_disconnect(struct usb_interface *intf)
|
|||
if (data->reset_gpio)
|
||||
gpiod_put(data->reset_gpio);
|
||||
|
||||
if (test_and_clear_bit(BTUSB_RESET, &data->flags))
|
||||
usb_autopm_put_interface_no_suspend(data->intf);
|
||||
|
||||
if (intf == data->intf) {
|
||||
if (data->isoc)
|
||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||
|
|
@ -4565,11 +4635,26 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
|
||||
BT_DBG("intf %p", intf);
|
||||
|
||||
/* Don't auto-suspend if there are connections or discovery in
|
||||
* progress; external suspend calls shall never fail.
|
||||
/*
|
||||
* It is reported that remote wakeup events could sometimes cause some
|
||||
* adapters completely unresponsive. Resetting the xHCI root hub doesn't
|
||||
* help at all, and recovering from such a state needs a power cycle.
|
||||
* Since disabling remote wakeup simply causes the USB core to gate
|
||||
* runtime autosuspend as well due to needs_remote_wakeup == 1, let's do
|
||||
* this ourselves to make our life easier. The interface can be safely
|
||||
* autosuspended as long as remote wakeup is disabled, i.e., after
|
||||
* closing the HCI device.
|
||||
*
|
||||
* Don't auto-suspend if there are connections or discovery in progress.
|
||||
*
|
||||
* External suspend calls shall never fail. Specifically, a device with
|
||||
* broken remote wakeup may still take the advantage of remote wakeup in
|
||||
* order to wake up the system from sleep if userspace has enabled it as
|
||||
* a wakeup source.
|
||||
*/
|
||||
if (PMSG_IS_AUTO(message) &&
|
||||
(hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
|
||||
((test_bit(BTUSB_WAKEUP_BROKEN, &data->flags) && data->intf->needs_remote_wakeup) ||
|
||||
hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
|
||||
return -EBUSY;
|
||||
|
||||
if (data->suspend_count++)
|
||||
|
|
|
|||
|
|
@ -4797,6 +4797,24 @@ static int hci_le_set_def_rate_sync(struct hci_dev *hdev)
|
|||
cp.cont_num = cpu_to_le16(0x0001);
|
||||
cp.supv_timeout = cpu_to_le16(0x000c); /* 120 ms */
|
||||
|
||||
/* The connection event length recommended in requests by a Peripheral
|
||||
* uses units of 125 us with a valid range of 0x0001 to 0x7CFF
|
||||
* (0.125 ms to 3.999875 s), so 0x0000 cannot be used. Also note that
|
||||
* the Controller is not required to use these values:
|
||||
*
|
||||
* BLUETOOTH CORE SPECIFICATION Version 6.2 | Vol 4, Part E
|
||||
* 7.8.158. LE Set Default Rate Parameters command
|
||||
*
|
||||
* The Min_CE_Length and Max_CE_Length parameters provide the
|
||||
* Controller with the expected minimum and maximum length of the
|
||||
* connection events. The Controller is not required to use these
|
||||
* values.
|
||||
*
|
||||
* So it is safe to just use the minimum.
|
||||
*/
|
||||
cp.min_ce_len = cpu_to_le16(0x0001);
|
||||
cp.max_ce_len = cpu_to_le16(0x0001);
|
||||
|
||||
return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_DEF_RATE,
|
||||
sizeof(cp), &cp, HCI_CMD_TIMEOUT);
|
||||
}
|
||||
|
|
@ -7467,8 +7485,24 @@ static int hci_le_conn_rate_request_sync(struct hci_dev *hdev, void *data)
|
|||
cp.max_latency = cpu_to_le16(params->max_latency);
|
||||
cp.cont_num = cpu_to_le16(params->cont_num);
|
||||
cp.supv_timeout = cpu_to_le16(params->rate_supv_timeout);
|
||||
cp.min_ce_len = cpu_to_le16(0x0000);
|
||||
cp.max_ce_len = cpu_to_le16(0x0000);
|
||||
|
||||
/* The connection event length recommended in requests by a Peripheral
|
||||
* uses units of 125 us with a valid range of 0x0001 to 0x7CFF
|
||||
* (0.125 ms to 3.999875 s), so 0x0000 cannot be used. Also note that
|
||||
* the Controller is not required to use these values:
|
||||
*
|
||||
* BLUETOOTH CORE SPECIFICATION Version 6.2 | Vol 4, Part E
|
||||
* 7.8.157. LE Connection Rate Request command
|
||||
*
|
||||
* The Min_CE_Length and Max_CE_Length parameters provide the
|
||||
* Controller with the expected minimum and maximum length of the
|
||||
* connection events. The Controller is not required to use these
|
||||
* values.
|
||||
*
|
||||
* So it is safe to just use the minimum.
|
||||
*/
|
||||
cp.min_ce_len = cpu_to_le16(0x0001);
|
||||
cp.max_ce_len = cpu_to_le16(0x0001);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@ static const struct class bt_class = {
|
|||
static void bt_link_release(struct device *dev)
|
||||
{
|
||||
struct hci_conn *conn = to_hci_conn(dev);
|
||||
struct device *parent = dev->parent;
|
||||
|
||||
kfree(conn);
|
||||
put_device(parent);
|
||||
}
|
||||
|
||||
static const struct device_type bt_link = {
|
||||
|
|
@ -21,6 +24,16 @@ static const struct device_type bt_link = {
|
|||
.release = bt_link_release,
|
||||
};
|
||||
|
||||
/*
|
||||
* The rfcomm tty device will possibly retain even when conn
|
||||
* is down, and sysfs doesn't support move zombie device,
|
||||
* so we should move the device before conn device is destroyed.
|
||||
*/
|
||||
static int __match_tty(struct device *dev, const void *data)
|
||||
{
|
||||
return !strncmp(dev_name(dev), "rfcomm", 6);
|
||||
}
|
||||
|
||||
void hci_conn_init_sysfs(struct hci_conn *conn)
|
||||
{
|
||||
struct hci_dev *hdev = conn->hdev;
|
||||
|
|
@ -29,7 +42,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn)
|
|||
|
||||
conn->dev.type = &bt_link;
|
||||
conn->dev.class = &bt_class;
|
||||
conn->dev.parent = &hdev->dev;
|
||||
conn->dev.parent = get_device(&hdev->dev);
|
||||
|
||||
device_initialize(&conn->dev);
|
||||
}
|
||||
|
|
@ -69,7 +82,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
|
|||
while (1) {
|
||||
struct device *dev;
|
||||
|
||||
dev = device_find_any_child(&conn->dev);
|
||||
dev = device_find_child(&conn->dev, NULL, __match_tty);
|
||||
if (!dev)
|
||||
break;
|
||||
device_move(dev, NULL, DPM_ORDER_DEV_LAST);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user