Merge "usb: dwc3: debug: Add logging APIs using IPC logging framework"

This commit is contained in:
qctecmdr 2019-10-25 10:19:26 -07:00 • committed by Gerrit - the friendly Code Review server
commit ffc159f25b
5 changed files with 204 additions and 1 deletions

View file

@ -4,7 +4,7 @@ CFLAGS_trace.o := -I$(src)
obj-$(CONFIG_USB_DWC3) += dwc3.o
dwc3-y := core.o
dwc3-y := core.o debug_ipc.o
ifneq ($(CONFIG_TRACING),)
dwc3-y += trace.o

View file

@ -40,6 +40,9 @@
#define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */
static int count;
static struct dwc3 *dwc3_instance[DWC_CTRL_COUNT];
/**
* dwc3_get_dr_mode - Validates and sets dr_mode
* @dwc: pointer to our context structure
@ -1523,6 +1526,16 @@ static int dwc3_probe(struct platform_device *pdev)
goto err5;
dwc3_debugfs_init(dwc);
dwc->dwc_ipc_log_ctxt = ipc_log_context_create(NUM_LOG_PAGES,
dev_name(dwc->dev), 0);
if (!dwc->dwc_ipc_log_ctxt)
dev_err(dwc->dev, "Error getting ipc_log_ctxt\n");
dwc3_instance[count] = dwc;
dwc->index = count;
count++;
pm_runtime_put(dev);
return 0;
@ -1571,6 +1584,11 @@ static int dwc3_remove(struct platform_device *pdev)
dwc3_free_event_buffers(dwc);
dwc3_free_scratch_buffers(dwc);
ipc_log_context_destroy(dwc->dwc_ipc_log_ctxt);
dwc->dwc_ipc_log_ctxt = NULL;
count--;
dwc3_instance[dwc->index] = NULL;
return 0;
}

View file

@ -606,6 +606,9 @@
#define DWC3_OSTS_VBUSVLD BIT(1)
#define DWC3_OSTS_CONIDSTS BIT(0)
#define DWC_CTRL_COUNT 10
#define NUM_LOG_PAGES 12
/* Structures */
struct dwc3_trb;
@ -1033,6 +1036,8 @@ struct dwc3_scratchpad_array {
* @imod_interval: set the interrupt moderation interval in 250ns
* increments or 0 to disable.
* @xhci_imod_value: imod value to use with xhci
* @index: dwc3's instance number
* @dwc_ipc_log_ctxt: dwc3 ipc log context
*/
struct dwc3 {
struct work_struct drd_work;
@ -1223,6 +1228,9 @@ struct dwc3 {
u16 imod_interval;
u32 xhci_imod_value;
unsigned int index;
void *dwc_ipc_log_ctxt;
};
#define INCRX_BURST_MODE 0

View file

@ -12,6 +12,33 @@
#define __DWC3_DEBUG_H
#include "core.h"
#include <linux/ipc_logging.h>
/*
* NOTE: Make sure to have dwc as local variable in function before using
* below macros.
*/
#define dbg_event(ep_num, name, status) \
dwc3_dbg_print(dwc, ep_num, name, status, "")
#define dbg_print(ep_num, name, status, extra) \
dwc3_dbg_print(dwc, ep_num, name, status, extra)
#define dbg_print_reg(name, reg) \
dwc3_dbg_print_reg(dwc, name, reg)
#define dbg_done(ep_num, count, status) \
dwc3_dbg_done(dwc, ep_num, count, status)
#define dbg_queue(ep_num, req, status) \
dwc3_dbg_queue(dwc, ep_num, req, status)
#define dbg_setup(ep_num, req) \
dwc3_dbg_setup(dwc, ep_num, req)
#define dbg_log_string(fmt, ...) \
ipc_log_string(dwc->dwc_ipc_log_ctxt,\
"%s: " fmt, __func__, ##__VA_ARGS__)
/**
* dwc3_gadget_ep_cmd_string - returns endpoint command string
@ -416,6 +443,18 @@ static inline const char *dwc3_gadget_generic_cmd_status_string(int status)
}
}
void dwc3_dbg_print(struct dwc3 *dwc, u8 ep_num,
const char *name, int status, const char *extra);
void dwc3_dbg_done(struct dwc3 *dwc, u8 ep_num,
const u32 count, int status);
void dwc3_dbg_event(struct dwc3 *dwc, u8 ep_num,
const char *name, int status);
void dwc3_dbg_queue(struct dwc3 *dwc, u8 ep_num,
const struct usb_request *req, int status);
void dwc3_dbg_setup(struct dwc3 *dwc, u8 ep_num,
const struct usb_ctrlrequest *req);
void dwc3_dbg_print_reg(struct dwc3 *dwc,
const char *name, int reg);
#ifdef CONFIG_DEBUG_FS
extern void dwc3_debugfs_init(struct dwc3 *);

View file

@ -0,0 +1,138 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*/
#include "debug.h"
#include <linux/moduleparam.h>
static unsigned int ep_addr_rxdbg_mask = 1;
module_param(ep_addr_rxdbg_mask, uint, 0644);
static unsigned int ep_addr_txdbg_mask = 1;
module_param(ep_addr_txdbg_mask, uint, 0644);
static int allow_dbg_print(u8 ep_num)
{
int dir, num;
/* allow bus wide events */
if (ep_num == 0xff)
return 1;
dir = ep_num & 0x1;
num = ep_num >> 1;
num = 1 << num;
if (dir && (num & ep_addr_txdbg_mask))
return 1;
if (!dir && (num & ep_addr_rxdbg_mask))
return 1;
return 0;
}
/**
* dwc3_dbg_print: prints the common part of the event
* @addr: endpoint address
* @name: event name
* @status: status
* @extra: extra information
* @dwc3: pointer to struct dwc3
*/
void dwc3_dbg_print(struct dwc3 *dwc, u8 ep_num, const char *name,
int status, const char *extra)
{
if (!allow_dbg_print(ep_num))
return;
if (name == NULL)
return;
ipc_log_string(dwc->dwc_ipc_log_ctxt, "%02X %-25.25s %4i ?\t%s",
ep_num, name, status, extra);
}
/**
* dwc3_dbg_done: prints a DONE event
* @addr: endpoint address
* @td: transfer descriptor
* @status: status
* @dwc3: pointer to struct dwc3
*/
void dwc3_dbg_done(struct dwc3 *dwc, u8 ep_num,
const u32 count, int status)
{
if (!allow_dbg_print(ep_num))
return;
ipc_log_string(dwc->dwc_ipc_log_ctxt, "%02X %-25.25s %4i ?\t%d",
ep_num, "DONE", status, count);
}
/**
* dwc3_dbg_event: prints a generic event
* @addr: endpoint address
* @name: event name
* @status: status
*/
void dwc3_dbg_event(struct dwc3 *dwc, u8 ep_num, const char *name, int status)
{
if (!allow_dbg_print(ep_num))
return;
if (name != NULL)
dwc3_dbg_print(dwc, ep_num, name, status, "");
}
/*
* dwc3_dbg_queue: prints a QUEUE event
* @addr: endpoint address
* @req: USB request
* @status: status
*/
void dwc3_dbg_queue(struct dwc3 *dwc, u8 ep_num,
const struct usb_request *req, int status)
{
if (!allow_dbg_print(ep_num))
return;
if (req != NULL) {
ipc_log_string(dwc->dwc_ipc_log_ctxt,
"%02X %-25.25s %4i ?\t%d %d", ep_num, "QUEUE", status,
!req->no_interrupt, req->length);
}
}
/**
* dwc3_dbg_setup: prints a SETUP event
* @addr: endpoint address
* @req: setup request
*/
void dwc3_dbg_setup(struct dwc3 *dwc, u8 ep_num,
const struct usb_ctrlrequest *req)
{
if (!allow_dbg_print(ep_num))
return;
if (req != NULL) {
ipc_log_string(dwc->dwc_ipc_log_ctxt,
"%02X %-25.25s ?\t%02X %02X %04X %04X %d",
ep_num, "SETUP", req->bRequestType,
req->bRequest, le16_to_cpu(req->wValue),
le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
}
}
/**
* dwc3_dbg_print_reg: prints a reg value
* @name: reg name
* @reg: reg value to be printed
*/
void dwc3_dbg_print_reg(struct dwc3 *dwc, const char *name, int reg)
{
if (name == NULL)
return;
ipc_log_string(dwc->dwc_ipc_log_ctxt, "%s = 0x%08x", name, reg);
}