xref: /linux/include/net/bluetooth/coredump.h (revision 26ba30221c03364d6ed9910be8da4c1fd871b07b)
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 /*
12  * Max header size, shared by both the devcoredump core and
13  * the dmp_hdr() registered by driver via hci_devcd_register()
14  */
15 #define HCI_DEVCD_HDR_SIZE_MAX	512
16 #define HCI_DEVCD_HDR_END_MARKER	"--- Start dump ---\n"
17 
18 typedef void (*coredump_t)(struct hci_dev *hdev);
19 typedef void (*dmp_hdr_t)(struct hci_dev *hdev, struct sk_buff *skb);
20 typedef void (*notify_change_t)(struct hci_dev *hdev, int state);
21 
22 /* struct hci_devcoredump - Devcoredump state
23  *
24  * @supported: Indicates if FW dump collection is supported by driver
25  * @state: Current state of dump collection
26  * @timeout: Indicates a timeout for collecting the devcoredump
27  *
28  * @alloc_size: Total size of the dump
29  * @head: Start of the dump
30  * @tail: Pointer to current end of dump
31  * @end: head + alloc_size for easy comparisons
32  *
33  * @dump_q: Dump queue for state machine to process
34  * @dump_rx: Devcoredump state machine work
35  * @dump_timeout: Devcoredump timeout work
36  *
37  * @coredump: Called from the driver's .coredump() function.
38  * @dmp_hdr: Create a dump header to identify controller/fw/driver info
39  * @notify_change: Notify driver when devcoredump state has changed
40  */
41 struct hci_devcoredump {
42 	bool		supported;
43 
44 	enum devcoredump_state {
45 		HCI_DEVCOREDUMP_IDLE,
46 		HCI_DEVCOREDUMP_ACTIVE,
47 		HCI_DEVCOREDUMP_DONE,
48 		HCI_DEVCOREDUMP_ABORT,
49 		HCI_DEVCOREDUMP_TIMEOUT,
50 	} state;
51 
52 	unsigned long	timeout;
53 
54 	size_t		alloc_size;
55 	char		*head;
56 	char		*tail;
57 	char		*end;
58 
59 	struct sk_buff_head	dump_q;
60 	struct work_struct	dump_rx;
61 	struct delayed_work	dump_timeout;
62 
63 	coredump_t		coredump;
64 	dmp_hdr_t		dmp_hdr;
65 	notify_change_t		notify_change;
66 };
67 
68 #ifdef CONFIG_DEV_COREDUMP
69 
70 const char *hci_devcd_state_name(enum devcoredump_state state);
71 
72 void hci_devcd_reset(struct hci_dev *hdev);
73 void hci_devcd_rx(struct work_struct *work);
74 void hci_devcd_timeout(struct work_struct *work);
75 
76 int hci_devcd_register(struct hci_dev *hdev, coredump_t coredump,
77 		       dmp_hdr_t dmp_hdr, notify_change_t notify_change);
78 int hci_devcd_init(struct hci_dev *hdev, u32 dump_size);
79 int hci_devcd_append(struct hci_dev *hdev, struct sk_buff *skb);
80 int hci_devcd_append_pattern(struct hci_dev *hdev, u8 pattern, u32 len);
81 int hci_devcd_complete(struct hci_dev *hdev);
82 int hci_devcd_abort(struct hci_dev *hdev);
83 
84 #else
85 
86 static inline const char *hci_devcd_state_name(enum devcoredump_state state)
87 {
88 	return "";
89 }
90 
91 static inline void hci_devcd_reset(struct hci_dev *hdev) {}
92 static inline void hci_devcd_rx(struct work_struct *work) {}
93 static inline void hci_devcd_timeout(struct work_struct *work) {}
94 
95 static inline int hci_devcd_register(struct hci_dev *hdev, coredump_t coredump,
96 				     dmp_hdr_t dmp_hdr,
97 				     notify_change_t notify_change)
98 {
99 	return -EOPNOTSUPP;
100 }
101 
102 static inline int hci_devcd_init(struct hci_dev *hdev, u32 dump_size)
103 {
104 	return -EOPNOTSUPP;
105 }
106 
107 static inline int hci_devcd_append(struct hci_dev *hdev, struct sk_buff *skb)
108 {
109 	return -EOPNOTSUPP;
110 }
111 
112 static inline int hci_devcd_append_pattern(struct hci_dev *hdev,
113 					   u8 pattern, u32 len)
114 {
115 	return -EOPNOTSUPP;
116 }
117 
118 static inline int hci_devcd_complete(struct hci_dev *hdev)
119 {
120 	return -EOPNOTSUPP;
121 }
122 
123 static inline int hci_devcd_abort(struct hci_dev *hdev)
124 {
125 	return -EOPNOTSUPP;
126 }
127 
128 #endif /* CONFIG_DEV_COREDUMP */
129 
130 #endif /* __COREDUMP_H */
131