mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== pull request: bluetooth-next 2020-06-01 Here's one last bluetooth-next pull request for 5.8, which I hope can still be accepted. - Enabled Wide-Band Speech (WBS) support for Qualcomm wcn3991 - Multiple fixes/imprvovements to Qualcomm-based devices - Fix GAP/SEC/SEM/BI-10-C qualfication test case - Added support for Broadcom BCM4350C5 device - Several other smaller fixes & improvements Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
07f6ecec65
10 changed files with 154 additions and 71 deletions
|
@ -414,11 +414,12 @@ static const struct bcm_subver_table bcm_usb_subver_table[] = {
|
|||
{ 0x2118, "BCM20702A0" }, /* 001.001.024 */
|
||||
{ 0x2126, "BCM4335A0" }, /* 001.001.038 */
|
||||
{ 0x220e, "BCM20702A1" }, /* 001.002.014 */
|
||||
{ 0x230f, "BCM4354A2" }, /* 001.003.015 */
|
||||
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */
|
||||
{ 0x4106, "BCM4335B0" }, /* 002.001.006 */
|
||||
{ 0x410e, "BCM20702B0" }, /* 002.001.014 */
|
||||
{ 0x6109, "BCM4335C0" }, /* 003.001.009 */
|
||||
{ 0x610c, "BCM4354" }, /* 003.001.012 */
|
||||
{ 0x6607, "BCM4350C5" }, /* 003.006.007 */
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -695,8 +695,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev)
|
|||
|
||||
/* Send a dummy byte 0xff to activate the new baudrate */
|
||||
param = 0xff;
|
||||
err = serdev_device_write(bdev->serdev, ¶m, sizeof(param),
|
||||
MAX_SCHEDULE_TIMEOUT);
|
||||
err = serdev_device_write_buf(bdev->serdev, ¶m, sizeof(param));
|
||||
if (err < 0 || err < sizeof(param))
|
||||
return err;
|
||||
|
||||
|
@ -1015,7 +1014,7 @@ static int btmtkuart_probe(struct serdev_device *serdev)
|
|||
if (btmtkuart_is_standalone(bdev)) {
|
||||
err = clk_prepare_enable(bdev->osc);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto err_hci_free_dev;
|
||||
|
||||
if (bdev->boot) {
|
||||
gpiod_set_value_cansleep(bdev->boot, 1);
|
||||
|
@ -1028,10 +1027,8 @@ static int btmtkuart_probe(struct serdev_device *serdev)
|
|||
|
||||
/* Power on */
|
||||
err = regulator_enable(bdev->vcc);
|
||||
if (err < 0) {
|
||||
clk_disable_unprepare(bdev->osc);
|
||||
return err;
|
||||
}
|
||||
if (err < 0)
|
||||
goto err_clk_disable_unprepare;
|
||||
|
||||
/* Reset if the reset-gpios is available otherwise the board
|
||||
* -level design should be guaranteed.
|
||||
|
@ -1063,7 +1060,6 @@ static int btmtkuart_probe(struct serdev_device *serdev)
|
|||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
dev_err(&serdev->dev, "Can't register HCI device\n");
|
||||
hci_free_dev(hdev);
|
||||
goto err_regulator_disable;
|
||||
}
|
||||
|
||||
|
@ -1072,6 +1068,11 @@ static int btmtkuart_probe(struct serdev_device *serdev)
|
|||
err_regulator_disable:
|
||||
if (btmtkuart_is_standalone(bdev))
|
||||
regulator_disable(bdev->vcc);
|
||||
err_clk_disable_unprepare:
|
||||
if (btmtkuart_is_standalone(bdev))
|
||||
clk_disable_unprepare(bdev->osc);
|
||||
err_hci_free_dev:
|
||||
hci_free_dev(hdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -74,17 +74,21 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version,
|
|||
|
||||
ver = (struct qca_btsoc_version *)(edl->data);
|
||||
|
||||
BT_DBG("%s: Product:0x%08x", hdev->name, le32_to_cpu(ver->product_id));
|
||||
BT_DBG("%s: Patch :0x%08x", hdev->name, le16_to_cpu(ver->patch_ver));
|
||||
BT_DBG("%s: ROM :0x%08x", hdev->name, le16_to_cpu(ver->rom_ver));
|
||||
BT_DBG("%s: SOC :0x%08x", hdev->name, le32_to_cpu(ver->soc_id));
|
||||
bt_dev_info(hdev, "QCA Product ID :0x%08x",
|
||||
le32_to_cpu(ver->product_id));
|
||||
bt_dev_info(hdev, "QCA SOC Version :0x%08x",
|
||||
le32_to_cpu(ver->soc_id));
|
||||
bt_dev_info(hdev, "QCA ROM Version :0x%08x",
|
||||
le16_to_cpu(ver->rom_ver));
|
||||
bt_dev_info(hdev, "QCA Patch Version:0x%08x",
|
||||
le16_to_cpu(ver->patch_ver));
|
||||
|
||||
/* QCA chipset version can be decided by patch and SoC
|
||||
* version, combination with upper 2 bytes from SoC
|
||||
* and lower 2 bytes from patch will be used.
|
||||
*/
|
||||
*soc_version = (le32_to_cpu(ver->soc_id) << 16) |
|
||||
(le16_to_cpu(ver->rom_ver) & 0x0000ffff);
|
||||
(le16_to_cpu(ver->rom_ver) & 0x0000ffff);
|
||||
if (*soc_version == 0)
|
||||
err = -EILSEQ;
|
||||
|
||||
|
|
|
@ -75,6 +75,9 @@ enum qca_flags {
|
|||
QCA_HW_ERROR_EVENT
|
||||
};
|
||||
|
||||
enum qca_capabilities {
|
||||
QCA_CAP_WIDEBAND_SPEECH = BIT(0),
|
||||
};
|
||||
|
||||
/* HCI_IBS transmit side sleep protocol states */
|
||||
enum tx_ibs_states {
|
||||
|
@ -111,6 +114,7 @@ struct qca_memdump_data {
|
|||
char *memdump_buf_tail;
|
||||
u32 current_seq_no;
|
||||
u32 received_dump;
|
||||
u32 ram_dump_size;
|
||||
};
|
||||
|
||||
struct qca_memdump_event_hdr {
|
||||
|
@ -187,10 +191,11 @@ struct qca_vreg {
|
|||
unsigned int load_uA;
|
||||
};
|
||||
|
||||
struct qca_vreg_data {
|
||||
struct qca_device_data {
|
||||
enum qca_btsoc_type soc_type;
|
||||
struct qca_vreg *vregs;
|
||||
size_t num_vregs;
|
||||
uint32_t capabilities;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -972,6 +977,8 @@ static void qca_controller_memdump(struct work_struct *work)
|
|||
char nullBuff[QCA_DUMP_PACKET_SIZE] = { 0 };
|
||||
u16 seq_no;
|
||||
u32 dump_size;
|
||||
u32 rx_size;
|
||||
enum qca_btsoc_type soc_type = qca_soc_type(hu);
|
||||
|
||||
while ((skb = skb_dequeue(&qca->rx_memdump_q))) {
|
||||
|
||||
|
@ -1021,10 +1028,12 @@ static void qca_controller_memdump(struct work_struct *work)
|
|||
dump_size);
|
||||
queue_delayed_work(qca->workqueue,
|
||||
&qca->ctrl_memdump_timeout,
|
||||
msecs_to_jiffies(MEMDUMP_TIMEOUT_MS));
|
||||
msecs_to_jiffies(MEMDUMP_TIMEOUT_MS)
|
||||
);
|
||||
|
||||
skb_pull(skb, sizeof(dump_size));
|
||||
memdump_buf = vmalloc(dump_size);
|
||||
qca_memdump->ram_dump_size = dump_size;
|
||||
qca_memdump->memdump_buf_head = memdump_buf;
|
||||
qca_memdump->memdump_buf_tail = memdump_buf;
|
||||
}
|
||||
|
@ -1047,26 +1056,57 @@ static void qca_controller_memdump(struct work_struct *work)
|
|||
* the controller. In such cases let us store the dummy
|
||||
* packets in the buffer.
|
||||
*/
|
||||
/* For QCA6390, controller does not lost packets but
|
||||
* sequence number field of packat sometimes has error
|
||||
* bits, so skip this checking for missing packet.
|
||||
*/
|
||||
while ((seq_no > qca_memdump->current_seq_no + 1) &&
|
||||
seq_no != QCA_LAST_SEQUENCE_NUM) {
|
||||
(soc_type != QCA_QCA6390) &&
|
||||
seq_no != QCA_LAST_SEQUENCE_NUM) {
|
||||
bt_dev_err(hu->hdev, "QCA controller missed packet:%d",
|
||||
qca_memdump->current_seq_no);
|
||||
rx_size = qca_memdump->received_dump;
|
||||
rx_size += QCA_DUMP_PACKET_SIZE;
|
||||
if (rx_size > qca_memdump->ram_dump_size) {
|
||||
bt_dev_err(hu->hdev,
|
||||
"QCA memdump received %d, no space for missed packet",
|
||||
qca_memdump->received_dump);
|
||||
break;
|
||||
}
|
||||
memcpy(memdump_buf, nullBuff, QCA_DUMP_PACKET_SIZE);
|
||||
memdump_buf = memdump_buf + QCA_DUMP_PACKET_SIZE;
|
||||
qca_memdump->received_dump += QCA_DUMP_PACKET_SIZE;
|
||||
qca_memdump->current_seq_no++;
|
||||
}
|
||||
|
||||
memcpy(memdump_buf, (unsigned char *) skb->data, skb->len);
|
||||
memdump_buf = memdump_buf + skb->len;
|
||||
qca_memdump->memdump_buf_tail = memdump_buf;
|
||||
qca_memdump->current_seq_no = seq_no + 1;
|
||||
qca_memdump->received_dump += skb->len;
|
||||
rx_size = qca_memdump->received_dump + skb->len;
|
||||
if (rx_size <= qca_memdump->ram_dump_size) {
|
||||
if ((seq_no != QCA_LAST_SEQUENCE_NUM) &&
|
||||
(seq_no != qca_memdump->current_seq_no))
|
||||
bt_dev_err(hu->hdev,
|
||||
"QCA memdump unexpected packet %d",
|
||||
seq_no);
|
||||
bt_dev_dbg(hu->hdev,
|
||||
"QCA memdump packet %d with length %d",
|
||||
seq_no, skb->len);
|
||||
memcpy(memdump_buf, (unsigned char *)skb->data,
|
||||
skb->len);
|
||||
memdump_buf = memdump_buf + skb->len;
|
||||
qca_memdump->memdump_buf_tail = memdump_buf;
|
||||
qca_memdump->current_seq_no = seq_no + 1;
|
||||
qca_memdump->received_dump += skb->len;
|
||||
} else {
|
||||
bt_dev_err(hu->hdev,
|
||||
"QCA memdump received %d, no space for packet %d",
|
||||
qca_memdump->received_dump, seq_no);
|
||||
}
|
||||
qca->qca_memdump = qca_memdump;
|
||||
kfree_skb(skb);
|
||||
if (seq_no == QCA_LAST_SEQUENCE_NUM) {
|
||||
bt_dev_info(hu->hdev, "QCA writing crash dump of size %d bytes",
|
||||
qca_memdump->received_dump);
|
||||
bt_dev_info(hu->hdev,
|
||||
"QCA memdump Done, received %d, total %d",
|
||||
qca_memdump->received_dump,
|
||||
qca_memdump->ram_dump_size);
|
||||
memdump_buf = qca_memdump->memdump_buf_head;
|
||||
dev_coredumpv(&hu->serdev->dev, memdump_buf,
|
||||
qca_memdump->received_dump, GFP_KERNEL);
|
||||
|
@ -1691,7 +1731,7 @@ static const struct hci_uart_proto qca_proto = {
|
|||
.dequeue = qca_dequeue,
|
||||
};
|
||||
|
||||
static const struct qca_vreg_data qca_soc_data_wcn3990 = {
|
||||
static const struct qca_device_data qca_soc_data_wcn3990 = {
|
||||
.soc_type = QCA_WCN3990,
|
||||
.vregs = (struct qca_vreg []) {
|
||||
{ "vddio", 15000 },
|
||||
|
@ -1702,7 +1742,7 @@ static const struct qca_vreg_data qca_soc_data_wcn3990 = {
|
|||
.num_vregs = 4,
|
||||
};
|
||||
|
||||
static const struct qca_vreg_data qca_soc_data_wcn3991 = {
|
||||
static const struct qca_device_data qca_soc_data_wcn3991 = {
|
||||
.soc_type = QCA_WCN3991,
|
||||
.vregs = (struct qca_vreg []) {
|
||||
{ "vddio", 15000 },
|
||||
|
@ -1711,9 +1751,10 @@ static const struct qca_vreg_data qca_soc_data_wcn3991 = {
|
|||
{ "vddch0", 450000 },
|
||||
},
|
||||
.num_vregs = 4,
|
||||
.capabilities = QCA_CAP_WIDEBAND_SPEECH,
|
||||
};
|
||||
|
||||
static const struct qca_vreg_data qca_soc_data_wcn3998 = {
|
||||
static const struct qca_device_data qca_soc_data_wcn3998 = {
|
||||
.soc_type = QCA_WCN3998,
|
||||
.vregs = (struct qca_vreg []) {
|
||||
{ "vddio", 10000 },
|
||||
|
@ -1724,7 +1765,7 @@ static const struct qca_vreg_data qca_soc_data_wcn3998 = {
|
|||
.num_vregs = 4,
|
||||
};
|
||||
|
||||
static const struct qca_vreg_data qca_soc_data_qca6390 = {
|
||||
static const struct qca_device_data qca_soc_data_qca6390 = {
|
||||
.soc_type = QCA_QCA6390,
|
||||
.num_vregs = 0,
|
||||
};
|
||||
|
@ -1860,7 +1901,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
|
|||
{
|
||||
struct qca_serdev *qcadev;
|
||||
struct hci_dev *hdev;
|
||||
const struct qca_vreg_data *data;
|
||||
const struct qca_device_data *data;
|
||||
int err;
|
||||
bool power_ctrl_enabled = true;
|
||||
|
||||
|
@ -1942,12 +1983,19 @@ static int qca_serdev_probe(struct serdev_device *serdev)
|
|||
}
|
||||
}
|
||||
|
||||
hdev = qcadev->serdev_hu.hdev;
|
||||
|
||||
if (power_ctrl_enabled) {
|
||||
hdev = qcadev->serdev_hu.hdev;
|
||||
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
|
||||
hdev->shutdown = qca_power_off;
|
||||
}
|
||||
|
||||
/* Wideband speech support must be set per driver since it can't be
|
||||
* queried via hci.
|
||||
*/
|
||||
if (data && (data->capabilities & QCA_CAP_WIDEBAND_SPEECH))
|
||||
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1963,10 +2011,43 @@ static void qca_serdev_remove(struct serdev_device *serdev)
|
|||
hci_uart_unregister_device(&qcadev->serdev_hu);
|
||||
}
|
||||
|
||||
static void qca_serdev_shutdown(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
|
||||
struct serdev_device *serdev = to_serdev_device(dev);
|
||||
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
|
||||
const u8 ibs_wake_cmd[] = { 0xFD };
|
||||
const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 };
|
||||
|
||||
if (qcadev->btsoc_type == QCA_QCA6390) {
|
||||
serdev_device_write_flush(serdev);
|
||||
ret = serdev_device_write_buf(serdev, ibs_wake_cmd,
|
||||
sizeof(ibs_wake_cmd));
|
||||
if (ret < 0) {
|
||||
BT_ERR("QCA send IBS_WAKE_IND error: %d", ret);
|
||||
return;
|
||||
}
|
||||
serdev_device_wait_until_sent(serdev, timeout);
|
||||
usleep_range(8000, 10000);
|
||||
|
||||
serdev_device_write_flush(serdev);
|
||||
ret = serdev_device_write_buf(serdev, edl_reset_soc_cmd,
|
||||
sizeof(edl_reset_soc_cmd));
|
||||
if (ret < 0) {
|
||||
BT_ERR("QCA send EDL_RESET_REQ error: %d", ret);
|
||||
return;
|
||||
}
|
||||
serdev_device_wait_until_sent(serdev, timeout);
|
||||
usleep_range(8000, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
static int __maybe_unused qca_suspend(struct device *dev)
|
||||
{
|
||||
struct hci_dev *hdev = container_of(dev, struct hci_dev, dev);
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
struct serdev_device *serdev = to_serdev_device(dev);
|
||||
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
|
||||
struct hci_uart *hu = &qcadev->serdev_hu;
|
||||
struct qca_data *qca = hu->priv;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
@ -2045,8 +2126,9 @@ static int __maybe_unused qca_suspend(struct device *dev)
|
|||
|
||||
static int __maybe_unused qca_resume(struct device *dev)
|
||||
{
|
||||
struct hci_dev *hdev = container_of(dev, struct hci_dev, dev);
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
struct serdev_device *serdev = to_serdev_device(dev);
|
||||
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
|
||||
struct hci_uart *hu = &qcadev->serdev_hu;
|
||||
struct qca_data *qca = hu->priv;
|
||||
|
||||
clear_bit(QCA_SUSPENDING, &qca->flags);
|
||||
|
@ -2088,6 +2170,7 @@ static struct serdev_device_driver qca_serdev_driver = {
|
|||
.name = "hci_uart_qca",
|
||||
.of_match_table = of_match_ptr(qca_bluetooth_of_match),
|
||||
.acpi_match_table = ACPI_PTR(qca_bluetooth_acpi_match),
|
||||
.shutdown = qca_serdev_shutdown,
|
||||
.pm = &qca_pm_ops,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1381,10 +1381,26 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
|
|||
conn->security_cfm_cb(conn, status);
|
||||
}
|
||||
|
||||
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
|
||||
__u8 encrypt)
|
||||
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
|
||||
{
|
||||
struct hci_cb *cb;
|
||||
__u8 encrypt;
|
||||
|
||||
if (conn->state == BT_CONFIG) {
|
||||
if (status)
|
||||
conn->state = BT_CONNECTED;
|
||||
|
||||
hci_connect_cfm(conn, status);
|
||||
hci_conn_drop(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
encrypt = 0x00;
|
||||
else if (test_bit(HCI_CONN_AES_CCM, &conn->flags))
|
||||
encrypt = 0x02;
|
||||
else
|
||||
encrypt = 0x01;
|
||||
|
||||
if (conn->sec_level == BT_SECURITY_SDP)
|
||||
conn->sec_level = BT_SECURITY_LOW;
|
||||
|
|
|
@ -499,7 +499,7 @@ struct l2cap_ecred_conn_req {
|
|||
__le16 mtu;
|
||||
__le16 mps;
|
||||
__le16 credits;
|
||||
__le16 scid[0];
|
||||
__le16 scid[];
|
||||
} __packed;
|
||||
|
||||
struct l2cap_ecred_conn_rsp {
|
||||
|
@ -507,13 +507,13 @@ struct l2cap_ecred_conn_rsp {
|
|||
__le16 mps;
|
||||
__le16 credits;
|
||||
__le16 result;
|
||||
__le16 dcid[0];
|
||||
__le16 dcid[];
|
||||
};
|
||||
|
||||
struct l2cap_ecred_reconf_req {
|
||||
__le16 mtu;
|
||||
__le16 mps;
|
||||
__le16 scid[0];
|
||||
__le16 scid[];
|
||||
} __packed;
|
||||
|
||||
#define L2CAP_RECONF_SUCCESS 0x0000
|
||||
|
|
|
@ -225,8 +225,6 @@ static void hci_acl_create_connection(struct hci_conn *conn)
|
|||
}
|
||||
|
||||
memcpy(conn->dev_class, ie->data.dev_class, 3);
|
||||
if (ie->data.ssp_mode > 0)
|
||||
set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
|
||||
}
|
||||
|
||||
cp.pkt_type = cpu_to_le16(conn->pkt_type);
|
||||
|
|
|
@ -2931,7 +2931,7 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
&cp);
|
||||
} else {
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
hci_encrypt_cfm(conn, ev->status, 0x00);
|
||||
hci_encrypt_cfm(conn, ev->status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3016,22 +3016,7 @@ static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status,
|
|||
conn->enc_key_size = rp->key_size;
|
||||
}
|
||||
|
||||
if (conn->state == BT_CONFIG) {
|
||||
conn->state = BT_CONNECTED;
|
||||
hci_connect_cfm(conn, 0);
|
||||
hci_conn_drop(conn);
|
||||
} else {
|
||||
u8 encrypt;
|
||||
|
||||
if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
||||
encrypt = 0x00;
|
||||
else if (test_bit(HCI_CONN_AES_CCM, &conn->flags))
|
||||
encrypt = 0x02;
|
||||
else
|
||||
encrypt = 0x01;
|
||||
|
||||
hci_encrypt_cfm(conn, 0, encrypt);
|
||||
}
|
||||
hci_encrypt_cfm(conn, 0);
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
|
@ -3149,14 +3134,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
notify:
|
||||
if (conn->state == BT_CONFIG) {
|
||||
if (!ev->status)
|
||||
conn->state = BT_CONNECTED;
|
||||
|
||||
hci_connect_cfm(conn, ev->status);
|
||||
hci_conn_drop(conn);
|
||||
} else
|
||||
hci_encrypt_cfm(conn, ev->status, ev->encrypt);
|
||||
hci_encrypt_cfm(conn, ev->status);
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
|
@ -4337,6 +4315,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
|
|||
case 0x11: /* Unsupported Feature or Parameter Value */
|
||||
case 0x1c: /* SCO interval rejected */
|
||||
case 0x1a: /* Unsupported Remote Feature */
|
||||
case 0x1e: /* Invalid LMP Parameters */
|
||||
case 0x1f: /* Unspecified error */
|
||||
case 0x20: /* Unsupported LMP Parameter value */
|
||||
if (conn->out) {
|
||||
|
|
|
@ -64,15 +64,13 @@ static void rfcomm_sk_data_ready(struct rfcomm_dlc *d, struct sk_buff *skb)
|
|||
static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
|
||||
{
|
||||
struct sock *sk = d->owner, *parent;
|
||||
unsigned long flags;
|
||||
|
||||
if (!sk)
|
||||
return;
|
||||
|
||||
BT_DBG("dlc %p state %ld err %d", d, d->state, err);
|
||||
|
||||
local_irq_save(flags);
|
||||
bh_lock_sock(sk);
|
||||
spin_lock_bh(&sk->sk_lock.slock);
|
||||
|
||||
if (err)
|
||||
sk->sk_err = err;
|
||||
|
@ -93,8 +91,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
|
|||
sk->sk_state_change(sk);
|
||||
}
|
||||
|
||||
bh_unlock_sock(sk);
|
||||
local_irq_restore(flags);
|
||||
spin_unlock_bh(&sk->sk_lock.slock);
|
||||
|
||||
if (parent && sock_flag(sk, SOCK_ZAPPED)) {
|
||||
/* We have to drop DLC lock here, otherwise
|
||||
|
|
|
@ -730,6 +730,10 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
|
|||
struct hci_dev *hdev = conn->hcon->hdev;
|
||||
struct smp_chan *smp = chan->data;
|
||||
|
||||
if (conn->hcon->pending_sec_level == BT_SECURITY_FIPS &&
|
||||
max_key_size != SMP_MAX_ENC_KEY_SIZE)
|
||||
return SMP_ENC_KEY_SIZE;
|
||||
|
||||
if (max_key_size > hdev->le_max_key_size ||
|
||||
max_key_size < SMP_MIN_ENC_KEY_SIZE)
|
||||
return SMP_ENC_KEY_SIZE;
|
||||
|
|
Loading…
Reference in a new issue