#define DBG_UNEXPECTED_STATE() \
bt_dev_dbg(hdev, \ "Unexpected packet (%d) for state (%d). ", \
hci_dmp_cb(skb)->pkt_type, hdev->dump.state)
#define MAX_DEVCOREDUMP_HDR_SIZE 512 /* bytes */
staticint hci_devcd_update_hdr_state(char *buf, size_t size, int state)
{ int len = 0;
if (!buf) return 0;
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. */ staticint 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);
/* Do not call with hci_dev_lock since this calls driver code. */ staticvoid hci_devcd_notify(struct hci_dev *hdev, int state)
{ if (hdev->dump.notify_change)
hdev->dump.notify_change(hdev, state);
}
/* 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);
}
/* Emit a devcoredump with the available data */
dev_coredumpv(&hdev->dev, hdev->dump.head, size, GFP_KERNEL);
}
bt_dev_dbg(hdev, "aborted with size %u (expect %zu)", dump_size,
hdev->dump.alloc_size);
hci_devcd_dump(hdev);
}
/* Bluetooth devcoredump state machine. * * Devcoredump states: * * HCI_DEVCOREDUMP_IDLE: The default state. * * HCI_DEVCOREDUMP_ACTIVE: A devcoredump will be in this state once it has * been initialized using hci_devcd_init(). Once active, the driver * can append data using hci_devcd_append() or insert a pattern * using hci_devcd_append_pattern(). * * HCI_DEVCOREDUMP_DONE: Once the dump collection is complete, the drive * can signal the completion using hci_devcd_complete(). A * devcoredump is generated indicating the completion event and * then the state machine is reset to the default state. * * HCI_DEVCOREDUMP_ABORT: The driver can cancel ongoing dump collection in * case of any error using hci_devcd_abort(). A devcoredump is * still generated with the available data indicating the abort * event and then the state machine is reset to the default state. * * HCI_DEVCOREDUMP_TIMEOUT: A timeout timer for HCI_DEVCOREDUMP_TIMEOUT sec * is started during devcoredump initialization. Once the timeout * occurs, the driver is notified, a devcoredump is generated with * the available data indicating the timeout event and then the * state machine is reset to the default state. * * The driver must register using hci_devcd_register() before using the hci * devcoredump APIs.
*/ void hci_devcd_rx(struct work_struct *work)
{ struct hci_dev *hdev = container_of(work, struct hci_dev, dump.dump_rx); struct sk_buff *skb; int start_state;
while ((skb = skb_dequeue(&hdev->dump.dump_q))) { /* Return if timeout occurs. The timeout handler function * hci_devcd_timeout() will report the available dump data.
*/ if (hdev->dump.state == HCI_DEVCOREDUMP_TIMEOUT) {
kfree_skb(skb); return;
}
switch (hci_dmp_cb(skb)->pkt_type) { case HCI_DEVCOREDUMP_PKT_INIT:
hci_devcd_handle_pkt_init(hdev, skb); break;
case HCI_DEVCOREDUMP_PKT_SKB:
hci_devcd_handle_pkt_skb(hdev, skb); break;
case HCI_DEVCOREDUMP_PKT_PATTERN:
hci_devcd_handle_pkt_pattern(hdev, skb); break;
case HCI_DEVCOREDUMP_PKT_COMPLETE:
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); break;
}
hci_dev_unlock(hdev);
kfree_skb(skb);
/* Notify the driver about any state changes before resetting * the state machine
*/ if (start_state != hdev->dump.state)
hci_devcd_notify(hdev, hdev->dump.state);
/* Reset the state machine if the devcoredump is complete */
hci_dev_lock(hdev); if (hdev->dump.state == HCI_DEVCOREDUMP_DONE ||
hdev->dump.state == HCI_DEVCOREDUMP_ABORT)
hci_devcd_reset(hdev);
hci_dev_unlock(hdev);
}
}
EXPORT_SYMBOL(hci_devcd_rx);
int hci_devcd_register(struct hci_dev *hdev, coredump_t coredump,
dmp_hdr_t dmp_hdr, notify_change_t notify_change)
{ /* Driver must implement coredump() and dmp_hdr() functions for * bluetooth devcoredump. The coredump() should trigger a coredump * event on the controller when the device's coredump sysfs entry is * written to. The dmp_hdr() should create a dump header to identify * the controller/fw/driver info.
*/ if (!coredump || !dmp_hdr) return -EINVAL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.