[PATCH 03/11] Bluetooth: coredump: Introduce and apply hci_devcd_state_name()
Zijun Hu <[email protected]> Sat, 25 Jul 2026 01:54:41 -0700
| Newsgroups | org.kernel.vger.linux-bluetooth,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Introduce hci_devcd_state_name() to describe the devcoredump state by a string name instead of a plain number, for several reasons: 1) Applying it in coredump.c makes the devcoredump state in log messages more readable than a plain number. 2) Transport drivers may need to show the devcoredump state name too. 3) In future, the universal state name could be notified to userspace via uevent, allowing a universal application (e.g. a daemon) to be developed to save the coredump, which is otherwise discarded by the device coredump core after 5 minutes (DEVCD_TIMEOUT); see nxp_coredump_notify(). Also drop a trailing space from two bt_dev_dbg() format strings while applying it in coredump.c. Signed-off-by: Zijun Hu <[email protected]> --- Previous version: https://lore.kernel.org/all/[email protected] Changes since previous version: - Improve commit title and message. --- include/net/bluetooth/coredump.h | 7 +++++++ net/bluetooth/coredump.c | 45 +++++++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/include/net/bluetooth/coredump.h b/include/net/bluetooth/coredump.h index 72f51b587a04..ab85a6adfffd 100644 --- a/include/net/bluetooth/coredump.h +++ b/include/net/bluetooth/coredump.h @@ -55,30 +55,37 @@ struct hci_devcoredump { coredump_t coredump; dmp_hdr_t dmp_hdr; notify_change_t notify_change; }; #ifdef CONFIG_DEV_COREDUMP +const char *hci_devcd_state_name(enum devcoredump_state state); + void hci_devcd_reset(struct hci_dev *hdev); void hci_devcd_rx(struct work_struct *work); void hci_devcd_timeout(struct work_struct *work); int hci_devcd_register(struct hci_dev *hdev, coredump_t coredump, dmp_hdr_t dmp_hdr, notify_change_t notify_change); int hci_devcd_init(struct hci_dev *hdev, u32 dump_size); int hci_devcd_append(struct hci_dev *hdev, struct sk_buff *skb); int hci_devcd_append_pattern(struct hci_dev *hdev, u8 pattern, u32 len); int hci_devcd_complete(struct hci_dev *hdev); int hci_devcd_abort(struct hci_dev *hdev); #else +static inline const char *hci_devcd_state_name(enum devcoredump_state state) +{ + return ""; +} + static inline void hci_devcd_reset(struct hci_dev *hdev) {} static inline void hci_devcd_rx(struct work_struct *work) {} static inline void hci_devcd_timeout(struct work_struct *work) {} static inline int hci_devcd_register(struct hci_dev *hdev, coredump_t coredump, dmp_hdr_t dmp_hdr, notify_change_t notify_change) { diff --git a/net/bluetooth/coredump.c b/net/bluetooth/coredump.c index c0f027fab583..913bbba559f8 100644 --- a/net/bluetooth/coredump.c +++ b/net/bluetooth/coredump.c @@ -25,18 +25,19 @@ struct hci_devcoredump_skb_pattern { u8 pattern; u32 len; } __packed; #define hci_dmp_cb(skb) ((struct hci_devcoredump_skb_cb *)((skb)->cb)) #define DBG_UNEXPECTED_STATE() \ bt_dev_dbg(hdev, \ - "Unexpected packet (%d) for state (%d). ", \ - hci_dmp_cb(skb)->pkt_type, hdev->dump.state) + "Unexpected packet (%d) for state %s.", \ + hci_dmp_cb(skb)->pkt_type, \ + hci_devcd_state_name(hdev->dump.state)) #define MAX_DEVCOREDUMP_HDR_SIZE 512 /* bytes */ static int hci_devcd_update_hdr_state(char *buf, size_t size, int state) { int len = 0; if (!buf) @@ -45,18 +46,19 @@ static int hci_devcd_update_hdr_state(char *buf, size_t size, int state) len = scnprintf(buf, size, "Bluetooth devcoredump\nState: %d\n", state); return len + 1; /* scnprintf adds \0 at the end upon state rewrite */ } /* Call with hci_dev_lock only. */ static int hci_devcd_update_state(struct hci_dev *hdev, int state) { - bt_dev_dbg(hdev, "Updating devcoredump state from %d to %d.", - hdev->dump.state, state); + bt_dev_dbg(hdev, "Updating devcoredump state from %s to %s.", + hci_devcd_state_name(hdev->dump.state), + hci_devcd_state_name(state)); hdev->dump.state = state; return hci_devcd_update_hdr_state(hdev->dump.head, hdev->dump.alloc_size, state); } static int hci_devcd_mkheader(struct hci_dev *hdev, struct sk_buff *skb) @@ -240,17 +242,17 @@ static void hci_devcd_handle_pkt_pattern(struct hci_dev *hdev, bt_dev_dbg(hdev, "Failed to set pattern"); } static void hci_devcd_dump(struct hci_dev *hdev) { struct sk_buff *skb; u32 size; - bt_dev_dbg(hdev, "state %d", hdev->dump.state); + bt_dev_dbg(hdev, "state %s", hci_devcd_state_name(hdev->dump.state)); size = hdev->dump.tail - hdev->dump.head; /* Send a copy to monitor as a diagnostic packet */ skb = bt_skb_alloc(size, GFP_ATOMIC); if (skb) { skb_put_data(skb, hdev->dump.head, size); hci_recv_diag(hdev, skb); @@ -363,18 +365,19 @@ void hci_devcd_rx(struct work_struct *work) hci_devcd_handle_pkt_complete(hdev, skb); break; case HCI_DEVCOREDUMP_PKT_ABORT: hci_devcd_handle_pkt_abort(hdev, skb); break; default: - bt_dev_dbg(hdev, "Unknown packet (%d) for state (%d). ", - hci_dmp_cb(skb)->pkt_type, hdev->dump.state); + bt_dev_dbg(hdev, "Unknown packet (%d) for state %s.", + hci_dmp_cb(skb)->pkt_type, + hci_devcd_state_name(hdev->dump.state)); break; } hci_dev_unlock(hdev); kfree_skb(skb); /* Notify the driver about any state changes before resetting * the state machine @@ -544,8 +547,36 @@ int hci_devcd_abort(struct hci_dev *hdev) hci_dmp_cb(skb)->pkt_type = HCI_DEVCOREDUMP_PKT_ABORT; skb_queue_tail(&hdev->dump.dump_q, skb); queue_work(hdev->workqueue, &hdev->dump.dump_rx); return 0; } EXPORT_SYMBOL(hci_devcd_abort); + +const char *hci_devcd_state_name(enum devcoredump_state state) +{ + const char *state_name = "Unknown"; + + switch (state) { + case HCI_DEVCOREDUMP_IDLE: + state_name = "IDLE"; + break; + case HCI_DEVCOREDUMP_ACTIVE: + state_name = "ACTIVE"; + break; + case HCI_DEVCOREDUMP_DONE: + state_name = "DONE"; + break; + case HCI_DEVCOREDUMP_ABORT: + state_name = "ABORT"; + break; + case HCI_DEVCOREDUMP_TIMEOUT: + state_name = "TIMEOUT"; + break; + default: + break; + } + + return state_name; +} +EXPORT_SYMBOL(hci_devcd_state_name); -- 2.34.1