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 */ |
117 | |