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