[PATCH 03/11] Bluetooth: coredump: Introduce and apply hci_devcd_state_name()
From: Zijun Hu
Date: Sat Jul 25 2026 - 04:55:35 EST
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 <zijun.hu@xxxxxxxxxxxxxxxx>
---
Previous version:
https://lore.kernel.org/all/20260713-btusb_prep_qcc2072-v2-1-bbcb651285f2@xxxxxxxxxxxxxxxx
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