|
@@ -340,271 +340,6 @@ uint32_t wmi_diag_log_max_entry = WMI_DIAG_RX_EVENT_DEBUG_MAX_ENTRY;
|
|
|
uint32_t wmi_record_max_length = WMI_DEBUG_ENTRY_MAX_LENGTH;
|
|
|
uint32_t wmi_display_size = 100;
|
|
|
|
|
|
-#ifdef WMI_EXT_DBG
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_dbg_msg_enqueue() - enqueue wmi message
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handler
|
|
|
- *
|
|
|
- * Return: size of wmi message queue after enqueue
|
|
|
- */
|
|
|
-static uint32_t wmi_ext_dbg_msg_enqueue(struct wmi_unified *wmi_handle,
|
|
|
- struct wmi_ext_dbg_msg *msg)
|
|
|
-{
|
|
|
- uint32_t list_size;
|
|
|
-
|
|
|
- qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
- qdf_list_insert_back_size(&wmi_handle->wmi_ext_dbg_msg_queue,
|
|
|
- &msg->node, &list_size);
|
|
|
- qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
-
|
|
|
- return list_size;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_dbg_msg_dequeue() - dequeue wmi message
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handler
|
|
|
- *
|
|
|
- * Return: wmi msg on success else NULL
|
|
|
- */
|
|
|
-static struct wmi_ext_dbg_msg *wmi_ext_dbg_msg_dequeue(struct wmi_unified
|
|
|
- *wmi_handle)
|
|
|
-{
|
|
|
- qdf_list_node_t *list_node = NULL;
|
|
|
-
|
|
|
- qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
- qdf_list_remove_front(&wmi_handle->wmi_ext_dbg_msg_queue, &list_node);
|
|
|
- qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
-
|
|
|
- if (!list_node)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- return qdf_container_of(list_node, struct wmi_ext_dbg_msg, node);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_dbg_msg_record() - record wmi messages
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handler
|
|
|
- * @buf: wmi message buffer
|
|
|
- * @len: wmi message length
|
|
|
- * @type: wmi message type
|
|
|
- *
|
|
|
- * Return: QDF_STATUS_SUCCESS on successful recording else failure.
|
|
|
- */
|
|
|
-static QDF_STATUS wmi_ext_dbg_msg_record(struct wmi_unified *wmi_handle,
|
|
|
- uint8_t *buf, uint32_t len,
|
|
|
- enum WMI_MSG_TYPE type)
|
|
|
-{
|
|
|
- struct wmi_ext_dbg_msg *msg;
|
|
|
- uint32_t list_size;
|
|
|
-
|
|
|
- msg = wmi_ext_dbg_msg_get(len);
|
|
|
- if (!msg)
|
|
|
- return QDF_STATUS_E_NOMEM;
|
|
|
-
|
|
|
- msg->len = len;
|
|
|
- msg->type = type;
|
|
|
- qdf_mem_copy(msg->buf, buf, len);
|
|
|
- msg->ts = qdf_get_log_timestamp();
|
|
|
- list_size = wmi_ext_dbg_msg_enqueue(wmi_handle, msg);
|
|
|
-
|
|
|
- if (list_size >= wmi_handle->wmi_ext_dbg_msg_queue_size) {
|
|
|
- msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
|
|
|
- wmi_ext_dbg_msg_put(msg);
|
|
|
- }
|
|
|
-
|
|
|
- return QDF_STATUS_SUCCESS;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_dbg_msg_cmd_record() - record wmi command messages
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handler
|
|
|
- * @buf: wmi command buffer
|
|
|
- * @len: wmi command message length
|
|
|
- *
|
|
|
- * Return: QDF_STATUS_SUCCESS on successful recording else failure.
|
|
|
- */
|
|
|
-static QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified *wmi_handle,
|
|
|
- uint8_t *buf, uint32_t len)
|
|
|
-{
|
|
|
- return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
|
|
|
- WMI_MSG_TYPE_CMD);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_dbg_msg_event_record() - record wmi event messages
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handler
|
|
|
- * @buf: wmi event buffer
|
|
|
- * @len: wmi event message length
|
|
|
- *
|
|
|
- * Return: QDF_STATUS_SUCCESS on successful recording else failure.
|
|
|
- */
|
|
|
-static QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified *wmi_handle,
|
|
|
- uint8_t *buf, uint32_t len)
|
|
|
-{
|
|
|
- uint32_t id;
|
|
|
-
|
|
|
- id = WMI_GET_FIELD(buf, WMI_CMD_HDR, COMMANDID);
|
|
|
- if (id != wmi_handle->wmi_events[wmi_diag_event_id])
|
|
|
- return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
|
|
|
- WMI_MSG_TYPE_EVENT);
|
|
|
-
|
|
|
- return QDF_STATUS_SUCCESS;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_dbg_msg_queue_init() - create debugfs queue and associated lock
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handler
|
|
|
- *
|
|
|
- * Return: none
|
|
|
- */
|
|
|
-static void wmi_ext_dbg_msg_queue_init(struct wmi_unified *wmi_handle)
|
|
|
-{
|
|
|
- qdf_list_create(&wmi_handle->wmi_ext_dbg_msg_queue,
|
|
|
- wmi_handle->wmi_ext_dbg_msg_queue_size);
|
|
|
- qdf_spinlock_create(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_dbg_msg_queue_deinit() - destroy debugfs queue and associated lock
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handler
|
|
|
- *
|
|
|
- * Return: none
|
|
|
- */
|
|
|
-static void wmi_ext_dbg_msg_queue_deinit(struct wmi_unified *wmi_handle)
|
|
|
-{
|
|
|
- qdf_list_destroy(&wmi_handle->wmi_ext_dbg_msg_queue);
|
|
|
- qdf_spinlock_destroy(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_dbg_msg_show() - debugfs function to display whole content of
|
|
|
- * wmi command/event messages including headers.
|
|
|
- *
|
|
|
- * @file: qdf debugfs file handler
|
|
|
- * @arg: pointer to wmi handler
|
|
|
- *
|
|
|
- * Return: QDF_STATUS_SUCCESS if all the messages are shown successfully,
|
|
|
- * else QDF_STATUS_E_AGAIN if more data to show.
|
|
|
- */
|
|
|
-static QDF_STATUS wmi_ext_dbg_msg_show(qdf_debugfs_file_t file, void *arg)
|
|
|
-{
|
|
|
- struct wmi_unified *wmi_handle = (struct wmi_unified *)arg;
|
|
|
- struct wmi_ext_dbg_msg *msg;
|
|
|
- uint64_t secs, usecs;
|
|
|
-
|
|
|
- msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
|
|
|
- if (!msg)
|
|
|
- return QDF_STATUS_SUCCESS;
|
|
|
-
|
|
|
- qdf_debugfs_printf(file, "%s: 0x%x\n",
|
|
|
- msg->type == WMI_MSG_TYPE_CMD ? "COMMAND" :
|
|
|
- "EVENT", WMI_GET_FIELD(msg->buf, WMI_CMD_HDR,
|
|
|
- COMMANDID));
|
|
|
- qdf_log_timestamp_to_secs(msg->ts, &secs, &usecs);
|
|
|
- qdf_debugfs_printf(file, "Time: %llu.%llu\n", secs, usecs);
|
|
|
- qdf_debugfs_printf(file, "Length:%d\n", msg->len);
|
|
|
- qdf_debugfs_hexdump(file, msg->buf, msg->len,
|
|
|
- WMI_EXT_DBG_DUMP_ROW_SIZE,
|
|
|
- WMI_EXT_DBG_DUMP_GROUP_SIZE);
|
|
|
- qdf_debugfs_printf(file, "\n");
|
|
|
-
|
|
|
- if (qdf_debugfs_overflow(file)) {
|
|
|
- qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
- qdf_list_insert_front(&wmi_handle->wmi_ext_dbg_msg_queue,
|
|
|
- &msg->node);
|
|
|
- qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
-
|
|
|
- } else {
|
|
|
- wmi_ext_dbg_msg_put(msg);
|
|
|
- }
|
|
|
-
|
|
|
- return QDF_STATUS_E_AGAIN;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_dbg_msg_write() - debugfs write not supported
|
|
|
- *
|
|
|
- * @priv: private data
|
|
|
- * @buf: received data buffer
|
|
|
- * @len: length of received buffer
|
|
|
- *
|
|
|
- * Return: QDF_STATUS_E_NOSUPPORT.
|
|
|
- */
|
|
|
-static QDF_STATUS wmi_ext_dbg_msg_write(void *priv, const char *buf,
|
|
|
- qdf_size_t len)
|
|
|
-{
|
|
|
- return QDF_STATUS_E_NOSUPPORT;
|
|
|
-}
|
|
|
-
|
|
|
-static struct qdf_debugfs_fops wmi_ext_dbgfs_ops = {
|
|
|
- .show = wmi_ext_dbg_msg_show,
|
|
|
- .write = wmi_ext_dbg_msg_write,
|
|
|
- .priv = NULL,
|
|
|
-};
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_debugfs_init() - init debugfs items for extended wmi dump.
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handler
|
|
|
- *
|
|
|
- * Return: QDF_STATUS_SUCCESS if debugfs is initialized else
|
|
|
- * QDF_STATUS_E_FAILURE
|
|
|
- */
|
|
|
-static QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle)
|
|
|
-{
|
|
|
- qdf_dentry_t dentry;
|
|
|
-
|
|
|
- dentry = qdf_debugfs_create_dir(WMI_EXT_DBG_DIR, NULL);
|
|
|
- if (!dentry) {
|
|
|
- WMI_LOGE("error while creating extended wmi debugfs dir");
|
|
|
- return QDF_STATUS_E_FAILURE;
|
|
|
- }
|
|
|
-
|
|
|
- wmi_ext_dbgfs_ops.priv = wmi_handle;
|
|
|
- if (!qdf_debugfs_create_file(WMI_EXT_DBG_FILE, WMI_EXT_DBG_FILE_PERM,
|
|
|
- dentry, &wmi_ext_dbgfs_ops)) {
|
|
|
- qdf_debugfs_remove_dir(dentry);
|
|
|
- WMI_LOGE("error while creating extended wmi debugfs file");
|
|
|
- return QDF_STATUS_E_FAILURE;
|
|
|
- }
|
|
|
-
|
|
|
- wmi_handle->wmi_ext_dbg_dentry = dentry;
|
|
|
- wmi_handle->wmi_ext_dbg_msg_queue_size = WMI_EXT_DBG_QUEUE_SIZE;
|
|
|
- wmi_ext_dbg_msg_queue_init(wmi_handle);
|
|
|
-
|
|
|
- return QDF_STATUS_SUCCESS;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * wmi_ext_debugfs_deinit() - cleanup/deinit debugfs items of extended wmi dump.
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handler
|
|
|
- *
|
|
|
- * Return: QDF_STATUS_SUCCESS if cleanup is successful
|
|
|
- */
|
|
|
-static QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
|
|
|
-{
|
|
|
- struct wmi_ext_dbg_msg *msg;
|
|
|
-
|
|
|
- while ((msg = wmi_ext_dbg_msg_dequeue(wmi_handle)))
|
|
|
- wmi_ext_dbg_msg_put(msg);
|
|
|
-
|
|
|
- wmi_ext_dbg_msg_queue_deinit(wmi_handle);
|
|
|
- qdf_debugfs_remove_dir_recursive(wmi_handle->wmi_ext_dbg_dentry);
|
|
|
-
|
|
|
- return QDF_STATUS_SUCCESS;
|
|
|
-}
|
|
|
-
|
|
|
-#endif /*WMI_EXT_DBG */
|
|
|
-
|
|
|
/**
|
|
|
* wmi_log_init() - Initialize WMI event logging
|
|
|
* @wmi_handle: WMI handle.
|
|
@@ -1407,138 +1142,430 @@ struct wmi_debugfs_info wmi_debugfs_infos[NUM_DEBUG_INFOS] = {
|
|
|
#endif
|
|
|
};
|
|
|
|
|
|
+/**
|
|
|
+ * wmi_debugfs_create() - Create debug_fs entry for wmi logging.
|
|
|
+ *
|
|
|
+ * @wmi_handle: wmi handle
|
|
|
+ * @par_entry: debug directory entry
|
|
|
+ * @id: Index to debug info data array
|
|
|
+ *
|
|
|
+ * Return: none
|
|
|
+ */
|
|
|
+static void wmi_debugfs_create(wmi_unified_t wmi_handle,
|
|
|
+ struct dentry *par_entry)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (!par_entry)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
|
|
|
+ wmi_handle->debugfs_de[i] = debugfs_create_file(
|
|
|
+ wmi_debugfs_infos[i].name, 0644, par_entry,
|
|
|
+ wmi_handle, wmi_debugfs_infos[i].ops);
|
|
|
+
|
|
|
+ if (!wmi_handle->debugfs_de[i]) {
|
|
|
+ WMI_LOGE("debug Entry creation failed!");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return;
|
|
|
+
|
|
|
+out:
|
|
|
+ WMI_LOGE("debug Entry creation failed!");
|
|
|
+ wmi_log_buffer_free(wmi_handle);
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * wmi_debugfs_remove() - Remove debugfs entry for wmi logging.
|
|
|
+ * @wmi_handle: wmi handle
|
|
|
+ * @dentry: debugfs directory entry
|
|
|
+ * @id: Index to debug info data array
|
|
|
+ *
|
|
|
+ * Return: none
|
|
|
+ */
|
|
|
+static void wmi_debugfs_remove(wmi_unified_t wmi_handle)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ struct dentry *dentry = wmi_handle->log_info.wmi_log_debugfs_dir;
|
|
|
+
|
|
|
+ if (dentry) {
|
|
|
+ for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
|
|
|
+ if (wmi_handle->debugfs_de[i])
|
|
|
+ wmi_handle->debugfs_de[i] = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dentry)
|
|
|
+ debugfs_remove_recursive(dentry);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * wmi_debugfs_init() - debugfs functions to create debugfs directory and to
|
|
|
+ * create debugfs enteries.
|
|
|
+ *
|
|
|
+ * @h: wmi handler
|
|
|
+ *
|
|
|
+ * Return: init status
|
|
|
+ */
|
|
|
+static QDF_STATUS wmi_debugfs_init(wmi_unified_t wmi_handle, uint32_t pdev_idx)
|
|
|
+{
|
|
|
+ char buf[32];
|
|
|
+
|
|
|
+ snprintf(buf, sizeof(buf), "WMI_SOC%u_PDEV%u",
|
|
|
+ wmi_handle->soc->soc_idx, pdev_idx);
|
|
|
+
|
|
|
+ wmi_handle->log_info.wmi_log_debugfs_dir =
|
|
|
+ debugfs_create_dir(buf, NULL);
|
|
|
+
|
|
|
+ if (!wmi_handle->log_info.wmi_log_debugfs_dir) {
|
|
|
+ WMI_LOGE("error while creating debugfs dir for %s", buf);
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+ wmi_debugfs_create(wmi_handle,
|
|
|
+ wmi_handle->log_info.wmi_log_debugfs_dir);
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * wmi_mgmt_cmd_record() - Wrapper function for mgmt command logging macro
|
|
|
+ *
|
|
|
+ * @wmi_handle: wmi handle
|
|
|
+ * @cmd: mgmt command
|
|
|
+ * @header: pointer to 802.11 header
|
|
|
+ * @vdev_id: vdev id
|
|
|
+ * @chanfreq: channel frequency
|
|
|
+ *
|
|
|
+ * Return: none
|
|
|
+ */
|
|
|
+void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
|
|
|
+ void *header, uint32_t vdev_id, uint32_t chanfreq)
|
|
|
+{
|
|
|
+
|
|
|
+ uint32_t data[CUSTOM_MGMT_CMD_DATA_SIZE];
|
|
|
+
|
|
|
+ data[0] = ((struct wmi_command_header *)header)->type;
|
|
|
+ data[1] = ((struct wmi_command_header *)header)->sub_type;
|
|
|
+ data[2] = vdev_id;
|
|
|
+ data[3] = chanfreq;
|
|
|
+
|
|
|
+ qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
|
|
|
+
|
|
|
+ WMI_MGMT_COMMAND_RECORD(wmi_handle, cmd, (uint8_t *)data);
|
|
|
+ wmi_specific_cmd_record(wmi_handle, cmd, (uint8_t *)data);
|
|
|
+ qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
|
|
|
+}
|
|
|
+#else
|
|
|
+/**
|
|
|
+ * wmi_debugfs_remove() - Remove debugfs entry for wmi logging.
|
|
|
+ * @wmi_handle: wmi handle
|
|
|
+ * @dentry: debugfs directory entry
|
|
|
+ * @id: Index to debug info data array
|
|
|
+ *
|
|
|
+ * Return: none
|
|
|
+ */
|
|
|
+static void wmi_debugfs_remove(wmi_unified_t wmi_handle) { }
|
|
|
+void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
|
|
|
+ void *header, uint32_t vdev_id, uint32_t chanfreq) { }
|
|
|
+static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle) { }
|
|
|
+#endif /*WMI_INTERFACE_EVENT_LOGGING */
|
|
|
+qdf_export_symbol(wmi_mgmt_cmd_record);
|
|
|
+
|
|
|
+#ifdef WMI_EXT_DBG
|
|
|
+
|
|
|
+/**
|
|
|
+ * wmi_ext_dbg_msg_enqueue() - enqueue wmi message
|
|
|
+ * @wmi_handle: wmi handler
|
|
|
+ *
|
|
|
+ * Return: size of wmi message queue after enqueue
|
|
|
+ */
|
|
|
+static uint32_t wmi_ext_dbg_msg_enqueue(struct wmi_unified *wmi_handle,
|
|
|
+ struct wmi_ext_dbg_msg *msg)
|
|
|
+{
|
|
|
+ uint32_t list_size;
|
|
|
+
|
|
|
+ qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
+ qdf_list_insert_back_size(&wmi_handle->wmi_ext_dbg_msg_queue,
|
|
|
+ &msg->node, &list_size);
|
|
|
+ qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
+
|
|
|
+ return list_size;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * wmi_ext_dbg_msg_dequeue() - dequeue wmi message
|
|
|
+ * @wmi_handle: wmi handler
|
|
|
+ *
|
|
|
+ * Return: wmi msg on success else NULL
|
|
|
+ */
|
|
|
+static struct wmi_ext_dbg_msg *wmi_ext_dbg_msg_dequeue(struct wmi_unified
|
|
|
+ *wmi_handle)
|
|
|
+{
|
|
|
+ qdf_list_node_t *list_node = NULL;
|
|
|
+
|
|
|
+ qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
+ qdf_list_remove_front(&wmi_handle->wmi_ext_dbg_msg_queue, &list_node);
|
|
|
+ qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
+
|
|
|
+ if (!list_node)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return qdf_container_of(list_node, struct wmi_ext_dbg_msg, node);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * wmi_ext_dbg_msg_record() - record wmi messages
|
|
|
+ * @wmi_handle: wmi handler
|
|
|
+ * @buf: wmi message buffer
|
|
|
+ * @len: wmi message length
|
|
|
+ * @type: wmi message type
|
|
|
+ *
|
|
|
+ * Return: QDF_STATUS_SUCCESS on successful recording else failure.
|
|
|
+ */
|
|
|
+static QDF_STATUS wmi_ext_dbg_msg_record(struct wmi_unified *wmi_handle,
|
|
|
+ uint8_t *buf, uint32_t len,
|
|
|
+ enum WMI_MSG_TYPE type)
|
|
|
+{
|
|
|
+ struct wmi_ext_dbg_msg *msg;
|
|
|
+ uint32_t list_size;
|
|
|
+
|
|
|
+ msg = wmi_ext_dbg_msg_get(len);
|
|
|
+ if (!msg)
|
|
|
+ return QDF_STATUS_E_NOMEM;
|
|
|
+
|
|
|
+ msg->len = len;
|
|
|
+ msg->type = type;
|
|
|
+ qdf_mem_copy(msg->buf, buf, len);
|
|
|
+ msg->ts = qdf_get_log_timestamp();
|
|
|
+ list_size = wmi_ext_dbg_msg_enqueue(wmi_handle, msg);
|
|
|
+
|
|
|
+ if (list_size >= wmi_handle->wmi_ext_dbg_msg_queue_size) {
|
|
|
+ msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
|
|
|
+ wmi_ext_dbg_msg_put(msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
|
|
|
/**
|
|
|
- * wmi_debugfs_create() - Create debug_fs entry for wmi logging.
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handle
|
|
|
- * @par_entry: debug directory entry
|
|
|
- * @id: Index to debug info data array
|
|
|
+ * wmi_ext_dbg_msg_cmd_record() - record wmi command messages
|
|
|
+ * @wmi_handle: wmi handler
|
|
|
+ * @buf: wmi command buffer
|
|
|
+ * @len: wmi command message length
|
|
|
*
|
|
|
- * Return: none
|
|
|
+ * Return: QDF_STATUS_SUCCESS on successful recording else failure.
|
|
|
*/
|
|
|
-static void wmi_debugfs_create(wmi_unified_t wmi_handle,
|
|
|
- struct dentry *par_entry)
|
|
|
+static QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified *wmi_handle,
|
|
|
+ uint8_t *buf, uint32_t len)
|
|
|
{
|
|
|
- int i;
|
|
|
-
|
|
|
- if (!par_entry)
|
|
|
- goto out;
|
|
|
+ return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
|
|
|
+ WMI_MSG_TYPE_CMD);
|
|
|
+}
|
|
|
|
|
|
- for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
|
|
|
- wmi_handle->debugfs_de[i] = debugfs_create_file(
|
|
|
- wmi_debugfs_infos[i].name, 0644, par_entry,
|
|
|
- wmi_handle, wmi_debugfs_infos[i].ops);
|
|
|
+/**
|
|
|
+ * wmi_ext_dbg_msg_event_record() - record wmi event messages
|
|
|
+ * @wmi_handle: wmi handler
|
|
|
+ * @buf: wmi event buffer
|
|
|
+ * @len: wmi event message length
|
|
|
+ *
|
|
|
+ * Return: QDF_STATUS_SUCCESS on successful recording else failure.
|
|
|
+ */
|
|
|
+static QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified *wmi_handle,
|
|
|
+ uint8_t *buf, uint32_t len)
|
|
|
+{
|
|
|
+ uint32_t id;
|
|
|
|
|
|
- if (!wmi_handle->debugfs_de[i]) {
|
|
|
- WMI_LOGE("debug Entry creation failed!");
|
|
|
- goto out;
|
|
|
- }
|
|
|
- }
|
|
|
+ id = WMI_GET_FIELD(buf, WMI_CMD_HDR, COMMANDID);
|
|
|
+ if (id != wmi_handle->wmi_events[wmi_diag_event_id])
|
|
|
+ return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
|
|
|
+ WMI_MSG_TYPE_EVENT);
|
|
|
|
|
|
- return;
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
|
|
|
-out:
|
|
|
- WMI_LOGE("debug Entry creation failed!");
|
|
|
- wmi_log_buffer_free(wmi_handle);
|
|
|
- return;
|
|
|
+/**
|
|
|
+ * wmi_ext_dbg_msg_queue_init() - create debugfs queue and associated lock
|
|
|
+ * @wmi_handle: wmi handler
|
|
|
+ *
|
|
|
+ * Return: none
|
|
|
+ */
|
|
|
+static void wmi_ext_dbg_msg_queue_init(struct wmi_unified *wmi_handle)
|
|
|
+{
|
|
|
+ qdf_list_create(&wmi_handle->wmi_ext_dbg_msg_queue,
|
|
|
+ wmi_handle->wmi_ext_dbg_msg_queue_size);
|
|
|
+ qdf_spinlock_create(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * wmi_debugfs_remove() - Remove debugfs entry for wmi logging.
|
|
|
- * @wmi_handle: wmi handle
|
|
|
- * @dentry: debugfs directory entry
|
|
|
- * @id: Index to debug info data array
|
|
|
+ * wmi_ext_dbg_msg_queue_deinit() - destroy debugfs queue and associated lock
|
|
|
+ * @wmi_handle: wmi handler
|
|
|
*
|
|
|
* Return: none
|
|
|
*/
|
|
|
-static void wmi_debugfs_remove(wmi_unified_t wmi_handle)
|
|
|
+static void wmi_ext_dbg_msg_queue_deinit(struct wmi_unified *wmi_handle)
|
|
|
{
|
|
|
- int i;
|
|
|
- struct dentry *dentry = wmi_handle->log_info.wmi_log_debugfs_dir;
|
|
|
+ qdf_list_destroy(&wmi_handle->wmi_ext_dbg_msg_queue);
|
|
|
+ qdf_spinlock_destroy(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
+}
|
|
|
|
|
|
- if (dentry) {
|
|
|
- for (i = 0; i < NUM_DEBUG_INFOS; ++i) {
|
|
|
- if (wmi_handle->debugfs_de[i])
|
|
|
- wmi_handle->debugfs_de[i] = NULL;
|
|
|
- }
|
|
|
+/**
|
|
|
+ * wmi_ext_dbg_msg_show() - debugfs function to display whole content of
|
|
|
+ * wmi command/event messages including headers.
|
|
|
+ * @file: qdf debugfs file handler
|
|
|
+ * @arg: pointer to wmi handler
|
|
|
+ *
|
|
|
+ * Return: QDF_STATUS_SUCCESS if all the messages are shown successfully,
|
|
|
+ * else QDF_STATUS_E_AGAIN if more data to show.
|
|
|
+ */
|
|
|
+static QDF_STATUS wmi_ext_dbg_msg_show(qdf_debugfs_file_t file, void *arg)
|
|
|
+{
|
|
|
+ struct wmi_unified *wmi_handle = (struct wmi_unified *)arg;
|
|
|
+ struct wmi_ext_dbg_msg *msg;
|
|
|
+ uint64_t secs, usecs;
|
|
|
+
|
|
|
+ msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
|
|
|
+ if (!msg)
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ qdf_debugfs_printf(file, "%s: 0x%x\n",
|
|
|
+ msg->type == WMI_MSG_TYPE_CMD ? "COMMAND" :
|
|
|
+ "EVENT", WMI_GET_FIELD(msg->buf, WMI_CMD_HDR,
|
|
|
+ COMMANDID));
|
|
|
+ qdf_log_timestamp_to_secs(msg->ts, &secs, &usecs);
|
|
|
+ qdf_debugfs_printf(file, "Time: %llu.%llu\n", secs, usecs);
|
|
|
+ qdf_debugfs_printf(file, "Length:%d\n", msg->len);
|
|
|
+ qdf_debugfs_hexdump(file, msg->buf, msg->len,
|
|
|
+ WMI_EXT_DBG_DUMP_ROW_SIZE,
|
|
|
+ WMI_EXT_DBG_DUMP_GROUP_SIZE);
|
|
|
+ qdf_debugfs_printf(file, "\n");
|
|
|
+
|
|
|
+ if (qdf_debugfs_overflow(file)) {
|
|
|
+ qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
+ qdf_list_insert_front(&wmi_handle->wmi_ext_dbg_msg_queue,
|
|
|
+ &msg->node);
|
|
|
+ qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ wmi_ext_dbg_msg_put(msg);
|
|
|
}
|
|
|
|
|
|
- if (dentry)
|
|
|
- debugfs_remove_recursive(dentry);
|
|
|
+ return QDF_STATUS_E_AGAIN;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * wmi_debugfs_init() - debugfs functions to create debugfs directory and to
|
|
|
- * create debugfs enteries.
|
|
|
+ * wmi_ext_dbg_msg_write() - debugfs write not supported
|
|
|
+ * @priv: private data
|
|
|
+ * @buf: received data buffer
|
|
|
+ * @len: length of received buffer
|
|
|
*
|
|
|
- * @h: wmi handler
|
|
|
+ * Return: QDF_STATUS_E_NOSUPPORT.
|
|
|
+ */
|
|
|
+static QDF_STATUS wmi_ext_dbg_msg_write(void *priv, const char *buf,
|
|
|
+ qdf_size_t len)
|
|
|
+{
|
|
|
+ return QDF_STATUS_E_NOSUPPORT;
|
|
|
+}
|
|
|
+
|
|
|
+static struct qdf_debugfs_fops wmi_ext_dbgfs_ops[WMI_MAX_RADIOS];
|
|
|
+
|
|
|
+/**
|
|
|
+ * wmi_ext_debugfs_init() - init debugfs items for extended wmi dump.
|
|
|
+ * @wmi_handle: wmi handler
|
|
|
+ * @pdev_idx: pdev index
|
|
|
*
|
|
|
- * Return: init status
|
|
|
+ * Return: QDF_STATUS_SUCCESS if debugfs is initialized else
|
|
|
+ * QDF_STATUS_E_FAILURE
|
|
|
*/
|
|
|
-static QDF_STATUS wmi_debugfs_init(wmi_unified_t wmi_handle, uint32_t pdev_idx)
|
|
|
+static QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle,
|
|
|
+ uint32_t pdev_idx)
|
|
|
{
|
|
|
+ qdf_dentry_t dentry;
|
|
|
char buf[32];
|
|
|
|
|
|
- snprintf(buf, sizeof(buf), "WMI_SOC%u_PDEV%u",
|
|
|
- wmi_handle->soc->soc_idx, pdev_idx);
|
|
|
+ /* To maintain backward compatibility, naming convention for PDEV 0
|
|
|
+ * dentry is kept same as before. For more than 1 PDEV, dentry
|
|
|
+ * names will be appended with PDEVx.
|
|
|
+ */
|
|
|
+ if (wmi_handle->soc->soc_idx == 0 && pdev_idx == 0) {
|
|
|
+ dentry = qdf_debugfs_create_dir(WMI_EXT_DBG_DIR, NULL);
|
|
|
+ } else {
|
|
|
+ snprintf(buf, sizeof(buf), "WMI_EXT_DBG_SOC%u_PDEV%u",
|
|
|
+ wmi_handle->soc->soc_idx, pdev_idx);
|
|
|
+ dentry = qdf_debugfs_create_dir(buf, NULL);
|
|
|
+ }
|
|
|
|
|
|
- wmi_handle->log_info.wmi_log_debugfs_dir =
|
|
|
- debugfs_create_dir(buf, NULL);
|
|
|
+ if (!dentry) {
|
|
|
+ WMI_LOGE("error while creating extended wmi debugfs dir");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
|
|
|
- if (!wmi_handle->log_info.wmi_log_debugfs_dir) {
|
|
|
- WMI_LOGE("error while creating debugfs dir for %s", buf);
|
|
|
+ wmi_ext_dbgfs_ops[pdev_idx].show = wmi_ext_dbg_msg_show;
|
|
|
+ wmi_ext_dbgfs_ops[pdev_idx].write = wmi_ext_dbg_msg_write;
|
|
|
+ wmi_ext_dbgfs_ops[pdev_idx].priv = wmi_handle;
|
|
|
+ if (!qdf_debugfs_create_file(WMI_EXT_DBG_FILE, WMI_EXT_DBG_FILE_PERM,
|
|
|
+ dentry, &wmi_ext_dbgfs_ops[pdev_idx])) {
|
|
|
+ qdf_debugfs_remove_dir(dentry);
|
|
|
+ WMI_LOGE("error while creating extended wmi debugfs file");
|
|
|
return QDF_STATUS_E_FAILURE;
|
|
|
}
|
|
|
- wmi_debugfs_create(wmi_handle,
|
|
|
- wmi_handle->log_info.wmi_log_debugfs_dir);
|
|
|
+
|
|
|
+ wmi_handle->wmi_ext_dbg_dentry = dentry;
|
|
|
+ wmi_handle->wmi_ext_dbg_msg_queue_size = WMI_EXT_DBG_QUEUE_SIZE;
|
|
|
+ wmi_ext_dbg_msg_queue_init(wmi_handle);
|
|
|
|
|
|
return QDF_STATUS_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * wmi_mgmt_cmd_record() - Wrapper function for mgmt command logging macro
|
|
|
- *
|
|
|
- * @wmi_handle: wmi handle
|
|
|
- * @cmd: mgmt command
|
|
|
- * @header: pointer to 802.11 header
|
|
|
- * @vdev_id: vdev id
|
|
|
- * @chanfreq: channel frequency
|
|
|
+ * wmi_ext_debugfs_deinit() - cleanup/deinit debugfs items of extended wmi dump.
|
|
|
+ * @wmi_handle: wmi handler
|
|
|
*
|
|
|
- * Return: none
|
|
|
+ * Return: QDF_STATUS_SUCCESS if cleanup is successful
|
|
|
*/
|
|
|
-void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
|
|
|
- void *header, uint32_t vdev_id, uint32_t chanfreq)
|
|
|
+static QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
|
|
|
{
|
|
|
+ struct wmi_ext_dbg_msg *msg;
|
|
|
|
|
|
- uint32_t data[CUSTOM_MGMT_CMD_DATA_SIZE];
|
|
|
-
|
|
|
- data[0] = ((struct wmi_command_header *)header)->type;
|
|
|
- data[1] = ((struct wmi_command_header *)header)->sub_type;
|
|
|
- data[2] = vdev_id;
|
|
|
- data[3] = chanfreq;
|
|
|
+ while ((msg = wmi_ext_dbg_msg_dequeue(wmi_handle)))
|
|
|
+ wmi_ext_dbg_msg_put(msg);
|
|
|
|
|
|
- qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
|
|
|
+ wmi_ext_dbg_msg_queue_deinit(wmi_handle);
|
|
|
+ qdf_debugfs_remove_dir_recursive(wmi_handle->wmi_ext_dbg_dentry);
|
|
|
|
|
|
- WMI_MGMT_COMMAND_RECORD(wmi_handle, cmd, (uint8_t *)data);
|
|
|
- wmi_specific_cmd_record(wmi_handle, cmd, (uint8_t *)data);
|
|
|
- qdf_spin_unlock_bh(&wmi_handle->log_info.wmi_record_lock);
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
}
|
|
|
+
|
|
|
#else
|
|
|
-/**
|
|
|
- * wmi_debugfs_remove() - Remove debugfs entry for wmi logging.
|
|
|
- * @wmi_handle: wmi handle
|
|
|
- * @dentry: debugfs directory entry
|
|
|
- * @id: Index to debug info data array
|
|
|
- *
|
|
|
- * Return: none
|
|
|
- */
|
|
|
-static void wmi_debugfs_remove(wmi_unified_t wmi_handle) { }
|
|
|
-void wmi_mgmt_cmd_record(wmi_unified_t wmi_handle, uint32_t cmd,
|
|
|
- void *header, uint32_t vdev_id, uint32_t chanfreq) { }
|
|
|
-static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle) { }
|
|
|
-#endif /*WMI_INTERFACE_EVENT_LOGGING */
|
|
|
-qdf_export_symbol(wmi_mgmt_cmd_record);
|
|
|
+
|
|
|
+static inline QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified
|
|
|
+ *wmi_handle,
|
|
|
+ uint8_t *buf, uint32_t len)
|
|
|
+{
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static inline QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified
|
|
|
+ *wmi_handle,
|
|
|
+ uint8_t *buf, uint32_t len)
|
|
|
+{
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static inline QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle,
|
|
|
+ uint32_t pdev_idx)
|
|
|
+{
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static inline QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
|
|
|
+{
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+#endif /*WMI_EXT_DBG */
|
|
|
|
|
|
int wmi_get_host_credits(wmi_unified_t wmi_handle);
|
|
|
/* WMI buffer APIs */
|
|
@@ -2754,6 +2781,9 @@ void *wmi_unified_get_pdev_handle(struct wmi_soc *soc, uint32_t pdev_idx)
|
|
|
wmi_handle->wmi_max_cmds = soc->wmi_max_cmds;
|
|
|
|
|
|
wmi_interface_sequence_init(wmi_handle);
|
|
|
+ if (wmi_ext_dbgfs_init(wmi_handle, pdev_idx) !=
|
|
|
+ QDF_STATUS_SUCCESS)
|
|
|
+ WMI_LOGE("failed to initialize wmi extended debugfs");
|
|
|
|
|
|
soc->wmi_pdev[pdev_idx] = wmi_handle;
|
|
|
} else
|
|
@@ -2902,7 +2932,7 @@ void *wmi_unified_attach(void *scn_handle,
|
|
|
qdf_spinlock_create(&soc->ctx_lock);
|
|
|
soc->ops = wmi_handle->ops;
|
|
|
soc->wmi_pdev[0] = wmi_handle;
|
|
|
- if (wmi_ext_dbgfs_init(wmi_handle) != QDF_STATUS_SUCCESS)
|
|
|
+ if (wmi_ext_dbgfs_init(wmi_handle, 0) != QDF_STATUS_SUCCESS)
|
|
|
WMI_LOGE("failed to initialize wmi extended debugfs");
|
|
|
|
|
|
wmi_wbuff_register(wmi_handle);
|
|
@@ -2935,8 +2965,6 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle)
|
|
|
|
|
|
wmi_wbuff_deregister(wmi_handle);
|
|
|
|
|
|
- wmi_ext_dbgfs_deinit(wmi_handle);
|
|
|
-
|
|
|
soc = wmi_handle->soc;
|
|
|
for (i = 0; i < WMI_MAX_RADIOS; i++) {
|
|
|
if (soc->wmi_pdev[i]) {
|
|
@@ -2963,6 +2991,7 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle)
|
|
|
qdf_spinlock_destroy(&soc->wmi_pdev[i]->eventq_lock);
|
|
|
|
|
|
wmi_interface_sequence_deinit(soc->wmi_pdev[i]);
|
|
|
+ wmi_ext_dbgfs_deinit(soc->wmi_pdev[i]);
|
|
|
|
|
|
qdf_mem_free(soc->wmi_pdev[i]);
|
|
|
}
|