Skip to content

Commit 9695ef8

Browse files
apanditVudentz
authored andcommitted
Bluetooth: Add support for hci devcoredump
Add devcoredump APIs to hci core so that drivers only have to provide the dump skbs instead of managing the synchronization and timeouts. The devcoredump APIs should be used in the following manner: - hci_devcoredump_init is called to allocate the dump. - hci_devcoredump_append is called to append any skbs with dump data OR hci_devcoredump_append_pattern is called to insert a pattern. - hci_devcoredump_complete is called when all dump packets have been sent OR hci_devcoredump_abort is called to indicate an error and cancel an ongoing dump collection. The high level APIs just prepare some skbs with the appropriate data and queue it for the dump to process. Packets part of the crashdump can be intercepted in the driver in interrupt context and forwarded directly to the devcoredump APIs. Internally, there are 5 states for the dump: idle, active, complete, abort and timeout. A devcoredump will only be in active state after it has been initialized. Once active, it accepts data to be appended, patterns to be inserted (i.e. memset) and a completion event or an abort event to generate a devcoredump. The timeout is initialized at the same time the dump is initialized (defaulting to 10s) and will be cleared either when the timeout occurs or the dump is complete or aborted. Signed-off-by: Abhishek Pandit-Subedi <[email protected]> Signed-off-by: Manish Mandlik <[email protected]> Reviewed-by: Abhishek Pandit-Subedi <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 77f542b commit 9695ef8

File tree

6 files changed

+670
-0
lines changed

6 files changed

+670
-0
lines changed

include/net/bluetooth/coredump.h

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (C) 2022 Google Corporation
4+
*/
5+
6+
#ifndef __COREDUMP_H
7+
#define __COREDUMP_H
8+
9+
#define DEVCOREDUMP_TIMEOUT msecs_to_jiffies(10000) /* 10 sec */
10+
11+
typedef void (*coredump_t)(struct hci_dev *hdev);
12+
typedef void (*dmp_hdr_t)(struct hci_dev *hdev, struct sk_buff *skb);
13+
typedef void (*notify_change_t)(struct hci_dev *hdev, int state);
14+
15+
/* struct hci_devcoredump - Devcoredump state
16+
*
17+
* @supported: Indicates if FW dump collection is supported by driver
18+
* @state: Current state of dump collection
19+
* @timeout: Indicates a timeout for collecting the devcoredump
20+
*
21+
* @alloc_size: Total size of the dump
22+
* @head: Start of the dump
23+
* @tail: Pointer to current end of dump
24+
* @end: head + alloc_size for easy comparisons
25+
*
26+
* @dump_q: Dump queue for state machine to process
27+
* @dump_rx: Devcoredump state machine work
28+
* @dump_timeout: Devcoredump timeout work
29+
*
30+
* @coredump: Called from the driver's .coredump() function.
31+
* @dmp_hdr: Create a dump header to identify controller/fw/driver info
32+
* @notify_change: Notify driver when devcoredump state has changed
33+
*/
34+
struct hci_devcoredump {
35+
bool supported;
36+
37+
enum devcoredump_state {
38+
HCI_DEVCOREDUMP_IDLE,
39+
HCI_DEVCOREDUMP_ACTIVE,
40+
HCI_DEVCOREDUMP_DONE,
41+
HCI_DEVCOREDUMP_ABORT,
42+
HCI_DEVCOREDUMP_TIMEOUT,
43+
} state;
44+
45+
unsigned long timeout;
46+
47+
size_t alloc_size;
48+
char *head;
49+
char *tail;
50+
char *end;
51+
52+
struct sk_buff_head dump_q;
53+
struct work_struct dump_rx;
54+
struct delayed_work dump_timeout;
55+
56+
coredump_t coredump;
57+
dmp_hdr_t dmp_hdr;
58+
notify_change_t notify_change;
59+
};
60+
61+
#ifdef CONFIG_DEV_COREDUMP
62+
63+
void hci_devcd_reset(struct hci_dev *hdev);
64+
void hci_devcd_rx(struct work_struct *work);
65+
void hci_devcd_timeout(struct work_struct *work);
66+
67+
int hci_devcd_register(struct hci_dev *hdev, coredump_t coredump,
68+
dmp_hdr_t dmp_hdr, notify_change_t notify_change);
69+
int hci_devcd_init(struct hci_dev *hdev, u32 dump_size);
70+
int hci_devcd_append(struct hci_dev *hdev, struct sk_buff *skb);
71+
int hci_devcd_append_pattern(struct hci_dev *hdev, u8 pattern, u32 len);
72+
int hci_devcd_complete(struct hci_dev *hdev);
73+
int hci_devcd_abort(struct hci_dev *hdev);
74+
75+
#else
76+
77+
static inline void hci_devcd_reset(struct hci_dev *hdev) {}
78+
static inline void hci_devcd_rx(struct work_struct *work) {}
79+
static inline void hci_devcd_timeout(struct work_struct *work) {}
80+
81+
static inline int hci_devcd_register(struct hci_dev *hdev, coredump_t coredump,
82+
dmp_hdr_t dmp_hdr,
83+
notify_change_t notify_change)
84+
{
85+
return -EOPNOTSUPP;
86+
}
87+
88+
static inline int hci_devcd_init(struct hci_dev *hdev, u32 dump_size)
89+
{
90+
return -EOPNOTSUPP;
91+
}
92+
93+
static inline int hci_devcd_append(struct hci_dev *hdev, struct sk_buff *skb)
94+
{
95+
return -EOPNOTSUPP;
96+
}
97+
98+
static inline int hci_devcd_append_pattern(struct hci_dev *hdev,
99+
u8 pattern, u32 len)
100+
{
101+
return -EOPNOTSUPP;
102+
}
103+
104+
static inline int hci_devcd_complete(struct hci_dev *hdev)
105+
{
106+
return -EOPNOTSUPP;
107+
}
108+
109+
static inline int hci_devcd_abort(struct hci_dev *hdev)
110+
{
111+
return -EOPNOTSUPP;
112+
}
113+
114+
#endif /* CONFIG_DEV_COREDUMP */
115+
116+
#endif /* __COREDUMP_H */

include/net/bluetooth/hci_core.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <net/bluetooth/hci.h>
3333
#include <net/bluetooth/hci_sync.h>
3434
#include <net/bluetooth/hci_sock.h>
35+
#include <net/bluetooth/coredump.h>
3536

3637
/* HCI priority */
3738
#define HCI_PRIO_MAX 7
@@ -590,6 +591,10 @@ struct hci_dev {
590591
const char *fw_info;
591592
struct dentry *debugfs;
592593

594+
#ifdef CONFIG_DEV_COREDUMP
595+
struct hci_devcoredump dump;
596+
#endif
597+
593598
struct device dev;
594599

595600
struct rfkill *rfkill;
@@ -1497,6 +1502,15 @@ static inline void hci_set_aosp_capable(struct hci_dev *hdev)
14971502
#endif
14981503
}
14991504

1505+
static inline void hci_devcd_setup(struct hci_dev *hdev)
1506+
{
1507+
#ifdef CONFIG_DEV_COREDUMP
1508+
INIT_WORK(&hdev->dump.dump_rx, hci_devcd_rx);
1509+
INIT_DELAYED_WORK(&hdev->dump.dump_timeout, hci_devcd_timeout);
1510+
skb_queue_head_init(&hdev->dump.dump_q);
1511+
#endif
1512+
}
1513+
15001514
int hci_dev_open(__u16 dev);
15011515
int hci_dev_close(__u16 dev);
15021516
int hci_dev_do_close(struct hci_dev *hdev);

net/bluetooth/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
1717
ecdh_helper.o hci_request.o mgmt_util.o mgmt_config.o hci_codec.o \
1818
eir.o hci_sync.o
1919

20+
bluetooth-$(CONFIG_DEV_COREDUMP) += coredump.o
21+
2022
bluetooth-$(CONFIG_BT_BREDR) += sco.o
2123
bluetooth-$(CONFIG_BT_LE) += iso.o
2224
bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o

0 commit comments

Comments
 (0)