mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
Revert "Bluetooth: hci_sync: Fix overwriting request callback"
This reverts commit da77c1d39b which is
commit 2615fd9a7c2507eb3be3fbe49dcec88a2f56454a upstream.
It is reported to cause regressions in the 6.1.y tree, so revert it for
now.
Link: https://lore.kernel.org/all/CADRbXaDqx6S+7tzdDPPEpRu9eDLrHQkqoWTTGfKJSRxY=hT5MQ@mail.gmail.com/
Reported-by: Jeremy Lainé <jeremy.laine@m4x.org>
Cc: Salvatore Bonaccorso <carnil@debian.org>
Cc: Mike <user.service2016@gmail.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Johan Hedberg <johan.hedberg@gmail.com>
Cc: Paul Menzel <pmenzel@molgen.mpg.de>
Cc: Pauli Virtanen <pav@iki.fi>
Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
@@ -544,7 +544,6 @@ struct hci_dev {
|
|||||||
__u32 req_status;
|
__u32 req_status;
|
||||||
__u32 req_result;
|
__u32 req_result;
|
||||||
struct sk_buff *req_skb;
|
struct sk_buff *req_skb;
|
||||||
struct sk_buff *req_rsp;
|
|
||||||
|
|
||||||
void *smp_data;
|
void *smp_data;
|
||||||
void *smp_bredr_data;
|
void *smp_bredr_data;
|
||||||
|
|||||||
@@ -2816,7 +2816,7 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
|
|||||||
case HCI_EV_LE_CONN_COMPLETE:
|
case HCI_EV_LE_CONN_COMPLETE:
|
||||||
case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
|
case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
|
||||||
case HCI_EVT_LE_CIS_ESTABLISHED:
|
case HCI_EVT_LE_CIS_ESTABLISHED:
|
||||||
hci_cmd_sync_cancel(hdev, ECANCELED);
|
hci_cmd_sync_cancel(hdev, -ECANCELED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1452,8 +1452,8 @@ static void hci_cmd_timeout(struct work_struct *work)
|
|||||||
struct hci_dev *hdev = container_of(work, struct hci_dev,
|
struct hci_dev *hdev = container_of(work, struct hci_dev,
|
||||||
cmd_timer.work);
|
cmd_timer.work);
|
||||||
|
|
||||||
if (hdev->req_skb) {
|
if (hdev->sent_cmd) {
|
||||||
u16 opcode = hci_skb_opcode(hdev->req_skb);
|
u16 opcode = hci_skb_opcode(hdev->sent_cmd);
|
||||||
|
|
||||||
bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode);
|
bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode);
|
||||||
|
|
||||||
@@ -2762,7 +2762,6 @@ void hci_release_dev(struct hci_dev *hdev)
|
|||||||
|
|
||||||
ida_simple_remove(&hci_index_ida, hdev->id);
|
ida_simple_remove(&hci_index_ida, hdev->id);
|
||||||
kfree_skb(hdev->sent_cmd);
|
kfree_skb(hdev->sent_cmd);
|
||||||
kfree_skb(hdev->req_skb);
|
|
||||||
kfree_skb(hdev->recv_event);
|
kfree_skb(hdev->recv_event);
|
||||||
kfree(hdev);
|
kfree(hdev);
|
||||||
}
|
}
|
||||||
@@ -3092,33 +3091,21 @@ int __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen,
|
|||||||
EXPORT_SYMBOL(__hci_cmd_send);
|
EXPORT_SYMBOL(__hci_cmd_send);
|
||||||
|
|
||||||
/* Get data from the previously sent command */
|
/* Get data from the previously sent command */
|
||||||
static void *hci_cmd_data(struct sk_buff *skb, __u16 opcode)
|
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
|
||||||
{
|
{
|
||||||
struct hci_command_hdr *hdr;
|
struct hci_command_hdr *hdr;
|
||||||
|
|
||||||
if (!skb || skb->len < HCI_COMMAND_HDR_SIZE)
|
if (!hdev->sent_cmd)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
hdr = (void *)skb->data;
|
hdr = (void *) hdev->sent_cmd->data;
|
||||||
|
|
||||||
if (hdr->opcode != cpu_to_le16(opcode))
|
if (hdr->opcode != cpu_to_le16(opcode))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return skb->data + HCI_COMMAND_HDR_SIZE;
|
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
|
||||||
}
|
|
||||||
|
|
||||||
/* Get data from the previously sent command */
|
return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE;
|
||||||
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
|
|
||||||
{
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
/* Check if opcode matches last sent command */
|
|
||||||
data = hci_cmd_data(hdev->sent_cmd, opcode);
|
|
||||||
if (!data)
|
|
||||||
/* Check if opcode matches last request */
|
|
||||||
data = hci_cmd_data(hdev->req_skb, opcode);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get data from last received event */
|
/* Get data from last received event */
|
||||||
@@ -4014,19 +4001,17 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
|
|||||||
if (!status && !hci_req_is_complete(hdev))
|
if (!status && !hci_req_is_complete(hdev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
skb = hdev->req_skb;
|
|
||||||
|
|
||||||
/* If this was the last command in a request the complete
|
/* If this was the last command in a request the complete
|
||||||
* callback would be found in hdev->req_skb instead of the
|
* callback would be found in hdev->sent_cmd instead of the
|
||||||
* command queue (hdev->cmd_q).
|
* command queue (hdev->cmd_q).
|
||||||
*/
|
*/
|
||||||
if (skb && bt_cb(skb)->hci.req_flags & HCI_REQ_SKB) {
|
if (bt_cb(hdev->sent_cmd)->hci.req_flags & HCI_REQ_SKB) {
|
||||||
*req_complete_skb = bt_cb(skb)->hci.req_complete_skb;
|
*req_complete_skb = bt_cb(hdev->sent_cmd)->hci.req_complete_skb;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skb && bt_cb(skb)->hci.req_complete) {
|
if (bt_cb(hdev->sent_cmd)->hci.req_complete) {
|
||||||
*req_complete = bt_cb(skb)->hci.req_complete;
|
*req_complete = bt_cb(hdev->sent_cmd)->hci.req_complete;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4143,11 +4128,8 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hci_req_status_pend(hdev) &&
|
if (hci_req_status_pend(hdev))
|
||||||
!hci_dev_test_and_set_flag(hdev, HCI_CMD_PENDING)) {
|
hci_dev_set_flag(hdev, HCI_CMD_PENDING);
|
||||||
kfree_skb(hdev->req_skb);
|
|
||||||
hdev->req_skb = skb_clone(skb, GFP_KERNEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic_dec(&hdev->cmd_cnt);
|
atomic_dec(&hdev->cmd_cnt);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4354,7 +4354,7 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, void *data,
|
|||||||
* (since for this kind of commands there will not be a command
|
* (since for this kind of commands there will not be a command
|
||||||
* complete event).
|
* complete event).
|
||||||
*/
|
*/
|
||||||
if (ev->status || (hdev->req_skb && !hci_skb_event(hdev->req_skb))) {
|
if (ev->status || (hdev->sent_cmd && !hci_skb_event(hdev->sent_cmd))) {
|
||||||
hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
|
hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
|
||||||
req_complete_skb);
|
req_complete_skb);
|
||||||
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
|
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
|
||||||
@@ -7171,10 +7171,10 @@ static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
|
|||||||
bt_dev_dbg(hdev, "subevent 0x%2.2x", ev->subevent);
|
bt_dev_dbg(hdev, "subevent 0x%2.2x", ev->subevent);
|
||||||
|
|
||||||
/* Only match event if command OGF is for LE */
|
/* Only match event if command OGF is for LE */
|
||||||
if (hdev->req_skb &&
|
if (hdev->sent_cmd &&
|
||||||
hci_opcode_ogf(hci_skb_opcode(hdev->req_skb)) == 0x08 &&
|
hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) == 0x08 &&
|
||||||
hci_skb_event(hdev->req_skb) == ev->subevent) {
|
hci_skb_event(hdev->sent_cmd) == ev->subevent) {
|
||||||
*opcode = hci_skb_opcode(hdev->req_skb);
|
*opcode = hci_skb_opcode(hdev->sent_cmd);
|
||||||
hci_req_cmd_complete(hdev, *opcode, 0x00, req_complete,
|
hci_req_cmd_complete(hdev, *opcode, 0x00, req_complete,
|
||||||
req_complete_skb);
|
req_complete_skb);
|
||||||
}
|
}
|
||||||
@@ -7561,10 +7561,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Only match event if command OGF is not for LE */
|
/* Only match event if command OGF is not for LE */
|
||||||
if (hdev->req_skb &&
|
if (hdev->sent_cmd &&
|
||||||
hci_opcode_ogf(hci_skb_opcode(hdev->req_skb)) != 0x08 &&
|
hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) != 0x08 &&
|
||||||
hci_skb_event(hdev->req_skb) == event) {
|
hci_skb_event(hdev->sent_cmd) == event) {
|
||||||
hci_req_cmd_complete(hdev, hci_skb_opcode(hdev->req_skb),
|
hci_req_cmd_complete(hdev, hci_skb_opcode(hdev->sent_cmd),
|
||||||
status, &req_complete, &req_complete_skb);
|
status, &req_complete, &req_complete_skb);
|
||||||
req_evt = event;
|
req_evt = event;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ static void hci_cmd_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
|
|||||||
hdev->req_result = result;
|
hdev->req_result = result;
|
||||||
hdev->req_status = HCI_REQ_DONE;
|
hdev->req_status = HCI_REQ_DONE;
|
||||||
|
|
||||||
/* Free the request command so it is not used as response */
|
|
||||||
kfree_skb(hdev->req_skb);
|
|
||||||
hdev->req_skb = NULL;
|
|
||||||
|
|
||||||
if (skb) {
|
if (skb) {
|
||||||
struct sock *sk = hci_skb_sk(skb);
|
struct sock *sk = hci_skb_sk(skb);
|
||||||
|
|
||||||
@@ -42,7 +38,7 @@ static void hci_cmd_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
|
|||||||
if (sk)
|
if (sk)
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
|
|
||||||
hdev->req_rsp = skb_get(skb);
|
hdev->req_skb = skb_get(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
wake_up_interruptible(&hdev->req_wait_q);
|
wake_up_interruptible(&hdev->req_wait_q);
|
||||||
@@ -190,8 +186,8 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
|
|||||||
|
|
||||||
hdev->req_status = 0;
|
hdev->req_status = 0;
|
||||||
hdev->req_result = 0;
|
hdev->req_result = 0;
|
||||||
skb = hdev->req_rsp;
|
skb = hdev->req_skb;
|
||||||
hdev->req_rsp = NULL;
|
hdev->req_skb = NULL;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "end: err %d", err);
|
bt_dev_dbg(hdev, "end: err %d", err);
|
||||||
|
|
||||||
@@ -4941,11 +4937,6 @@ int hci_dev_open_sync(struct hci_dev *hdev)
|
|||||||
hdev->sent_cmd = NULL;
|
hdev->sent_cmd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdev->req_skb) {
|
|
||||||
kfree_skb(hdev->req_skb);
|
|
||||||
hdev->req_skb = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||||
hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
|
hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
|
||||||
|
|
||||||
@@ -5107,12 +5098,6 @@ int hci_dev_close_sync(struct hci_dev *hdev)
|
|||||||
hdev->sent_cmd = NULL;
|
hdev->sent_cmd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Drop last request */
|
|
||||||
if (hdev->req_skb) {
|
|
||||||
kfree_skb(hdev->req_skb);
|
|
||||||
hdev->req_skb = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||||
hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
|
hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user