Commit 3d382936 authored by David S. Miller's avatar David S. Miller

Merge tag 'for-net-next-2023-08-11' of...

Merge tag 'for-net-next-2023-08-11' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

bluetooth-next pull request for net-next:

 - Add new VID/PID for Mediatek MT7922
 - Add support multiple BIS/BIG
 - Add support for Intel Gale Peak
 - Add support for Qualcomm WCN3988
 - Add support for BT_PKT_STATUS for ISO sockets
 - Various fixes for experimental ISO support
 - Load FW v2 for RTL8852C
 - Add support for NXP AW693 chipset
 - Add support for Mediatek MT2925
parents 2f4503f9 b5793de3
...@@ -19,6 +19,7 @@ properties: ...@@ -19,6 +19,7 @@ properties:
- qcom,qca2066-bt - qcom,qca2066-bt
- qcom,qca6174-bt - qcom,qca6174-bt
- qcom,qca9377-bt - qcom,qca9377-bt
- qcom,wcn3988-bt
- qcom,wcn3990-bt - qcom,wcn3990-bt
- qcom,wcn3991-bt - qcom,wcn3991-bt
- qcom,wcn3998-bt - qcom,wcn3998-bt
...@@ -111,6 +112,7 @@ allOf: ...@@ -111,6 +112,7 @@ allOf:
compatible: compatible:
contains: contains:
enum: enum:
- qcom,wcn3988-bt
- qcom,wcn3990-bt - qcom,wcn3990-bt
- qcom,wcn3991-bt - qcom,wcn3991-bt
- qcom,wcn3998-bt - qcom,wcn3998-bt
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#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_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_BCM43430A1 (&(bdaddr_t) {{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}})
#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_BCM4334B0 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb0, 0x34, 0x43}}) #define BDADDR_BCM4334B0 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb0, 0x34, 0x43}})
...@@ -115,6 +116,9 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) ...@@ -115,6 +116,9 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
* *
* The address 43:43:A0:12:1F:AC indicates a BCM43430A0 controller * The address 43:43:A0:12:1F:AC indicates a BCM43430A0 controller
* with no configured address. * with no configured address.
*
* The address AA:AA:AA:AA:AA:AA indicates a BCM43430A1 controller
* with no configured address.
*/ */
if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) || if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM20702A1) || !bacmp(&bda->bdaddr, BDADDR_BCM20702A1) ||
...@@ -124,6 +128,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) ...@@ -124,6 +128,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
!bacmp(&bda->bdaddr, BDADDR_BCM4334B0) || !bacmp(&bda->bdaddr, BDADDR_BCM4334B0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM4345C5) || !bacmp(&bda->bdaddr, BDADDR_BCM4345C5) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43430A0) || !bacmp(&bda->bdaddr, BDADDR_BCM43430A0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43430A1) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43341B)) { !bacmp(&bda->bdaddr, BDADDR_BCM43341B)) {
/* Try falling back to BDADDR EFI variable */ /* Try falling back to BDADDR EFI variable */
if (btbcm_set_bdaddr_from_efi(hdev) != 0) { if (btbcm_set_bdaddr_from_efi(hdev) != 0) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -27,6 +28,11 @@ ...@@ -27,6 +28,11 @@
#define BTINTEL_PPAG_NAME "PPAG" #define BTINTEL_PPAG_NAME "PPAG"
enum {
DSM_SET_WDISABLE2_DELAY = 1,
DSM_SET_RESET_METHOD = 3,
};
/* structure to store the PPAG data read from ACPI table */ /* structure to store the PPAG data read from ACPI table */
struct btintel_ppag { struct btintel_ppag {
u32 domain; u32 domain;
...@@ -49,6 +55,10 @@ static struct { ...@@ -49,6 +55,10 @@ static struct {
u32 fw_build_num; u32 fw_build_num;
} coredump_info; } coredump_info;
static const guid_t btintel_guid_dsm =
GUID_INIT(0xaa10f4e0, 0x81ac, 0x4233,
0xab, 0xf6, 0x3b, 0x2a, 0xc5, 0x0e, 0x28, 0xd9);
int btintel_check_bdaddr(struct hci_dev *hdev) int btintel_check_bdaddr(struct hci_dev *hdev)
{ {
struct hci_rp_read_bd_addr *bda; struct hci_rp_read_bd_addr *bda;
...@@ -470,6 +480,7 @@ static int btintel_version_info_tlv(struct hci_dev *hdev, ...@@ -470,6 +480,7 @@ static int btintel_version_info_tlv(struct hci_dev *hdev,
case 0x18: /* Slr */ case 0x18: /* Slr */
case 0x19: /* Slr-F */ case 0x19: /* Slr-F */
case 0x1b: /* Mgr */ case 0x1b: /* Mgr */
case 0x1c: /* Gale Peak (GaP) */
break; break;
default: default:
bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)", bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
...@@ -2444,6 +2455,116 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver ...@@ -2444,6 +2455,116 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver
kfree_skb(skb); kfree_skb(skb);
} }
static int btintel_acpi_reset_method(struct hci_dev *hdev)
{
int ret = 0;
acpi_status status;
union acpi_object *p, *ref;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
status = acpi_evaluate_object(ACPI_HANDLE(GET_HCIDEV_DEV(hdev)), "_PRR", NULL, &buffer);
if (ACPI_FAILURE(status)) {
bt_dev_err(hdev, "Failed to run _PRR method");
ret = -ENODEV;
return ret;
}
p = buffer.pointer;
if (p->package.count != 1 || p->type != ACPI_TYPE_PACKAGE) {
bt_dev_err(hdev, "Invalid arguments");
ret = -EINVAL;
goto exit_on_error;
}
ref = &p->package.elements[0];
if (ref->type != ACPI_TYPE_LOCAL_REFERENCE) {
bt_dev_err(hdev, "Invalid object type: 0x%x", ref->type);
ret = -EINVAL;
goto exit_on_error;
}
status = acpi_evaluate_object(ref->reference.handle, "_RST", NULL, NULL);
if (ACPI_FAILURE(status)) {
bt_dev_err(hdev, "Failed to run_RST method");
ret = -ENODEV;
goto exit_on_error;
}
exit_on_error:
kfree(buffer.pointer);
return ret;
}
static void btintel_set_dsm_reset_method(struct hci_dev *hdev,
struct intel_version_tlv *ver_tlv)
{
struct btintel_data *data = hci_get_priv(hdev);
acpi_handle handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev));
u8 reset_payload[4] = {0x01, 0x00, 0x01, 0x00};
union acpi_object *obj, argv4;
enum {
RESET_TYPE_WDISABLE2,
RESET_TYPE_VSEC
};
handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev));
if (!handle) {
bt_dev_dbg(hdev, "No support for bluetooth device in ACPI firmware");
return;
}
if (!acpi_has_method(handle, "_PRR")) {
bt_dev_err(hdev, "No support for _PRR ACPI method");
return;
}
switch (ver_tlv->cnvi_top & 0xfff) {
case 0x910: /* GalePeak2 */
reset_payload[2] = RESET_TYPE_VSEC;
break;
default:
/* WDISABLE2 is the default reset method */
reset_payload[2] = RESET_TYPE_WDISABLE2;
if (!acpi_check_dsm(handle, &btintel_guid_dsm, 0,
BIT(DSM_SET_WDISABLE2_DELAY))) {
bt_dev_err(hdev, "No dsm support to set reset delay");
return;
}
argv4.integer.type = ACPI_TYPE_INTEGER;
/* delay required to toggle BT power */
argv4.integer.value = 160;
obj = acpi_evaluate_dsm(handle, &btintel_guid_dsm, 0,
DSM_SET_WDISABLE2_DELAY, &argv4);
if (!obj) {
bt_dev_err(hdev, "Failed to call dsm to set reset delay");
return;
}
ACPI_FREE(obj);
}
bt_dev_info(hdev, "DSM reset method type: 0x%02x", reset_payload[2]);
if (!acpi_check_dsm(handle, &btintel_guid_dsm, 0,
DSM_SET_RESET_METHOD)) {
bt_dev_warn(hdev, "No support for dsm to set reset method");
return;
}
argv4.buffer.type = ACPI_TYPE_BUFFER;
argv4.buffer.length = sizeof(reset_payload);
argv4.buffer.pointer = reset_payload;
obj = acpi_evaluate_dsm(handle, &btintel_guid_dsm, 0,
DSM_SET_RESET_METHOD, &argv4);
if (!obj) {
bt_dev_err(hdev, "Failed to call dsm to set reset method");
return;
}
ACPI_FREE(obj);
data->acpi_reset_method = btintel_acpi_reset_method;
}
static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
struct intel_version_tlv *ver) struct intel_version_tlv *ver)
{ {
...@@ -2528,6 +2649,7 @@ static void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant) ...@@ -2528,6 +2649,7 @@ static void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant)
case 0x18: case 0x18:
case 0x19: case 0x19:
case 0x1b: case 0x1b:
case 0x1c:
hci_set_msft_opcode(hdev, 0xFC1E); hci_set_msft_opcode(hdev, 0xFC1E);
break; break;
default: default:
...@@ -2742,6 +2864,7 @@ static int btintel_setup_combined(struct hci_dev *hdev) ...@@ -2742,6 +2864,7 @@ static int btintel_setup_combined(struct hci_dev *hdev)
case 0x18: case 0x18:
case 0x19: case 0x19:
case 0x1b: case 0x1b:
case 0x1c:
/* Display version information of TLV type */ /* Display version information of TLV type */
btintel_version_info_tlv(hdev, &ver_tlv); btintel_version_info_tlv(hdev, &ver_tlv);
...@@ -2757,6 +2880,7 @@ static int btintel_setup_combined(struct hci_dev *hdev) ...@@ -2757,6 +2880,7 @@ static int btintel_setup_combined(struct hci_dev *hdev)
/* Setup MSFT Extension support */ /* Setup MSFT Extension support */
btintel_set_msft_opcode(hdev, btintel_set_msft_opcode(hdev,
INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); INTEL_HW_VARIANT(ver_tlv.cnvi_bt));
btintel_set_dsm_reset_method(hdev, &ver_tlv);
err = btintel_bootloader_setup_tlv(hdev, &ver_tlv); err = btintel_bootloader_setup_tlv(hdev, &ver_tlv);
btintel_register_devcoredump_support(hdev); btintel_register_devcoredump_support(hdev);
...@@ -2824,6 +2948,80 @@ int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name) ...@@ -2824,6 +2948,80 @@ int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name)
} }
EXPORT_SYMBOL_GPL(btintel_configure_setup); EXPORT_SYMBOL_GPL(btintel_configure_setup);
static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
{
struct intel_tlv *tlv = (void *)&skb->data[5];
/* The first event is always an event type TLV */
if (tlv->type != INTEL_TLV_TYPE_ID)
goto recv_frame;
switch (tlv->val[0]) {
case INTEL_TLV_SYSTEM_EXCEPTION:
case INTEL_TLV_FATAL_EXCEPTION:
case INTEL_TLV_DEBUG_EXCEPTION:
case INTEL_TLV_TEST_EXCEPTION:
/* Generate devcoredump from exception */
if (!hci_devcd_init(hdev, skb->len)) {
hci_devcd_append(hdev, skb);
hci_devcd_complete(hdev);
} else {
bt_dev_err(hdev, "Failed to generate devcoredump");
kfree_skb(skb);
}
return 0;
default:
bt_dev_err(hdev, "Invalid exception type %02X", tlv->val[0]);
}
recv_frame:
return hci_recv_frame(hdev, skb);
}
int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *)skb->data;
const char diagnostics_hdr[] = { 0x87, 0x80, 0x03 };
if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff &&
hdr->plen > 0) {
const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1;
unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1;
if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
switch (skb->data[2]) {
case 0x02:
/* When switching to the operational firmware
* the device sends a vendor specific event
* indicating that the bootup completed.
*/
btintel_bootup(hdev, ptr, len);
break;
case 0x06:
/* When the firmware loading completes the
* device sends out a vendor specific event
* indicating the result of the firmware
* loading.
*/
btintel_secure_send_result(hdev, ptr, len);
break;
}
}
/* Handle all diagnostics events separately. May still call
* hci_recv_frame.
*/
if (len >= sizeof(diagnostics_hdr) &&
memcmp(&skb->data[2], diagnostics_hdr,
sizeof(diagnostics_hdr)) == 0) {
return btintel_diagnostics(hdev, skb);
}
}
return hci_recv_frame(hdev, skb);
}
EXPORT_SYMBOL_GPL(btintel_recv_event);
void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len) void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len)
{ {
const struct intel_bootup *evt = ptr; const struct intel_bootup *evt = ptr;
......
...@@ -166,12 +166,14 @@ enum { ...@@ -166,12 +166,14 @@ enum {
INTEL_BROKEN_SHUTDOWN_LED, INTEL_BROKEN_SHUTDOWN_LED,
INTEL_ROM_LEGACY, INTEL_ROM_LEGACY,
INTEL_ROM_LEGACY_NO_WBS_SUPPORT, INTEL_ROM_LEGACY_NO_WBS_SUPPORT,
INTEL_ACPI_RESET_ACTIVE,
__INTEL_NUM_FLAGS, __INTEL_NUM_FLAGS,
}; };
struct btintel_data { struct btintel_data {
DECLARE_BITMAP(flags, __INTEL_NUM_FLAGS); DECLARE_BITMAP(flags, __INTEL_NUM_FLAGS);
int (*acpi_reset_method)(struct hci_dev *hdev);
}; };
#define btintel_set_flag(hdev, nr) \ #define btintel_set_flag(hdev, nr) \
...@@ -220,6 +222,7 @@ int btintel_read_boot_params(struct hci_dev *hdev, ...@@ -220,6 +222,7 @@ int btintel_read_boot_params(struct hci_dev *hdev,
int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver, int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver,
const struct firmware *fw, u32 *boot_param); const struct firmware *fw, u32 *boot_param);
int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name); int btintel_configure_setup(struct hci_dev *hdev, const char *driver_name);
int btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb);
void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len); void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len);
void btintel_secure_send_result(struct hci_dev *hdev, void btintel_secure_send_result(struct hci_dev *hdev,
const void *ptr, unsigned int len); const void *ptr, unsigned int len);
......
...@@ -53,10 +53,61 @@ struct btmtk_section_map { ...@@ -53,10 +53,61 @@ struct btmtk_section_map {
}; };
} __packed; } __packed;
static void btmtk_coredump(struct hci_dev *hdev)
{
int err;
err = __hci_cmd_send(hdev, 0xfd5b, 0, NULL);
if (err < 0)
bt_dev_err(hdev, "Coredump failed (%d)", err);
}
static void btmtk_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btmediatek_data *data = hci_get_priv(hdev);
char buf[80];
snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
data->dev_id);
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n",
data->cd_info.fw_version);
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Driver: %s\n",
data->cd_info.driver_name);
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Vendor: MediaTek\n");
skb_put_data(skb, buf, strlen(buf));
}
static void btmtk_coredump_notify(struct hci_dev *hdev, int state)
{
struct btmediatek_data *data = hci_get_priv(hdev);
switch (state) {
case HCI_DEVCOREDUMP_IDLE:
data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
break;
case HCI_DEVCOREDUMP_ACTIVE:
data->cd_info.state = HCI_DEVCOREDUMP_ACTIVE;
break;
case HCI_DEVCOREDUMP_TIMEOUT:
case HCI_DEVCOREDUMP_ABORT:
case HCI_DEVCOREDUMP_DONE:
data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
btmtk_reset_sync(hdev);
break;
}
}
int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
wmt_cmd_sync_func_t wmt_cmd_sync) wmt_cmd_sync_func_t wmt_cmd_sync)
{ {
struct btmtk_hci_wmt_params wmt_params; struct btmtk_hci_wmt_params wmt_params;
struct btmtk_patch_header *hdr;
struct btmtk_global_desc *globaldesc = NULL; struct btmtk_global_desc *globaldesc = NULL;
struct btmtk_section_map *sectionmap; struct btmtk_section_map *sectionmap;
const struct firmware *fw; const struct firmware *fw;
...@@ -75,9 +126,13 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, ...@@ -75,9 +126,13 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
fw_ptr = fw->data; fw_ptr = fw->data;
fw_bin_ptr = fw_ptr; fw_bin_ptr = fw_ptr;
hdr = (struct btmtk_patch_header *)fw_ptr;
globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE); globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE);
section_num = le32_to_cpu(globaldesc->section_num); section_num = le32_to_cpu(globaldesc->section_num);
bt_dev_info(hdev, "HW/SW Version: 0x%04x%04x, Build Time: %s",
le16_to_cpu(hdr->hwver), le16_to_cpu(hdr->swver), hdr->datetime);
for (i = 0; i < section_num; i++) { for (i = 0; i < section_num; i++) {
first_block = 1; first_block = 1;
fw_ptr = fw_bin_ptr; fw_ptr = fw_bin_ptr;
...@@ -280,6 +335,83 @@ int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) ...@@ -280,6 +335,83 @@ int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
} }
EXPORT_SYMBOL_GPL(btmtk_set_bdaddr); EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);
void btmtk_reset_sync(struct hci_dev *hdev)
{
struct btmediatek_data *reset_work = hci_get_priv(hdev);
int err;
hci_dev_lock(hdev);
err = hci_cmd_sync_queue(hdev, reset_work->reset_sync, NULL, NULL);
if (err)
bt_dev_err(hdev, "failed to reset (%d)", err);
hci_dev_unlock(hdev);
}
EXPORT_SYMBOL_GPL(btmtk_reset_sync);
int btmtk_register_coredump(struct hci_dev *hdev, const char *name,
u32 fw_version)
{
struct btmediatek_data *data = hci_get_priv(hdev);
if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
return -EOPNOTSUPP;
data->cd_info.fw_version = fw_version;
data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
data->cd_info.driver_name = name;
return hci_devcd_register(hdev, btmtk_coredump, btmtk_coredump_hdr,
btmtk_coredump_notify);
}
EXPORT_SYMBOL_GPL(btmtk_register_coredump);
int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btmediatek_data *data = hci_get_priv(hdev);
int err;
if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
return 0;
switch (data->cd_info.state) {
case HCI_DEVCOREDUMP_IDLE:
err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
if (err < 0)
break;
data->cd_info.cnt = 0;
/* It is supposed coredump can be done within 5 seconds */
schedule_delayed_work(&hdev->dump.dump_timeout,
msecs_to_jiffies(5000));
fallthrough;
case HCI_DEVCOREDUMP_ACTIVE:
default:
err = hci_devcd_append(hdev, skb);
if (err < 0)
break;
data->cd_info.cnt++;
/* Mediatek coredump data would be more than MTK_COREDUMP_NUM */
if (data->cd_info.cnt > MTK_COREDUMP_NUM &&
skb->len > MTK_COREDUMP_END_LEN)
if (!memcmp((char *)&skb->data[skb->len - MTK_COREDUMP_END_LEN],
MTK_COREDUMP_END, MTK_COREDUMP_END_LEN - 1)) {
bt_dev_info(hdev, "Mediatek coredump end");
hci_devcd_complete(hdev);
}
break;
}
if (err < 0)
kfree_skb(skb);
return err;
}
EXPORT_SYMBOL_GPL(btmtk_process_coredump);
MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>"); MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION); MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
...@@ -289,3 +421,4 @@ MODULE_FIRMWARE(FIRMWARE_MT7622); ...@@ -289,3 +421,4 @@ MODULE_FIRMWARE(FIRMWARE_MT7622);
MODULE_FIRMWARE(FIRMWARE_MT7663); MODULE_FIRMWARE(FIRMWARE_MT7663);
MODULE_FIRMWARE(FIRMWARE_MT7668); MODULE_FIRMWARE(FIRMWARE_MT7668);
MODULE_FIRMWARE(FIRMWARE_MT7961); MODULE_FIRMWARE(FIRMWARE_MT7961);
MODULE_FIRMWARE(FIRMWARE_MT7925);
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" #define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"
#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" #define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
#define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin" #define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
#define FIRMWARE_MT7925 "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin"
#define HCI_EV_WMT 0xe4 #define HCI_EV_WMT 0xe4
#define HCI_WMT_MAX_EVENT_SIZE 64 #define HCI_WMT_MAX_EVENT_SIZE 64
...@@ -21,6 +22,11 @@ ...@@ -21,6 +22,11 @@
#define MT7921_DLSTATUS 0x7c053c10 #define MT7921_DLSTATUS 0x7c053c10
#define BT_DL_STATE BIT(1) #define BT_DL_STATE BIT(1)
#define MTK_COREDUMP_SIZE (1024 * 1000)
#define MTK_COREDUMP_END "coredump end"
#define MTK_COREDUMP_END_LEN (sizeof(MTK_COREDUMP_END))
#define MTK_COREDUMP_NUM 255
enum { enum {
BTMTK_WMT_PATCH_DWNLD = 0x1, BTMTK_WMT_PATCH_DWNLD = 0x1,
BTMTK_WMT_TEST = 0x2, BTMTK_WMT_TEST = 0x2,
...@@ -119,6 +125,21 @@ struct btmtk_hci_wmt_params { ...@@ -119,6 +125,21 @@ struct btmtk_hci_wmt_params {
u32 *status; u32 *status;
}; };
typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *);
struct btmtk_coredump_info {
const char *driver_name;
u32 fw_version;
u16 cnt;
int state;
};
struct btmediatek_data {
u32 dev_id;
btmtk_reset_sync_func_t reset_sync;
struct btmtk_coredump_info cd_info;
};
typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *, typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *,
struct btmtk_hci_wmt_params *); struct btmtk_hci_wmt_params *);
...@@ -131,6 +152,13 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, ...@@ -131,6 +152,13 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname, int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
wmt_cmd_sync_func_t wmt_cmd_sync); wmt_cmd_sync_func_t wmt_cmd_sync);
void btmtk_reset_sync(struct hci_dev *hdev);
int btmtk_register_coredump(struct hci_dev *hdev, const char *name,
u32 fw_version);
int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb);
#else #else
static inline int btmtk_set_bdaddr(struct hci_dev *hdev, static inline int btmtk_set_bdaddr(struct hci_dev *hdev,
...@@ -151,4 +179,18 @@ static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname, ...@@ -151,4 +179,18 @@ static int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static void btmtk_reset_sync(struct hci_dev *hdev)
{
}
static int btmtk_register_coredump(struct hci_dev *hdev, const char *name,
u32 fw_version)
{
return -EOPNOTSUPP;
}
static int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
{
return -EOPNOTSUPP;
}
#endif #endif
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
......
...@@ -29,16 +29,25 @@ ...@@ -29,16 +29,25 @@
#define BTNXPUART_CHECK_BOOT_SIGNATURE 3 #define BTNXPUART_CHECK_BOOT_SIGNATURE 3
#define BTNXPUART_SERDEV_OPEN 4 #define BTNXPUART_SERDEV_OPEN 4
#define FIRMWARE_W8987 "nxp/uartuart8987_bt.bin" #define FIRMWARE_W8987 "nxp/uartuart8987_bt.bin"
#define FIRMWARE_W8997 "nxp/uartuart8997_bt_v4.bin" #define FIRMWARE_W8997 "nxp/uartuart8997_bt_v4.bin"
#define FIRMWARE_W9098 "nxp/uartuart9098_bt_v1.bin" #define FIRMWARE_W9098 "nxp/uartuart9098_bt_v1.bin"
#define FIRMWARE_IW416 "nxp/uartiw416_bt_v0.bin" #define FIRMWARE_IW416 "nxp/uartiw416_bt_v0.bin"
#define FIRMWARE_IW612 "nxp/uartspi_n61x_v1.bin.se" #define FIRMWARE_IW612 "nxp/uartspi_n61x_v1.bin.se"
#define FIRMWARE_HELPER "nxp/helper_uart_3000000.bin" #define FIRMWARE_AW693 "nxp/uartaw693_bt.bin"
#define FIRMWARE_SECURE_AW693 "nxp/uartaw693_bt.bin.se"
#define FIRMWARE_HELPER "nxp/helper_uart_3000000.bin"
#define CHIP_ID_W9098 0x5c03 #define CHIP_ID_W9098 0x5c03
#define CHIP_ID_IW416 0x7201 #define CHIP_ID_IW416 0x7201
#define CHIP_ID_IW612 0x7601 #define CHIP_ID_IW612 0x7601
#define CHIP_ID_AW693 0x8200
#define FW_SECURE_MASK 0xc0
#define FW_OPEN 0x00
#define FW_AUTH_ILLEGAL 0x40
#define FW_AUTH_PLAIN 0x80
#define FW_AUTH_ENC 0xc0
#define HCI_NXP_PRI_BAUDRATE 115200 #define HCI_NXP_PRI_BAUDRATE 115200
#define HCI_NXP_SEC_BAUDRATE 3000000 #define HCI_NXP_SEC_BAUDRATE 3000000
...@@ -665,6 +674,9 @@ static int nxp_request_firmware(struct hci_dev *hdev, const char *fw_name) ...@@ -665,6 +674,9 @@ static int nxp_request_firmware(struct hci_dev *hdev, const char *fw_name)
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
int err = 0; int err = 0;
if (!fw_name)
return -ENOENT;
if (!strlen(nxpdev->fw_name)) { if (!strlen(nxpdev->fw_name)) {
snprintf(nxpdev->fw_name, MAX_FW_FILE_NAME_LEN, "%s", fw_name); snprintf(nxpdev->fw_name, MAX_FW_FILE_NAME_LEN, "%s", fw_name);
...@@ -812,7 +824,8 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -812,7 +824,8 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
return 0; return 0;
} }
static char *nxp_get_fw_name_from_chipid(struct hci_dev *hdev, u16 chipid) static char *nxp_get_fw_name_from_chipid(struct hci_dev *hdev, u16 chipid,
u8 loader_ver)
{ {
char *fw_name = NULL; char *fw_name = NULL;
...@@ -826,6 +839,14 @@ static char *nxp_get_fw_name_from_chipid(struct hci_dev *hdev, u16 chipid) ...@@ -826,6 +839,14 @@ static char *nxp_get_fw_name_from_chipid(struct hci_dev *hdev, u16 chipid)
case CHIP_ID_IW612: case CHIP_ID_IW612:
fw_name = FIRMWARE_IW612; fw_name = FIRMWARE_IW612;
break; break;
case CHIP_ID_AW693:
if ((loader_ver & FW_SECURE_MASK) == FW_OPEN)
fw_name = FIRMWARE_AW693;
else if ((loader_ver & FW_SECURE_MASK) != FW_AUTH_ILLEGAL)
fw_name = FIRMWARE_SECURE_AW693;
else
bt_dev_err(hdev, "Illegal loader version %02x", loader_ver);
break;
default: default:
bt_dev_err(hdev, "Unknown chip signature %04x", chipid); bt_dev_err(hdev, "Unknown chip signature %04x", chipid);
break; break;
...@@ -838,13 +859,15 @@ static int nxp_recv_chip_ver_v3(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -838,13 +859,15 @@ static int nxp_recv_chip_ver_v3(struct hci_dev *hdev, struct sk_buff *skb)
struct v3_start_ind *req = skb_pull_data(skb, sizeof(*req)); struct v3_start_ind *req = skb_pull_data(skb, sizeof(*req));
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
u16 chip_id; u16 chip_id;
u8 loader_ver;
if (!process_boot_signature(nxpdev)) if (!process_boot_signature(nxpdev))
goto free_skb; goto free_skb;
chip_id = le16_to_cpu(req->chip_id); chip_id = le16_to_cpu(req->chip_id);
loader_ver = req->loader_ver;
if (!nxp_request_firmware(hdev, nxp_get_fw_name_from_chipid(hdev, if (!nxp_request_firmware(hdev, nxp_get_fw_name_from_chipid(hdev,
chip_id))) chip_id, loader_ver)))
nxp_send_ack(NXP_ACK_V3, hdev); nxp_send_ack(NXP_ACK_V3, hdev);
free_skb: free_skb:
......
...@@ -594,14 +594,20 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, ...@@ -594,14 +594,20 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
/* 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.
*/ */
rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f); if (soc_type == QCA_WCN3988)
rom_ver = ((soc_ver & 0x00000f00) >> 0x05) | (soc_ver & 0x0000000f);
else
rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f);
if (soc_type == QCA_WCN6750) if (soc_type == QCA_WCN6750)
qca_send_patch_config_cmd(hdev); qca_send_patch_config_cmd(hdev);
/* Download rampatch file */ /* Download rampatch file */
config.type = TLV_TYPE_PATCH; config.type = TLV_TYPE_PATCH;
if (qca_is_wcn399x(soc_type)) { if (soc_type == QCA_WCN3988) {
snprintf(config.fwname, sizeof(config.fwname),
"qca/apbtfw%02x.tlv", rom_ver);
} else if (qca_is_wcn399x(soc_type)) {
snprintf(config.fwname, sizeof(config.fwname), snprintf(config.fwname, sizeof(config.fwname),
"qca/crbtfw%02x.tlv", rom_ver); "qca/crbtfw%02x.tlv", rom_ver);
} else if (soc_type == QCA_QCA6390) { } else if (soc_type == QCA_QCA6390) {
...@@ -636,6 +642,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, ...@@ -636,6 +642,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
if (firmware_name) if (firmware_name)
snprintf(config.fwname, sizeof(config.fwname), snprintf(config.fwname, sizeof(config.fwname),
"qca/%s", firmware_name); "qca/%s", firmware_name);
else if (soc_type == QCA_WCN3988)
snprintf(config.fwname, sizeof(config.fwname),
"qca/apnv%02x.bin", rom_ver);
else if (qca_is_wcn399x(soc_type)) { else if (qca_is_wcn399x(soc_type)) {
if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) { if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) {
snprintf(config.fwname, sizeof(config.fwname), snprintf(config.fwname, sizeof(config.fwname),
......
...@@ -142,6 +142,7 @@ enum qca_btsoc_type { ...@@ -142,6 +142,7 @@ enum qca_btsoc_type {
QCA_INVALID = -1, QCA_INVALID = -1,
QCA_AR3002, QCA_AR3002,
QCA_ROME, QCA_ROME,
QCA_WCN3988,
QCA_WCN3990, QCA_WCN3990,
QCA_WCN3998, QCA_WCN3998,
QCA_WCN3991, QCA_WCN3991,
...@@ -162,8 +163,15 @@ int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); ...@@ -162,8 +163,15 @@ int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
int qca_send_pre_shutdown_cmd(struct hci_dev *hdev); int qca_send_pre_shutdown_cmd(struct hci_dev *hdev);
static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type) static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
{ {
return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3991 || switch (soc_type) {
soc_type == QCA_WCN3998; case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
case QCA_WCN3998:
return true;
default:
return false;
}
} }
static inline bool qca_is_wcn6750(enum qca_btsoc_type soc_type) static inline bool qca_is_wcn6750(enum qca_btsoc_type soc_type)
{ {
......
This diff is collapsed.
...@@ -109,8 +109,16 @@ enum { ...@@ -109,8 +109,16 @@ enum {
__REALTEK_NUM_FLAGS, __REALTEK_NUM_FLAGS,
}; };
struct rtl_dump_info {
const char *driver_name;
char *controller;
u32 fw_version;
};
struct btrealtek_data { struct btrealtek_data {
DECLARE_BITMAP(flags, __REALTEK_NUM_FLAGS); DECLARE_BITMAP(flags, __REALTEK_NUM_FLAGS);
struct rtl_dump_info rtl_dump;
}; };
#define btrealtek_set_flag(hdev, nr) \ #define btrealtek_set_flag(hdev, nr) \
...@@ -139,6 +147,7 @@ int btrtl_get_uart_settings(struct hci_dev *hdev, ...@@ -139,6 +147,7 @@ int btrtl_get_uart_settings(struct hci_dev *hdev,
struct btrtl_device_info *btrtl_dev, struct btrtl_device_info *btrtl_dev,
unsigned int *controller_baudrate, unsigned int *controller_baudrate,
u32 *device_baudrate, bool *flow_control); u32 *device_baudrate, bool *flow_control);
void btrtl_set_driver_name(struct hci_dev *hdev, const char *driver_name);
#else #else
...@@ -182,4 +191,8 @@ static inline int btrtl_get_uart_settings(struct hci_dev *hdev, ...@@ -182,4 +191,8 @@ static inline int btrtl_get_uart_settings(struct hci_dev *hdev,
return -ENOENT; return -ENOENT;
} }
static inline void btrtl_set_driver_name(struct hci_dev *hdev, const char *driver_name)
{
}
#endif #endif
This diff is collapsed.
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/of_device.h> #include <linux/of.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/serdev.h> #include <linux/serdev.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
......
...@@ -770,7 +770,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, unsigned int cmd, ...@@ -770,7 +770,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
break; break;
case HCIUARTGETPROTO: case HCIUARTGETPROTO:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) if (test_bit(HCI_UART_PROTO_SET, &hu->flags) &&
test_bit(HCI_UART_PROTO_READY, &hu->flags))
err = hu->proto->id; err = hu->proto->id;
else else
err = -EUNATCH; err = -EUNATCH;
......
...@@ -734,7 +734,11 @@ static int nokia_bluetooth_serdev_probe(struct serdev_device *serdev) ...@@ -734,7 +734,11 @@ static int nokia_bluetooth_serdev_probe(struct serdev_device *serdev)
return err; return err;
} }
clk_prepare_enable(sysclk); err = clk_prepare_enable(sysclk);
if (err) {
dev_err(dev, "could not enable sysclk: %d", err);
return err;
}
btdev->sysclk_speed = clk_get_rate(sysclk); btdev->sysclk_speed = clk_get_rate(sysclk);
clk_disable_unprepare(sysclk); clk_disable_unprepare(sysclk);
......
This diff is collapsed.
...@@ -386,6 +386,7 @@ struct bt_sock { ...@@ -386,6 +386,7 @@ struct bt_sock {
enum { enum {
BT_SK_DEFER_SETUP, BT_SK_DEFER_SETUP,
BT_SK_SUSPEND, BT_SK_SUSPEND,
BT_SK_PKT_STATUS
}; };
struct bt_sock_list { struct bt_sock_list {
...@@ -400,6 +401,8 @@ int bt_sock_register(int proto, const struct net_proto_family *ops); ...@@ -400,6 +401,8 @@ int bt_sock_register(int proto, const struct net_proto_family *ops);
void bt_sock_unregister(int proto); void bt_sock_unregister(int proto);
void bt_sock_link(struct bt_sock_list *l, struct sock *s); void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s); void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
struct sock *bt_sock_alloc(struct net *net, struct socket *sock,
struct proto *prot, int proto, gfp_t prio, int kern);
int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
int flags); int flags);
int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg, int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg,
...@@ -430,10 +433,6 @@ struct l2cap_ctrl { ...@@ -430,10 +433,6 @@ struct l2cap_ctrl {
struct l2cap_chan *chan; struct l2cap_chan *chan;
}; };
struct sco_ctrl {
u8 pkt_status;
};
struct hci_dev; struct hci_dev;
typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status, u16 opcode); typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status, u16 opcode);
...@@ -464,16 +463,18 @@ struct bt_skb_cb { ...@@ -464,16 +463,18 @@ struct bt_skb_cb {
u8 force_active; u8 force_active;
u16 expect; u16 expect;
u8 incoming:1; u8 incoming:1;
u8 pkt_status:2;
union { union {
struct l2cap_ctrl l2cap; struct l2cap_ctrl l2cap;
struct sco_ctrl sco;
struct hci_ctrl hci; struct hci_ctrl hci;
struct mgmt_ctrl mgmt; struct mgmt_ctrl mgmt;
struct scm_creds creds;
}; };
}; };
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
#define hci_skb_pkt_type(skb) bt_cb((skb))->pkt_type #define hci_skb_pkt_type(skb) bt_cb((skb))->pkt_type
#define hci_skb_pkt_status(skb) bt_cb((skb))->pkt_status
#define hci_skb_expect(skb) bt_cb((skb))->expect #define hci_skb_expect(skb) bt_cb((skb))->expect
#define hci_skb_opcode(skb) bt_cb((skb))->hci.opcode #define hci_skb_opcode(skb) bt_cb((skb))->hci.opcode
#define hci_skb_event(skb) bt_cb((skb))->hci.req_event #define hci_skb_event(skb) bt_cb((skb))->hci.req_event
......
...@@ -309,6 +309,16 @@ enum { ...@@ -309,6 +309,16 @@ enum {
* to support it. * to support it.
*/ */
HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT,
/* When this quirk is set, MSFT extension monitor tracking by
* address filter is supported. Since tracking quantity of each
* pattern is limited, this feature supports tracking multiple
* devices concurrently if controller supports multiple
* address filters.
*
* This quirk must be set before hci_register_dev is called.
*/
HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER,
}; };
/* HCI device flags */ /* HCI device flags */
...@@ -577,6 +587,7 @@ enum { ...@@ -577,6 +587,7 @@ enum {
#define HCI_LE_CIS_CENTRAL 0x10 #define HCI_LE_CIS_CENTRAL 0x10
#define HCI_LE_CIS_PERIPHERAL 0x20 #define HCI_LE_CIS_PERIPHERAL 0x20
#define HCI_LE_ISO_BROADCASTER 0x40 #define HCI_LE_ISO_BROADCASTER 0x40
#define HCI_LE_ISO_SYNC_RECEIVER 0x80
/* Connection modes */ /* Connection modes */
#define HCI_CM_ACTIVE 0x0000 #define HCI_CM_ACTIVE 0x0000
......
...@@ -321,8 +321,8 @@ struct adv_monitor { ...@@ -321,8 +321,8 @@ struct adv_monitor {
#define HCI_MAX_SHORT_NAME_LENGTH 10 #define HCI_MAX_SHORT_NAME_LENGTH 10
#define HCI_CONN_HANDLE_UNSET 0xffff
#define HCI_CONN_HANDLE_MAX 0x0eff #define HCI_CONN_HANDLE_MAX 0x0eff
#define HCI_CONN_HANDLE_UNSET(_handle) (_handle > HCI_CONN_HANDLE_MAX)
/* Min encryption key size to match with SMP */ /* Min encryption key size to match with SMP */
#define HCI_MIN_ENC_KEY_SIZE 7 #define HCI_MIN_ENC_KEY_SIZE 7
...@@ -739,6 +739,7 @@ struct hci_conn { ...@@ -739,6 +739,7 @@ struct hci_conn {
unsigned long flags; unsigned long flags;
enum conn_reasons conn_reason; enum conn_reasons conn_reason;
__u8 abort_reason;
__u32 clock; __u32 clock;
__u16 clock_accuracy; __u16 clock_accuracy;
...@@ -758,7 +759,6 @@ struct hci_conn { ...@@ -758,7 +759,6 @@ struct hci_conn {
struct delayed_work auto_accept_work; struct delayed_work auto_accept_work;
struct delayed_work idle_work; struct delayed_work idle_work;
struct delayed_work le_conn_timeout; struct delayed_work le_conn_timeout;
struct work_struct le_scan_cleanup;
struct device dev; struct device dev;
struct dentry *debugfs; struct dentry *debugfs;
...@@ -974,6 +974,10 @@ enum { ...@@ -974,6 +974,10 @@ enum {
HCI_CONN_SCANNING, HCI_CONN_SCANNING,
HCI_CONN_AUTH_FAILURE, HCI_CONN_AUTH_FAILURE,
HCI_CONN_PER_ADV, HCI_CONN_PER_ADV,
HCI_CONN_BIG_CREATED,
HCI_CONN_CREATE_CIS,
HCI_CONN_BIG_SYNC,
HCI_CONN_BIG_SYNC_FAILED,
}; };
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
...@@ -1093,8 +1097,7 @@ static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle) ...@@ -1093,8 +1097,7 @@ static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle)
} }
static inline struct hci_conn *hci_conn_hash_lookup_bis(struct hci_dev *hdev, static inline struct hci_conn *hci_conn_hash_lookup_bis(struct hci_dev *hdev,
bdaddr_t *ba, bdaddr_t *ba, __u8 bis)
__u8 big, __u8 bis)
{ {
struct hci_conn_hash *h = &hdev->conn_hash; struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c; struct hci_conn *c;
...@@ -1105,7 +1108,33 @@ static inline struct hci_conn *hci_conn_hash_lookup_bis(struct hci_dev *hdev, ...@@ -1105,7 +1108,33 @@ static inline struct hci_conn *hci_conn_hash_lookup_bis(struct hci_dev *hdev,
if (bacmp(&c->dst, ba) || c->type != ISO_LINK) if (bacmp(&c->dst, ba) || c->type != ISO_LINK)
continue; continue;
if (c->iso_qos.bcast.big == big && c->iso_qos.bcast.bis == bis) { if (c->iso_qos.bcast.bis == bis) {
rcu_read_unlock();
return c;
}
}
rcu_read_unlock();
return NULL;
}
static inline struct hci_conn *
hci_conn_hash_lookup_per_adv_bis(struct hci_dev *hdev,
bdaddr_t *ba,
__u8 big, __u8 bis)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
if (bacmp(&c->dst, ba) || c->type != ISO_LINK ||
!test_bit(HCI_CONN_PER_ADV, &c->flags))
continue;
if (c->iso_qos.bcast.big == big &&
c->iso_qos.bcast.bis == bis) {
rcu_read_unlock(); rcu_read_unlock();
return c; return c;
} }
...@@ -1190,7 +1219,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_cis(struct hci_dev *hdev, ...@@ -1190,7 +1219,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_cis(struct hci_dev *hdev,
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) { list_for_each_entry_rcu(c, &h->list, list) {
if (c->type != ISO_LINK) if (c->type != ISO_LINK || !bacmp(&c->dst, BDADDR_ANY))
continue; continue;
/* Match CIG ID if set */ /* Match CIG ID if set */
...@@ -1222,7 +1251,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_cig(struct hci_dev *hdev, ...@@ -1222,7 +1251,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_cig(struct hci_dev *hdev,
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) { list_for_each_entry_rcu(c, &h->list, list) {
if (c->type != ISO_LINK) if (c->type != ISO_LINK || !bacmp(&c->dst, BDADDR_ANY))
continue; continue;
if (handle == c->iso_qos.ucast.cig) { if (handle == c->iso_qos.ucast.cig) {
...@@ -1259,6 +1288,29 @@ static inline struct hci_conn *hci_conn_hash_lookup_big(struct hci_dev *hdev, ...@@ -1259,6 +1288,29 @@ static inline struct hci_conn *hci_conn_hash_lookup_big(struct hci_dev *hdev,
return NULL; return NULL;
} }
static inline struct hci_conn *hci_conn_hash_lookup_big_any_dst(struct hci_dev *hdev,
__u8 handle)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
if (c->type != ISO_LINK)
continue;
if (handle == c->iso_qos.bcast.big) {
rcu_read_unlock();
return c;
}
}
rcu_read_unlock();
return NULL;
}
static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
__u8 type, __u16 state) __u8 type, __u16 state)
{ {
...@@ -1320,11 +1372,33 @@ static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev) ...@@ -1320,11 +1372,33 @@ static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev)
return NULL; return NULL;
} }
/* Returns true if an le connection is in the scanning state */
static inline bool hci_is_le_conn_scanning(struct hci_dev *hdev)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
if (c->type == LE_LINK && c->state == BT_CONNECT &&
test_bit(HCI_CONN_SCANNING, &c->flags)) {
rcu_read_unlock();
return true;
}
}
rcu_read_unlock();
return false;
}
int hci_disconnect(struct hci_conn *conn, __u8 reason); int hci_disconnect(struct hci_conn *conn, __u8 reason);
bool hci_setup_sync(struct hci_conn *conn, __u16 handle); bool hci_setup_sync(struct hci_conn *conn, __u16 handle);
void hci_sco_setup(struct hci_conn *conn, __u8 status); void hci_sco_setup(struct hci_conn *conn, __u8 status);
bool hci_iso_setup_path(struct hci_conn *conn); bool hci_iso_setup_path(struct hci_conn *conn);
int hci_le_create_cis(struct hci_conn *conn); int hci_le_create_cis_pending(struct hci_dev *hdev);
int hci_conn_check_create_cis(struct hci_conn *conn);
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
u8 role); u8 role);
...@@ -1351,6 +1425,9 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, ...@@ -1351,6 +1425,9 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u16 setting, struct bt_codec *codec); __u16 setting, struct bt_codec *codec);
struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
__u8 dst_type, struct bt_iso_qos *qos); __u8 dst_type, struct bt_iso_qos *qos);
struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
struct bt_iso_qos *qos,
__u8 base_len, __u8 *base);
struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
__u8 dst_type, struct bt_iso_qos *qos); __u8 dst_type, struct bt_iso_qos *qos);
struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
...@@ -1369,6 +1446,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role); ...@@ -1369,6 +1446,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
void hci_conn_failed(struct hci_conn *conn, u8 status); void hci_conn_failed(struct hci_conn *conn, u8 status);
u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle);
/* /*
* hci_conn_get() and hci_conn_put() are used to control the life-time of an * hci_conn_get() and hci_conn_put() are used to control the life-time of an
...@@ -1745,6 +1823,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn); ...@@ -1745,6 +1823,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
/* Extended advertising support */ /* Extended advertising support */
#define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV)) #define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV))
/* Maximum advertising length */
#define max_adv_len(dev) \
(ext_adv_capable(dev) ? HCI_MAX_EXT_AD_LENGTH : HCI_MAX_AD_LENGTH)
/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E page 1789: /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E page 1789:
* *
* C24: Mandatory if the LE Controller supports Connection State and either * C24: Mandatory if the LE Controller supports Connection State and either
...@@ -1765,6 +1847,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); ...@@ -1765,6 +1847,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define cis_peripheral_capable(dev) \ #define cis_peripheral_capable(dev) \
((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL) ((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL)
#define bis_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_BROADCASTER) #define bis_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_BROADCASTER)
#define sync_recv_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER)
#define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \ #define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \
(!test_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &(dev)->quirks))) (!test_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &(dev)->quirks)))
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
* Copyright (C) 2021 Intel Corporation * Copyright (C) 2021 Intel Corporation
*/ */
#define UINT_PTR(_handle) ((void *)((uintptr_t)_handle))
#define PTR_UINT(_ptr) ((uintptr_t)((void *)_ptr))
typedef int (*hci_cmd_sync_work_func_t)(struct hci_dev *hdev, void *data); typedef int (*hci_cmd_sync_work_func_t)(struct hci_dev *hdev, void *data);
typedef void (*hci_cmd_sync_work_destroy_t)(struct hci_dev *hdev, void *data, typedef void (*hci_cmd_sync_work_destroy_t)(struct hci_dev *hdev, void *data,
int err); int err);
...@@ -124,7 +127,7 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason); ...@@ -124,7 +127,7 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason);
int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn); int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn);
int hci_le_create_cis_sync(struct hci_dev *hdev, struct hci_conn *conn); int hci_le_create_cis_sync(struct hci_dev *hdev);
int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle); int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle);
......
...@@ -111,6 +111,8 @@ struct mgmt_rp_read_index_list { ...@@ -111,6 +111,8 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_WIDEBAND_SPEECH BIT(17) #define MGMT_SETTING_WIDEBAND_SPEECH BIT(17)
#define MGMT_SETTING_CIS_CENTRAL BIT(18) #define MGMT_SETTING_CIS_CENTRAL BIT(18)
#define MGMT_SETTING_CIS_PERIPHERAL BIT(19) #define MGMT_SETTING_CIS_PERIPHERAL BIT(19)
#define MGMT_SETTING_ISO_BROADCASTER BIT(20)
#define MGMT_SETTING_ISO_SYNC_RECEIVER BIT(21)
#define MGMT_OP_READ_INFO 0x0004 #define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0 #define MGMT_READ_INFO_SIZE 0
......
...@@ -46,6 +46,4 @@ struct sco_conninfo { ...@@ -46,6 +46,4 @@ struct sco_conninfo {
__u8 dev_class[3]; __u8 dev_class[3];
}; };
#define SCO_CMSG_PKT_STATUS 0x01
#endif /* __SCO_H */ #endif /* __SCO_H */
...@@ -140,6 +140,35 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto, ...@@ -140,6 +140,35 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto,
return err; return err;
} }
struct sock *bt_sock_alloc(struct net *net, struct socket *sock,
struct proto *prot, int proto, gfp_t prio, int kern)
{
struct sock *sk;
sk = sk_alloc(net, PF_BLUETOOTH, prio, prot, kern);
if (!sk)
return NULL;
sock_init_data(sock, sk);
INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_protocol = proto;
sk->sk_state = BT_OPEN;
/* Init peer information so it can be properly monitored */
if (!kern) {
spin_lock(&sk->sk_peer_lock);
sk->sk_peer_pid = get_pid(task_tgid(current));
sk->sk_peer_cred = get_current_cred();
spin_unlock(&sk->sk_peer_lock);
}
return sk;
}
EXPORT_SYMBOL(bt_sock_alloc);
void bt_sock_link(struct bt_sock_list *l, struct sock *sk) void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
{ {
write_lock(&l->lock); write_lock(&l->lock);
...@@ -158,6 +187,9 @@ EXPORT_SYMBOL(bt_sock_unlink); ...@@ -158,6 +187,9 @@ EXPORT_SYMBOL(bt_sock_unlink);
void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh) void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh)
{ {
const struct cred *old_cred;
struct pid *old_pid;
BT_DBG("parent %p, sk %p", parent, sk); BT_DBG("parent %p, sk %p", parent, sk);
sock_hold(sk); sock_hold(sk);
...@@ -170,6 +202,19 @@ void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh) ...@@ -170,6 +202,19 @@ void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh)
list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q); list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
bt_sk(sk)->parent = parent; bt_sk(sk)->parent = parent;
/* Copy credentials from parent since for incoming connections the
* socket is allocated by the kernel.
*/
spin_lock(&sk->sk_peer_lock);
old_pid = sk->sk_peer_pid;
old_cred = sk->sk_peer_cred;
sk->sk_peer_pid = get_pid(parent->sk_peer_pid);
sk->sk_peer_cred = get_cred(parent->sk_peer_cred);
spin_unlock(&sk->sk_peer_lock);
put_pid(old_pid);
put_cred(old_cred);
if (bh) if (bh)
bh_unlock_sock(sk); bh_unlock_sock(sk);
else else
...@@ -288,8 +333,12 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ...@@ -288,8 +333,12 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
bt_sk(sk)->skb_msg_name(skb, msg->msg_name, bt_sk(sk)->skb_msg_name(skb, msg->msg_name,
&msg->msg_namelen); &msg->msg_namelen);
if (bt_sk(sk)->skb_put_cmsg) if (test_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags)) {
bt_sk(sk)->skb_put_cmsg(skb, msg, sk); u8 pkt_status = hci_skb_pkt_status(skb);
put_cmsg(msg, SOL_BLUETOOTH, BT_SCM_PKT_STATUS,
sizeof(pkt_status), &pkt_status);
}
} }
skb_free_datagram(sk, skb); skb_free_datagram(sk, skb);
......
...@@ -28,7 +28,6 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, ...@@ -28,7 +28,6 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type); int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle); void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr); void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_read_loc_assoc_final_data(struct hci_dev *hdev, void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
......
...@@ -205,21 +205,13 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, ...@@ -205,21 +205,13 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
if (sock->type != SOCK_RAW) if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT; return -ESOCKTNOSUPPORT;
sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, kern); sk = bt_sock_alloc(net, sock, &bnep_proto, protocol, GFP_ATOMIC, kern);
if (!sk) if (!sk)
return -ENOMEM; return -ENOMEM;
sock_init_data(sock, sk);
sock->ops = &bnep_sock_ops; sock->ops = &bnep_sock_ops;
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_protocol = protocol;
sk->sk_state = BT_OPEN;
bt_sock_link(&bnep_sk_list, sk); bt_sock_link(&bnep_sk_list, sk);
return 0; return 0;
} }
......
...@@ -100,8 +100,7 @@ void hci_devcd_reset(struct hci_dev *hdev) ...@@ -100,8 +100,7 @@ void hci_devcd_reset(struct hci_dev *hdev)
/* Call with hci_dev_lock only. */ /* Call with hci_dev_lock only. */
static void hci_devcd_free(struct hci_dev *hdev) static void hci_devcd_free(struct hci_dev *hdev)
{ {
if (hdev->dump.head) vfree(hdev->dump.head);
vfree(hdev->dump.head);
hci_devcd_reset(hdev); hci_devcd_reset(hdev);
} }
......
This diff is collapsed.
...@@ -1074,9 +1074,9 @@ void hci_uuids_clear(struct hci_dev *hdev) ...@@ -1074,9 +1074,9 @@ void hci_uuids_clear(struct hci_dev *hdev)
void hci_link_keys_clear(struct hci_dev *hdev) void hci_link_keys_clear(struct hci_dev *hdev)
{ {
struct link_key *key; struct link_key *key, *tmp;
list_for_each_entry(key, &hdev->link_keys, list) { list_for_each_entry_safe(key, tmp, &hdev->link_keys, list) {
list_del_rcu(&key->list); list_del_rcu(&key->list);
kfree_rcu(key, rcu); kfree_rcu(key, rcu);
} }
...@@ -1084,9 +1084,9 @@ void hci_link_keys_clear(struct hci_dev *hdev) ...@@ -1084,9 +1084,9 @@ void hci_link_keys_clear(struct hci_dev *hdev)
void hci_smp_ltks_clear(struct hci_dev *hdev) void hci_smp_ltks_clear(struct hci_dev *hdev)
{ {
struct smp_ltk *k; struct smp_ltk *k, *tmp;
list_for_each_entry(k, &hdev->long_term_keys, list) { list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
list_del_rcu(&k->list); list_del_rcu(&k->list);
kfree_rcu(k, rcu); kfree_rcu(k, rcu);
} }
...@@ -1094,9 +1094,9 @@ void hci_smp_ltks_clear(struct hci_dev *hdev) ...@@ -1094,9 +1094,9 @@ void hci_smp_ltks_clear(struct hci_dev *hdev)
void hci_smp_irks_clear(struct hci_dev *hdev) void hci_smp_irks_clear(struct hci_dev *hdev)
{ {
struct smp_irk *k; struct smp_irk *k, *tmp;
list_for_each_entry(k, &hdev->identity_resolving_keys, list) { list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
list_del_rcu(&k->list); list_del_rcu(&k->list);
kfree_rcu(k, rcu); kfree_rcu(k, rcu);
} }
...@@ -1104,9 +1104,9 @@ void hci_smp_irks_clear(struct hci_dev *hdev) ...@@ -1104,9 +1104,9 @@ void hci_smp_irks_clear(struct hci_dev *hdev)
void hci_blocked_keys_clear(struct hci_dev *hdev) void hci_blocked_keys_clear(struct hci_dev *hdev)
{ {
struct blocked_key *b; struct blocked_key *b, *tmp;
list_for_each_entry(b, &hdev->blocked_keys, list) { list_for_each_entry_safe(b, tmp, &hdev->blocked_keys, list) {
list_del_rcu(&b->list); list_del_rcu(&b->list);
kfree_rcu(b, rcu); kfree_rcu(b, rcu);
} }
...@@ -1949,15 +1949,15 @@ int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor) ...@@ -1949,15 +1949,15 @@ int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
switch (hci_get_adv_monitor_offload_ext(hdev)) { switch (hci_get_adv_monitor_offload_ext(hdev)) {
case HCI_ADV_MONITOR_EXT_NONE: case HCI_ADV_MONITOR_EXT_NONE:
bt_dev_dbg(hdev, "%s add monitor %d status %d", hdev->name, bt_dev_dbg(hdev, "add monitor %d status %d",
monitor->handle, status); monitor->handle, status);
/* Message was not forwarded to controller - not an error */ /* Message was not forwarded to controller - not an error */
break; break;
case HCI_ADV_MONITOR_EXT_MSFT: case HCI_ADV_MONITOR_EXT_MSFT:
status = msft_add_monitor_pattern(hdev, monitor); status = msft_add_monitor_pattern(hdev, monitor);
bt_dev_dbg(hdev, "%s add monitor %d msft status %d", hdev->name, bt_dev_dbg(hdev, "add monitor %d msft status %d",
monitor->handle, status); handle, status);
break; break;
} }
...@@ -1976,15 +1976,15 @@ static int hci_remove_adv_monitor(struct hci_dev *hdev, ...@@ -1976,15 +1976,15 @@ static int hci_remove_adv_monitor(struct hci_dev *hdev,
switch (hci_get_adv_monitor_offload_ext(hdev)) { switch (hci_get_adv_monitor_offload_ext(hdev)) {
case HCI_ADV_MONITOR_EXT_NONE: /* also goes here when powered off */ case HCI_ADV_MONITOR_EXT_NONE: /* also goes here when powered off */
bt_dev_dbg(hdev, "%s remove monitor %d status %d", hdev->name, bt_dev_dbg(hdev, "remove monitor %d status %d",
monitor->handle, status); monitor->handle, status);
goto free_monitor; goto free_monitor;
case HCI_ADV_MONITOR_EXT_MSFT: case HCI_ADV_MONITOR_EXT_MSFT:
handle = monitor->handle; handle = monitor->handle;
status = msft_remove_monitor(hdev, monitor); status = msft_remove_monitor(hdev, monitor);
bt_dev_dbg(hdev, "%s remove monitor %d msft status %d", bt_dev_dbg(hdev, "remove monitor %d msft status %d",
hdev->name, handle, status); handle, status);
break; break;
} }
...@@ -2436,6 +2436,9 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action, ...@@ -2436,6 +2436,9 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
return NOTIFY_DONE; return NOTIFY_DONE;
/* To avoid a potential race with hci_unregister_dev. */
hci_dev_hold(hdev);
if (action == PM_SUSPEND_PREPARE) if (action == PM_SUSPEND_PREPARE)
ret = hci_suspend_dev(hdev); ret = hci_suspend_dev(hdev);
else if (action == PM_POST_SUSPEND) else if (action == PM_POST_SUSPEND)
...@@ -2445,6 +2448,7 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action, ...@@ -2445,6 +2448,7 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d", bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d",
action, ret); action, ret);
hci_dev_put(hdev);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -3891,7 +3895,7 @@ static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -3891,7 +3895,7 @@ static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
if (conn) { if (conn) {
/* Send to upper protocol */ /* Send to upper protocol */
bt_cb(skb)->sco.pkt_status = flags & 0x03; hci_skb_pkt_status(skb) = flags & 0x03;
sco_recv_scodata(conn, skb); sco_recv_scodata(conn, skb);
return; return;
} else { } else {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
*/ */
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/kstrtox.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -1152,7 +1153,7 @@ static ssize_t force_no_mitm_write(struct file *file, ...@@ -1152,7 +1153,7 @@ static ssize_t force_no_mitm_write(struct file *file,
return -EFAULT; return -EFAULT;
buf[buf_size] = '\0'; buf[buf_size] = '\0';
if (strtobool(buf, &enable)) if (kstrtobool(buf, &enable))
return -EINVAL; return -EINVAL;
if (enable == hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM)) if (enable == hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM))
......
This diff is collapsed.
...@@ -629,27 +629,6 @@ static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval, ...@@ -629,27 +629,6 @@ static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval,
} }
} }
/* Returns true if an le connection is in the scanning state */
static inline bool hci_is_le_conn_scanning(struct hci_dev *hdev)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c;
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
if (c->type == LE_LINK && c->state == BT_CONNECT &&
test_bit(HCI_CONN_SCANNING, &c->flags)) {
rcu_read_unlock();
return true;
}
}
rcu_read_unlock();
return false;
}
static void set_random_addr(struct hci_request *req, bdaddr_t *rpa); static void set_random_addr(struct hci_request *req, bdaddr_t *rpa);
static int hci_update_random_address(struct hci_request *req, static int hci_update_random_address(struct hci_request *req,
bool require_privacy, bool use_rpa, bool require_privacy, bool use_rpa,
......
...@@ -264,6 +264,53 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -264,6 +264,53 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
kfree_skb(skb_copy); kfree_skb(skb_copy);
} }
static void hci_sock_copy_creds(struct sock *sk, struct sk_buff *skb)
{
struct scm_creds *creds;
if (!sk || WARN_ON(!skb))
return;
creds = &bt_cb(skb)->creds;
/* Check if peer credentials is set */
if (!sk->sk_peer_pid) {
/* Check if parent peer credentials is set */
if (bt_sk(sk)->parent && bt_sk(sk)->parent->sk_peer_pid)
sk = bt_sk(sk)->parent;
else
return;
}
/* Check if scm_creds already set */
if (creds->pid == pid_vnr(sk->sk_peer_pid))
return;
memset(creds, 0, sizeof(*creds));
creds->pid = pid_vnr(sk->sk_peer_pid);
if (sk->sk_peer_cred) {
creds->uid = sk->sk_peer_cred->uid;
creds->gid = sk->sk_peer_cred->gid;
}
}
static struct sk_buff *hci_skb_clone(struct sk_buff *skb)
{
struct sk_buff *nskb;
if (!skb)
return NULL;
nskb = skb_clone(skb, GFP_ATOMIC);
if (!nskb)
return NULL;
hci_sock_copy_creds(skb->sk, nskb);
return nskb;
}
/* Send frame to sockets with specific channel */ /* Send frame to sockets with specific channel */
static void __hci_send_to_channel(unsigned short channel, struct sk_buff *skb, static void __hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
int flag, struct sock *skip_sk) int flag, struct sock *skip_sk)
...@@ -289,7 +336,7 @@ static void __hci_send_to_channel(unsigned short channel, struct sk_buff *skb, ...@@ -289,7 +336,7 @@ static void __hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
if (hci_pi(sk)->channel != channel) if (hci_pi(sk)->channel != channel)
continue; continue;
nskb = skb_clone(skb, GFP_ATOMIC); nskb = hci_skb_clone(skb);
if (!nskb) if (!nskb)
continue; continue;
...@@ -356,6 +403,8 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -356,6 +403,8 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
if (!skb_copy) if (!skb_copy)
return; return;
hci_sock_copy_creds(skb->sk, skb_copy);
/* Put header before the data */ /* Put header before the data */
hdr = skb_push(skb_copy, HCI_MON_HDR_SIZE); hdr = skb_push(skb_copy, HCI_MON_HDR_SIZE);
hdr->opcode = opcode; hdr->opcode = opcode;
...@@ -531,10 +580,12 @@ static struct sk_buff *create_monitor_ctrl_open(struct sock *sk) ...@@ -531,10 +580,12 @@ static struct sk_buff *create_monitor_ctrl_open(struct sock *sk)
return NULL; return NULL;
} }
skb = bt_skb_alloc(14 + TASK_COMM_LEN , GFP_ATOMIC); skb = bt_skb_alloc(14 + TASK_COMM_LEN, GFP_ATOMIC);
if (!skb) if (!skb)
return NULL; return NULL;
hci_sock_copy_creds(sk, skb);
flags = hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) ? 0x1 : 0x0; flags = hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) ? 0x1 : 0x0;
put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4)); put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4));
...@@ -580,6 +631,8 @@ static struct sk_buff *create_monitor_ctrl_close(struct sock *sk) ...@@ -580,6 +631,8 @@ static struct sk_buff *create_monitor_ctrl_close(struct sock *sk)
if (!skb) if (!skb)
return NULL; return NULL;
hci_sock_copy_creds(sk, skb);
put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4)); put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4));
__net_timestamp(skb); __net_timestamp(skb);
...@@ -606,6 +659,8 @@ static struct sk_buff *create_monitor_ctrl_command(struct sock *sk, u16 index, ...@@ -606,6 +659,8 @@ static struct sk_buff *create_monitor_ctrl_command(struct sock *sk, u16 index,
if (!skb) if (!skb)
return NULL; return NULL;
hci_sock_copy_creds(sk, skb);
put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4)); put_unaligned_le32(hci_pi(sk)->cookie, skb_put(skb, 4));
put_unaligned_le16(opcode, skb_put(skb, 2)); put_unaligned_le16(opcode, skb_put(skb, 2));
...@@ -638,6 +693,8 @@ send_monitor_note(struct sock *sk, const char *fmt, ...) ...@@ -638,6 +693,8 @@ send_monitor_note(struct sock *sk, const char *fmt, ...)
if (!skb) if (!skb)
return; return;
hci_sock_copy_creds(sk, skb);
va_start(args, fmt); va_start(args, fmt);
vsprintf(skb_put(skb, len), fmt, args); vsprintf(skb_put(skb, len), fmt, args);
*(u8 *)skb_put(skb, 1) = 0; *(u8 *)skb_put(skb, 1) = 0;
...@@ -1494,6 +1551,7 @@ static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, ...@@ -1494,6 +1551,7 @@ static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg,
static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
size_t len, int flags) size_t len, int flags)
{ {
struct scm_cookie scm;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct sk_buff *skb; struct sk_buff *skb;
int copied, err; int copied, err;
...@@ -1538,11 +1596,16 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -1538,11 +1596,16 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
break; break;
} }
memset(&scm, 0, sizeof(scm));
scm.creds = bt_cb(skb)->creds;
skb_free_datagram(sk, skb); skb_free_datagram(sk, skb);
if (flags & MSG_TRUNC) if (flags & MSG_TRUNC)
copied = skblen; copied = skblen;
scm_recv(sock, msg, &scm, flags);
return err ? : copied; return err ? : copied;
} }
...@@ -2143,18 +2206,12 @@ static int hci_sock_create(struct net *net, struct socket *sock, int protocol, ...@@ -2143,18 +2206,12 @@ static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
sock->ops = &hci_sock_ops; sock->ops = &hci_sock_ops;
sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, kern); sk = bt_sock_alloc(net, sock, &hci_sk_proto, protocol, GFP_ATOMIC,
kern);
if (!sk) if (!sk)
return -ENOMEM; return -ENOMEM;
sock_init_data(sock, sk);
sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_protocol = protocol;
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
sk->sk_state = BT_OPEN;
sk->sk_destruct = hci_sock_destruct; sk->sk_destruct = hci_sock_destruct;
bt_sock_link(&hci_sk_list, sk); bt_sock_link(&hci_sk_list, sk);
......
This diff is collapsed.
...@@ -256,21 +256,13 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, ...@@ -256,21 +256,13 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol,
if (sock->type != SOCK_RAW) if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT; return -ESOCKTNOSUPPORT;
sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, kern); sk = bt_sock_alloc(net, sock, &hidp_proto, protocol, GFP_ATOMIC, kern);
if (!sk) if (!sk)
return -ENOMEM; return -ENOMEM;
sock_init_data(sock, sk);
sock->ops = &hidp_sock_ops; sock->ops = &hidp_sock_ops;
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_protocol = protocol;
sk->sk_state = BT_OPEN;
bt_sock_link(&hidp_sk_list, sk); bt_sock_link(&hidp_sk_list, sk);
return 0; return 0;
......
...@@ -48,6 +48,11 @@ static void iso_sock_kill(struct sock *sk); ...@@ -48,6 +48,11 @@ static void iso_sock_kill(struct sock *sk);
#define EIR_SERVICE_DATA_LENGTH 4 #define EIR_SERVICE_DATA_LENGTH 4
#define BASE_MAX_LENGTH (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH) #define BASE_MAX_LENGTH (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH)
/* iso_pinfo flags values */
enum {
BT_SK_BIG_SYNC,
};
struct iso_pinfo { struct iso_pinfo {
struct bt_sock bt; struct bt_sock bt;
bdaddr_t src; bdaddr_t src;
...@@ -58,7 +63,7 @@ struct iso_pinfo { ...@@ -58,7 +63,7 @@ struct iso_pinfo {
__u8 bc_num_bis; __u8 bc_num_bis;
__u8 bc_bis[ISO_MAX_NUM_BIS]; __u8 bc_bis[ISO_MAX_NUM_BIS];
__u16 sync_handle; __u16 sync_handle;
__u32 flags; unsigned long flags;
struct bt_iso_qos qos; struct bt_iso_qos qos;
bool qos_user_set; bool qos_user_set;
__u8 base_len; __u8 base_len;
...@@ -287,13 +292,24 @@ static int iso_connect_bis(struct sock *sk) ...@@ -287,13 +292,24 @@ static int iso_connect_bis(struct sock *sk)
goto unlock; goto unlock;
} }
hcon = hci_connect_bis(hdev, &iso_pi(sk)->dst, /* Just bind if DEFER_SETUP has been set */
le_addr_type(iso_pi(sk)->dst_type), if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
&iso_pi(sk)->qos, iso_pi(sk)->base_len, hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst,
iso_pi(sk)->base); &iso_pi(sk)->qos, iso_pi(sk)->base_len,
if (IS_ERR(hcon)) { iso_pi(sk)->base);
err = PTR_ERR(hcon); if (IS_ERR(hcon)) {
goto unlock; err = PTR_ERR(hcon);
goto unlock;
}
} else {
hcon = hci_connect_bis(hdev, &iso_pi(sk)->dst,
le_addr_type(iso_pi(sk)->dst_type),
&iso_pi(sk)->qos, iso_pi(sk)->base_len,
iso_pi(sk)->base);
if (IS_ERR(hcon)) {
err = PTR_ERR(hcon);
goto unlock;
}
} }
conn = iso_conn_add(hcon); conn = iso_conn_add(hcon);
...@@ -317,6 +333,9 @@ static int iso_connect_bis(struct sock *sk) ...@@ -317,6 +333,9 @@ static int iso_connect_bis(struct sock *sk)
if (hcon->state == BT_CONNECTED) { if (hcon->state == BT_CONNECTED) {
iso_sock_clear_timer(sk); iso_sock_clear_timer(sk);
sk->sk_state = BT_CONNECTED; sk->sk_state = BT_CONNECTED;
} else if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
iso_sock_clear_timer(sk);
sk->sk_state = BT_CONNECT;
} else { } else {
sk->sk_state = BT_CONNECT; sk->sk_state = BT_CONNECT;
iso_sock_set_timer(sk, sk->sk_sndtimeo); iso_sock_set_timer(sk, sk->sk_sndtimeo);
...@@ -600,18 +619,6 @@ static void iso_sock_kill(struct sock *sk) ...@@ -600,18 +619,6 @@ static void iso_sock_kill(struct sock *sk)
sock_put(sk); sock_put(sk);
} }
static void iso_conn_defer_reject(struct hci_conn *conn)
{
struct hci_cp_le_reject_cis cp;
BT_DBG("conn %p", conn);
memset(&cp, 0, sizeof(cp));
cp.handle = cpu_to_le16(conn->handle);
cp.reason = HCI_ERROR_REJ_BAD_ADDR;
hci_send_cmd(conn->hdev, HCI_OP_LE_REJECT_CIS, sizeof(cp), &cp);
}
static void __iso_sock_close(struct sock *sk) static void __iso_sock_close(struct sock *sk)
{ {
BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
...@@ -621,6 +628,7 @@ static void __iso_sock_close(struct sock *sk) ...@@ -621,6 +628,7 @@ static void __iso_sock_close(struct sock *sk)
iso_sock_cleanup_listen(sk); iso_sock_cleanup_listen(sk);
break; break;
case BT_CONNECT:
case BT_CONNECTED: case BT_CONNECTED:
case BT_CONFIG: case BT_CONFIG:
if (iso_pi(sk)->conn->hcon) { if (iso_pi(sk)->conn->hcon) {
...@@ -636,21 +644,6 @@ static void __iso_sock_close(struct sock *sk) ...@@ -636,21 +644,6 @@ static void __iso_sock_close(struct sock *sk)
break; break;
case BT_CONNECT2: case BT_CONNECT2:
if (iso_pi(sk)->conn->hcon)
iso_conn_defer_reject(iso_pi(sk)->conn->hcon);
iso_chan_del(sk, ECONNRESET);
break;
case BT_CONNECT:
/* In case of DEFER_SETUP the hcon would be bound to CIG which
* needs to be removed so just call hci_conn_del so the cleanup
* callback do what is needed.
*/
if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) &&
iso_pi(sk)->conn->hcon) {
hci_conn_del(iso_pi(sk)->conn->hcon);
iso_pi(sk)->conn->hcon = NULL;
}
iso_chan_del(sk, ECONNRESET); iso_chan_del(sk, ECONNRESET);
break; break;
case BT_DISCONN: case BT_DISCONN:
...@@ -724,21 +717,13 @@ static struct sock *iso_sock_alloc(struct net *net, struct socket *sock, ...@@ -724,21 +717,13 @@ static struct sock *iso_sock_alloc(struct net *net, struct socket *sock,
{ {
struct sock *sk; struct sock *sk;
sk = sk_alloc(net, PF_BLUETOOTH, prio, &iso_proto, kern); sk = bt_sock_alloc(net, sock, &iso_proto, proto, prio, kern);
if (!sk) if (!sk)
return NULL; return NULL;
sock_init_data(sock, sk);
INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
sk->sk_destruct = iso_sock_destruct; sk->sk_destruct = iso_sock_destruct;
sk->sk_sndtimeo = ISO_CONN_TIMEOUT; sk->sk_sndtimeo = ISO_CONN_TIMEOUT;
sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_protocol = proto;
sk->sk_state = BT_OPEN;
/* Set address type as public as default src address is BDADDR_ANY */ /* Set address type as public as default src address is BDADDR_ANY */
iso_pi(sk)->src_type = BDADDR_LE_PUBLIC; iso_pi(sk)->src_type = BDADDR_LE_PUBLIC;
...@@ -1202,6 +1187,12 @@ static bool check_io_qos(struct bt_iso_io_qos *qos) ...@@ -1202,6 +1187,12 @@ static bool check_io_qos(struct bt_iso_io_qos *qos)
static bool check_ucast_qos(struct bt_iso_qos *qos) static bool check_ucast_qos(struct bt_iso_qos *qos)
{ {
if (qos->ucast.cig > 0xef && qos->ucast.cig != BT_ISO_QOS_CIG_UNSET)
return false;
if (qos->ucast.cis > 0xef && qos->ucast.cis != BT_ISO_QOS_CIS_UNSET)
return false;
if (qos->ucast.sca > 0x07) if (qos->ucast.sca > 0x07)
return false; return false;
...@@ -1291,6 +1282,18 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1291,6 +1282,18 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
break; break;
case BT_PKT_STATUS:
if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
err = -EFAULT;
break;
}
if (opt)
set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
else
clear_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
break;
case BT_ISO_QOS: case BT_ISO_QOS:
if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND && if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND &&
sk->sk_state != BT_CONNECT2) { sk->sk_state != BT_CONNECT2) {
...@@ -1376,6 +1379,12 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname, ...@@ -1376,6 +1379,12 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_PKT_STATUS:
if (put_user(test_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags),
(int __user *)optval))
err = -EFAULT;
break;
case BT_ISO_QOS: case BT_ISO_QOS:
qos = iso_sock_get_qos(sk); qos = iso_sock_get_qos(sk);
...@@ -1563,6 +1572,12 @@ static void iso_conn_ready(struct iso_conn *conn) ...@@ -1563,6 +1572,12 @@ static void iso_conn_ready(struct iso_conn *conn)
hci_conn_hold(hcon); hci_conn_hold(hcon);
iso_chan_add(conn, sk, parent); iso_chan_add(conn, sk, parent);
if (ev && ((struct hci_evt_le_big_sync_estabilished *)ev)->status) {
/* Trigger error signal on child socket */
sk->sk_err = ECONNREFUSED;
sk->sk_error_report(sk);
}
if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
sk->sk_state = BT_CONNECT2; sk->sk_state = BT_CONNECT2;
else else
...@@ -1631,15 +1646,17 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) ...@@ -1631,15 +1646,17 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
if (ev2->num_bis < iso_pi(sk)->bc_num_bis) if (ev2->num_bis < iso_pi(sk)->bc_num_bis)
iso_pi(sk)->bc_num_bis = ev2->num_bis; iso_pi(sk)->bc_num_bis = ev2->num_bis;
err = hci_le_big_create_sync(hdev, if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
&iso_pi(sk)->qos, err = hci_le_big_create_sync(hdev,
iso_pi(sk)->sync_handle, &iso_pi(sk)->qos,
iso_pi(sk)->bc_num_bis, iso_pi(sk)->sync_handle,
iso_pi(sk)->bc_bis); iso_pi(sk)->bc_num_bis,
if (err) { iso_pi(sk)->bc_bis);
bt_dev_err(hdev, "hci_le_big_create_sync: %d", if (err) {
err); bt_dev_err(hdev, "hci_le_big_create_sync: %d",
sk = NULL; err);
sk = NULL;
}
} }
} }
} else { } else {
...@@ -1676,13 +1693,18 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status) ...@@ -1676,13 +1693,18 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
} }
/* Create CIS if pending */ /* Create CIS if pending */
hci_le_create_cis(hcon); hci_le_create_cis_pending(hcon->hdev);
return; return;
} }
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
if (!status) { /* Similar to the success case, if HCI_CONN_BIG_SYNC_FAILED is set,
* queue the failed bis connection into the accept queue of the
* listening socket and wake up userspace, to inform the user about
* the BIG sync failed event.
*/
if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
struct iso_conn *conn; struct iso_conn *conn;
conn = iso_conn_add(hcon); conn = iso_conn_add(hcon);
...@@ -1757,6 +1779,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) ...@@ -1757,6 +1779,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
if (len == skb->len) { if (len == skb->len) {
/* Complete frame received */ /* Complete frame received */
hci_skb_pkt_status(skb) = flags & 0x03;
iso_recv_frame(conn, skb); iso_recv_frame(conn, skb);
return; return;
} }
...@@ -1778,6 +1801,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) ...@@ -1778,6 +1801,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
if (!conn->rx_skb) if (!conn->rx_skb)
goto drop; goto drop;
hci_skb_pkt_status(conn->rx_skb) = flags & 0x03;
skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
skb->len); skb->len);
conn->rx_len = len - skb->len; conn->rx_len = len - skb->len;
......
...@@ -178,21 +178,6 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) ...@@ -178,21 +178,6 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
return err; return err;
} }
static void l2cap_sock_init_pid(struct sock *sk)
{
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
/* Only L2CAP_MODE_EXT_FLOWCTL ever need to access the PID in order to
* group the channels being requested.
*/
if (chan->mode != L2CAP_MODE_EXT_FLOWCTL)
return;
spin_lock(&sk->sk_peer_lock);
sk->sk_peer_pid = get_pid(task_tgid(current));
spin_unlock(&sk->sk_peer_lock);
}
static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
int alen, int flags) int alen, int flags)
{ {
...@@ -268,8 +253,6 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, ...@@ -268,8 +253,6 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
chan->mode != L2CAP_MODE_EXT_FLOWCTL) chan->mode != L2CAP_MODE_EXT_FLOWCTL)
chan->mode = L2CAP_MODE_LE_FLOWCTL; chan->mode = L2CAP_MODE_LE_FLOWCTL;
l2cap_sock_init_pid(sk);
err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
&la.l2_bdaddr, la.l2_bdaddr_type); &la.l2_bdaddr, la.l2_bdaddr_type);
if (err) if (err)
...@@ -325,8 +308,6 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) ...@@ -325,8 +308,6 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
goto done; goto done;
} }
l2cap_sock_init_pid(sk);
sk->sk_max_ack_backlog = backlog; sk->sk_max_ack_backlog = backlog;
sk->sk_ack_backlog = 0; sk->sk_ack_backlog = 0;
...@@ -1858,21 +1839,13 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, ...@@ -1858,21 +1839,13 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
struct sock *sk; struct sock *sk;
struct l2cap_chan *chan; struct l2cap_chan *chan;
sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto, kern); sk = bt_sock_alloc(net, sock, &l2cap_proto, proto, prio, kern);
if (!sk) if (!sk)
return NULL; return NULL;
sock_init_data(sock, sk);
INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
sk->sk_destruct = l2cap_sock_destruct; sk->sk_destruct = l2cap_sock_destruct;
sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT; sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_protocol = proto;
sk->sk_state = BT_OPEN;
chan = l2cap_chan_create(); chan = l2cap_chan_create();
if (!chan) { if (!chan) {
sk_free(sk); sk_free(sk);
......
...@@ -944,6 +944,12 @@ static u32 get_current_settings(struct hci_dev *hdev) ...@@ -944,6 +944,12 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (cis_peripheral_capable(hdev)) if (cis_peripheral_capable(hdev))
settings |= MGMT_SETTING_CIS_PERIPHERAL; settings |= MGMT_SETTING_CIS_PERIPHERAL;
if (bis_capable(hdev))
settings |= MGMT_SETTING_ISO_BROADCASTER;
if (sync_recv_capable(hdev))
settings |= MGMT_SETTING_ISO_SYNC_RECEIVER;
return settings; return settings;
} }
...@@ -3580,18 +3586,6 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3580,18 +3586,6 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
return err; return err;
} }
static int abort_conn_sync(struct hci_dev *hdev, void *data)
{
struct hci_conn *conn;
u16 handle = PTR_ERR(data);
conn = hci_conn_hash_lookup_handle(hdev, handle);
if (!conn)
return 0;
return hci_abort_conn_sync(hdev, conn, HCI_ERROR_REMOTE_USER_TERM);
}
static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data, static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
...@@ -3642,8 +3636,7 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -3642,8 +3636,7 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
le_addr_type(addr->type)); le_addr_type(addr->type));
if (conn->conn_reason == CONN_REASON_PAIR_DEVICE) if (conn->conn_reason == CONN_REASON_PAIR_DEVICE)
hci_cmd_sync_queue(hdev, abort_conn_sync, ERR_PTR(conn->handle), hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
NULL);
unlock: unlock:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -8435,8 +8428,8 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev, ...@@ -8435,8 +8428,8 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
supported_flags = get_supported_adv_flags(hdev); supported_flags = get_supported_adv_flags(hdev);
rp->supported_flags = cpu_to_le32(supported_flags); rp->supported_flags = cpu_to_le32(supported_flags);
rp->max_adv_data_len = HCI_MAX_AD_LENGTH; rp->max_adv_data_len = max_adv_len(hdev);
rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH; rp->max_scan_rsp_len = max_adv_len(hdev);
rp->max_instances = hdev->le_num_of_adv_sets; rp->max_instances = hdev->le_num_of_adv_sets;
rp->num_instances = hdev->adv_instance_cnt; rp->num_instances = hdev->adv_instance_cnt;
...@@ -8472,7 +8465,7 @@ static u8 calculate_name_len(struct hci_dev *hdev) ...@@ -8472,7 +8465,7 @@ static u8 calculate_name_len(struct hci_dev *hdev)
static u8 tlv_data_max_len(struct hci_dev *hdev, u32 adv_flags, static u8 tlv_data_max_len(struct hci_dev *hdev, u32 adv_flags,
bool is_adv_data) bool is_adv_data)
{ {
u8 max_len = HCI_MAX_AD_LENGTH; u8 max_len = max_adv_len(hdev);
if (is_adv_data) { if (is_adv_data) {
if (adv_flags & (MGMT_ADV_FLAG_DISCOV | if (adv_flags & (MGMT_ADV_FLAG_DISCOV |
......
This diff is collapsed.
...@@ -268,18 +268,16 @@ static struct proto rfcomm_proto = { ...@@ -268,18 +268,16 @@ static struct proto rfcomm_proto = {
.obj_size = sizeof(struct rfcomm_pinfo) .obj_size = sizeof(struct rfcomm_pinfo)
}; };
static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio, int kern) static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock,
int proto, gfp_t prio, int kern)
{ {
struct rfcomm_dlc *d; struct rfcomm_dlc *d;
struct sock *sk; struct sock *sk;
sk = sk_alloc(net, PF_BLUETOOTH, prio, &rfcomm_proto, kern); sk = bt_sock_alloc(net, sock, &rfcomm_proto, proto, prio, kern);
if (!sk) if (!sk)
return NULL; return NULL;
sock_init_data(sock, sk);
INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
d = rfcomm_dlc_alloc(prio); d = rfcomm_dlc_alloc(prio);
if (!d) { if (!d) {
sk_free(sk); sk_free(sk);
...@@ -298,11 +296,6 @@ static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int ...@@ -298,11 +296,6 @@ static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int
sk->sk_sndbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10; sk->sk_sndbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
sk->sk_rcvbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10; sk->sk_rcvbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_protocol = proto;
sk->sk_state = BT_OPEN;
bt_sock_link(&rfcomm_sk_list, sk); bt_sock_link(&rfcomm_sk_list, sk);
BT_DBG("sk %p", sk); BT_DBG("sk %p", sk);
......
This diff is collapsed.
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