bluetooth: hci_qca: Fix QCA6390 memdump failure
PATCH v4 1/1 bluetooth: hci_qca: Fix QCA6390 memdump failure
QCA6390 memdump VSE sometimes come to bluetooth driver with wrong sequence number as illustrated as follows:
frame # in dec: frame data in hex
1396: ff fd 01 08 74 05 00 37 8f 14
1397: ff fd 01 08 75 05 00 ff bf 38
1414: ff fd 01 08 86 05 00 fb 5e 4b
1399: ff fd 01 08 77 05 00 f3 44 0a
1400: ff fd 01 08 78 05 00 ca f7 41
it is mistook for controller missing packets, so results in page fault after overwriting memdump buffer allocated.
Fixed by ignoring QCA6390 sequence number check and checking buffer space before writing.
---
Changes in v4:
- add a piece of code comments
Changes in v3:
- correct coding style
Changes in v2:
- rename a local variable from @temp to @rx_size
drivers/bluetooth/hci_qca.c | 49 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-)
drivers/bluetooth/hci_qca.c +42 -7
@@ -114,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 {
@@ -976,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))) {
@@ -1029,6 +1032,7 @@ static void qca_controller_memdump(struct work_struct *work)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; }
@@ -1051,26 +1055,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 ) && + (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 );
Signature · 1 line
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Marcel Holtmann
maintainerHi Zijun,
Quoted 65 lines
QCA6390 memdump VSE sometimes come to bluetooth driver with wrong sequence number as illustrated as follows:
frame # in dec: frame data in hex
1396: ff fd 01 08 74 05 00 37 8f 14
1397: ff fd 01 08 75 05 00 ff bf 38
1414: ff fd 01 08 86 05 00 fb 5e 4b
1399: ff fd 01 08 77 05 00 f3 44 0a
1400: ff fd 01 08 78 05 00 ca f7 41
it is mistook for controller missing packets, so results in page fault after overwriting memdump buffer allocated.Fixed by ignoring QCA6390 sequence number check and checking buffer space before writing.
Signed-off-by Zijun Hu <[email protected]>Tested-by Zijun Hu <[email protected]>---
Changes in v4:
- add a piece of code comments
Changes in v3:
- correct coding style
Changes in v2:
- rename a local variable from @temp to @rx_size
drivers/bluetooth/hci_qca.c| 49 ++++++++++++++++++++++++++++++++++++++-------1 file changed, 42 insertions(+), 7 deletions(-)drivers/bluetooth/hci_qca.c +8
-0@@ -114,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 {@@ -976,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))) {@@ -1029,6 +1032,7 @@ static void qca_controller_memdump(struct work_struct *work)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; }@@ -1051,26 +1055,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) &&
drivers/bluetooth/hci_qca.c static void qca_controller_memdump(struct work_struct *work) · line 1072
Quoted 10 lines
drivers/bluetooth/hci_qca.c +7
-0+ (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);
please use correct indentation according to the coding style.
Regards
Marcel