Commit 07a3aef2 authored by Pawel Laszczak's avatar Pawel Laszczak Committed by Greg Kroah-Hartman

usb: cdns2: Add tracepoints for CDNS2 driver

Patch adds the series of tracepoints that can be used for
debugging issues detected in driver.
Signed-off-by: default avatarPawel Laszczak <pawell@cadence.com>
Message-ID: <20230602102644.77470-4-pawell@cadence.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3eb1f1ef
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# define_trace.h needs to know how to find our header # define_trace.h needs to know how to find our header
CFLAGS_cdns2-trace.o := -I$(src)
obj-$(CONFIG_USB_CDNS2_UDC) += cdns2-udc-pci.o obj-$(CONFIG_USB_CDNS2_UDC) += cdns2-udc-pci.o
cdns2-udc-pci-$(CONFIG_USB_CDNS2_UDC) += cdns2-pci.o cdns2-gadget.o cdns2-ep0.o cdns2-udc-pci-$(CONFIG_USB_CDNS2_UDC) += cdns2-pci.o cdns2-gadget.o cdns2-ep0.o
cdns2-udc-pci-$(CONFIG_TRACING) += cdns2-trace.o
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Cadence USBHS-DEV Driver.
* Debug header file.
*
* Copyright (C) 2023 Cadence.
*
* Author: Pawel Laszczak <pawell@cadence.com>
*/
#ifndef __LINUX_CDNS2_DEBUG
#define __LINUX_CDNS2_DEBUG
static inline const char *cdns2_decode_usb_irq(char *str, size_t size,
u8 usb_irq, u8 ext_irq)
{
int ret;
ret = snprintf(str, size, "usbirq: 0x%02x - ", usb_irq);
if (usb_irq & USBIRQ_SOF)
ret += snprintf(str + ret, size - ret, "SOF ");
if (usb_irq & USBIRQ_SUTOK)
ret += snprintf(str + ret, size - ret, "SUTOK ");
if (usb_irq & USBIRQ_SUDAV)
ret += snprintf(str + ret, size - ret, "SETUP ");
if (usb_irq & USBIRQ_SUSPEND)
ret += snprintf(str + ret, size - ret, "Suspend ");
if (usb_irq & USBIRQ_URESET)
ret += snprintf(str + ret, size - ret, "Reset ");
if (usb_irq & USBIRQ_HSPEED)
ret += snprintf(str + ret, size - ret, "HS ");
if (usb_irq & USBIRQ_LPM)
ret += snprintf(str + ret, size - ret, "LPM ");
ret += snprintf(str + ret, size - ret, ", EXT: 0x%02x - ", ext_irq);
if (ext_irq & EXTIRQ_WAKEUP)
ret += snprintf(str + ret, size - ret, "Wakupe ");
if (ext_irq & EXTIRQ_VBUSFAULT_FALL)
ret += snprintf(str + ret, size - ret, "VBUS_FALL ");
if (ext_irq & EXTIRQ_VBUSFAULT_RISE)
ret += snprintf(str + ret, size - ret, "VBUS_RISE ");
if (ret >= size)
pr_info("CDNS2: buffer overflowed.\n");
return str;
}
static inline const char *cdns2_decode_dma_irq(char *str, size_t size,
u32 ep_ists, u32 ep_sts,
const char *ep_name)
{
int ret;
ret = snprintf(str, size, "ISTS: %08x, %s: %08x ",
ep_ists, ep_name, ep_sts);
if (ep_sts & DMA_EP_STS_IOC)
ret += snprintf(str + ret, size - ret, "IOC ");
if (ep_sts & DMA_EP_STS_ISP)
ret += snprintf(str + ret, size - ret, "ISP ");
if (ep_sts & DMA_EP_STS_DESCMIS)
ret += snprintf(str + ret, size - ret, "DESCMIS ");
if (ep_sts & DMA_EP_STS_TRBERR)
ret += snprintf(str + ret, size - ret, "TRBERR ");
if (ep_sts & DMA_EP_STS_OUTSMM)
ret += snprintf(str + ret, size - ret, "OUTSMM ");
if (ep_sts & DMA_EP_STS_ISOERR)
ret += snprintf(str + ret, size - ret, "ISOERR ");
if (ep_sts & DMA_EP_STS_DBUSY)
ret += snprintf(str + ret, size - ret, "DBUSY ");
if (DMA_EP_STS_CCS(ep_sts))
ret += snprintf(str + ret, size - ret, "CCS ");
if (ret >= size)
pr_info("CDNS2: buffer overflowed.\n");
return str;
}
static inline const char *cdns2_decode_epx_irq(char *str, size_t size,
char *ep_name, u32 ep_ists,
u32 ep_sts)
{
return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts, ep_name);
}
static inline const char *cdns2_decode_ep0_irq(char *str, size_t size,
u32 ep_ists, u32 ep_sts,
int dir)
{
return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts,
dir ? "ep0IN" : "ep0OUT");
}
static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep,
struct cdns2_trb *trbs,
char *str, size_t size)
{
struct cdns2_ring *ring = &pep->ring;
struct cdns2_trb *trb;
dma_addr_t dma;
int ret;
int i;
ret = snprintf(str, size, "\n\t\tTR for %s:", pep->name);
trb = &trbs[ring->dequeue];
dma = cdns2_trb_virt_to_dma(pep, trb);
ret += snprintf(str + ret, size - ret,
"\n\t\tRing deq index: %d, trb: V=%p, P=0x%pad\n",
ring->dequeue, trb, &dma);
trb = &trbs[ring->enqueue];
dma = cdns2_trb_virt_to_dma(pep, trb);
ret += snprintf(str + ret, size - ret,
"\t\tRing enq index: %d, trb: V=%p, P=0x%pad\n",
ring->enqueue, trb, &dma);
ret += snprintf(str + ret, size - ret,
"\t\tfree trbs: %d, CCS=%d, PCS=%d\n",
ring->free_trbs, ring->ccs, ring->pcs);
if (TRBS_PER_SEGMENT > 40) {
ret += snprintf(str + ret, size - ret,
"\t\tTransfer ring %d too big\n", TRBS_PER_SEGMENT);
return str;
}
dma = ring->dma;
for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
trb = &trbs[i];
ret += snprintf(str + ret, size - ret,
"\t\t@%pad %08x %08x %08x\n", &dma,
le32_to_cpu(trb->buffer),
le32_to_cpu(trb->length),
le32_to_cpu(trb->control));
dma += sizeof(*trb);
}
if (ret >= size)
pr_info("CDNS2: buffer overflowed.\n");
return str;
}
static inline const char *cdns2_trb_type_string(u8 type)
{
switch (type) {
case TRB_NORMAL:
return "Normal";
case TRB_LINK:
return "Link";
default:
return "UNKNOWN";
}
}
static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags,
u32 length, u32 buffer)
{
int type = TRB_FIELD_TO_TYPE(flags);
int ret;
switch (type) {
case TRB_LINK:
ret = snprintf(str, size,
"LINK %08x type '%s' flags %c:%c:%c%c:%c",
buffer, cdns2_trb_type_string(type),
flags & TRB_CYCLE ? 'C' : 'c',
flags & TRB_TOGGLE ? 'T' : 't',
flags & TRB_CHAIN ? 'C' : 'c',
flags & TRB_CHAIN ? 'H' : 'h',
flags & TRB_IOC ? 'I' : 'i');
break;
case TRB_NORMAL:
ret = snprintf(str, size,
"type: '%s', Buffer: %08x, length: %ld, burst len: %ld, "
"flags %c:%c:%c%c:%c",
cdns2_trb_type_string(type),
buffer, TRB_LEN(length),
TRB_FIELD_TO_BURST(length),
flags & TRB_CYCLE ? 'C' : 'c',
flags & TRB_ISP ? 'I' : 'i',
flags & TRB_CHAIN ? 'C' : 'c',
flags & TRB_CHAIN ? 'H' : 'h',
flags & TRB_IOC ? 'I' : 'i');
break;
default:
ret = snprintf(str, size, "type '%s' -> raw %08x %08x %08x",
cdns2_trb_type_string(type),
buffer, length, flags);
}
if (ret >= size)
pr_info("CDNS2: buffer overflowed.\n");
return str;
}
#endif /*__LINUX_CDNS2_DEBUG*/
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "cdns2-gadget.h" #include "cdns2-gadget.h"
#include "cdns2-trace.h"
static struct usb_endpoint_descriptor cdns2_gadget_ep0_desc = { static struct usb_endpoint_descriptor cdns2_gadget_ep0_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
...@@ -60,6 +61,8 @@ static void cdns2_ep0_enqueue(struct cdns2_device *pdev, dma_addr_t dma_addr, ...@@ -60,6 +61,8 @@ static void cdns2_ep0_enqueue(struct cdns2_device *pdev, dma_addr_t dma_addr,
ring->trbs[1].control = 0; ring->trbs[1].control = 0;
} }
trace_cdns2_queue_trb(pep, ring->trbs);
if (!pep->dir) if (!pep->dir)
writel(0, &pdev->ep0_regs->rxbc); writel(0, &pdev->ep0_regs->rxbc);
...@@ -68,6 +71,8 @@ static void cdns2_ep0_enqueue(struct cdns2_device *pdev, dma_addr_t dma_addr, ...@@ -68,6 +71,8 @@ static void cdns2_ep0_enqueue(struct cdns2_device *pdev, dma_addr_t dma_addr,
writel(DMA_EP_STS_TRBERR, &regs->ep_sts); writel(DMA_EP_STS_TRBERR, &regs->ep_sts);
writel(pep->ring.dma, &regs->ep_traddr); writel(pep->ring.dma, &regs->ep_traddr);
trace_cdns2_doorbell_ep0(pep, readl(&regs->ep_traddr));
writel(DMA_EP_CMD_DRDY, &regs->ep_cmd); writel(DMA_EP_CMD_DRDY, &regs->ep_cmd);
} }
...@@ -128,6 +133,8 @@ static int cdns2_req_ep0_set_configuration(struct cdns2_device *pdev, ...@@ -128,6 +133,8 @@ static int cdns2_req_ep0_set_configuration(struct cdns2_device *pdev,
if (ret) if (ret)
return ret; return ret;
trace_cdns2_device_state(config ? "configured" : "addressed");
if (!config) if (!config)
usb_gadget_set_state(&pdev->gadget, USB_STATE_ADDRESS); usb_gadget_set_state(&pdev->gadget, USB_STATE_ADDRESS);
...@@ -158,6 +165,8 @@ static int cdns2_req_ep0_set_address(struct cdns2_device *pdev, u32 addr) ...@@ -158,6 +165,8 @@ static int cdns2_req_ep0_set_address(struct cdns2_device *pdev, u32 addr)
usb_gadget_set_state(&pdev->gadget, usb_gadget_set_state(&pdev->gadget,
(addr ? USB_STATE_ADDRESS : USB_STATE_DEFAULT)); (addr ? USB_STATE_ADDRESS : USB_STATE_DEFAULT));
trace_cdns2_device_state(addr ? "addressed" : "default");
return 0; return 0;
} }
...@@ -385,8 +394,12 @@ void cdns2_handle_setup_packet(struct cdns2_device *pdev) ...@@ -385,8 +394,12 @@ void cdns2_handle_setup_packet(struct cdns2_device *pdev)
* If SETUP packet was modified while reading just simple ignore it. * If SETUP packet was modified while reading just simple ignore it.
* The new one will be handled latter. * The new one will be handled latter.
*/ */
if (cdns2_check_new_setup(pdev)) if (cdns2_check_new_setup(pdev)) {
trace_cdns2_ep0_setup("overridden");
return; return;
}
trace_cdns2_ctrl_req(ctrl);
if (!pdev->gadget_driver) if (!pdev->gadget_driver)
goto out; goto out;
...@@ -431,8 +444,10 @@ void cdns2_handle_setup_packet(struct cdns2_device *pdev) ...@@ -431,8 +444,10 @@ void cdns2_handle_setup_packet(struct cdns2_device *pdev)
else else
ret = cdns2_ep0_delegate_req(pdev); ret = cdns2_ep0_delegate_req(pdev);
if (ret == USB_GADGET_DELAYED_STATUS) if (ret == USB_GADGET_DELAYED_STATUS) {
trace_cdns2_ep0_status_stage("delayed");
return; return;
}
out: out:
if (ret < 0) if (ret < 0)
...@@ -448,6 +463,7 @@ static void cdns2_transfer_completed(struct cdns2_device *pdev) ...@@ -448,6 +463,7 @@ static void cdns2_transfer_completed(struct cdns2_device *pdev)
if (!list_empty(&pep->pending_list)) { if (!list_empty(&pep->pending_list)) {
struct cdns2_request *preq; struct cdns2_request *preq;
trace_cdns2_complete_trb(pep, pep->ring.trbs);
preq = cdns2_next_preq(&pep->pending_list); preq = cdns2_next_preq(&pep->pending_list);
preq->request.actual = preq->request.actual =
...@@ -464,6 +480,8 @@ void cdns2_handle_ep0_interrupt(struct cdns2_device *pdev, int dir) ...@@ -464,6 +480,8 @@ void cdns2_handle_ep0_interrupt(struct cdns2_device *pdev, int dir)
cdns2_select_ep(pdev, dir); cdns2_select_ep(pdev, dir);
trace_cdns2_ep0_irq(pdev);
ep_sts_reg = readl(&pdev->adma_regs->ep_sts); ep_sts_reg = readl(&pdev->adma_regs->ep_sts);
writel(ep_sts_reg, &pdev->adma_regs->ep_sts); writel(ep_sts_reg, &pdev->adma_regs->ep_sts);
...@@ -530,8 +548,11 @@ static int cdns2_gadget_ep0_queue(struct usb_ep *ep, ...@@ -530,8 +548,11 @@ static int cdns2_gadget_ep0_queue(struct usb_ep *ep,
preq = to_cdns2_request(request); preq = to_cdns2_request(request);
trace_cdns2_request_enqueue(preq);
/* Cancel the request if controller receive new SETUP packet. */ /* Cancel the request if controller receive new SETUP packet. */
if (cdns2_check_new_setup(pdev)) { if (cdns2_check_new_setup(pdev)) {
trace_cdns2_ep0_setup("overridden");
spin_unlock_irqrestore(&pdev->lock, flags); spin_unlock_irqrestore(&pdev->lock, flags);
return -ECONNRESET; return -ECONNRESET;
} }
...@@ -556,6 +577,7 @@ static int cdns2_gadget_ep0_queue(struct usb_ep *ep, ...@@ -556,6 +577,7 @@ static int cdns2_gadget_ep0_queue(struct usb_ep *ep,
} }
if (!list_empty(&pep->pending_list)) { if (!list_empty(&pep->pending_list)) {
trace_cdns2_ep0_setup("pending");
dev_err(pdev->dev, dev_err(pdev->dev,
"can't handle multiple requests for ep0\n"); "can't handle multiple requests for ep0\n");
spin_unlock_irqrestore(&pdev->lock, flags); spin_unlock_irqrestore(&pdev->lock, flags);
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include "cdns2-gadget.h" #include "cdns2-gadget.h"
#include "cdns2-trace.h"
/** /**
* set_reg_bit_32 - set bit in given 32 bits register. * set_reg_bit_32 - set bit in given 32 bits register.
...@@ -154,6 +155,8 @@ static void cdns2_ep_stall_flush(struct cdns2_endpoint *pep) ...@@ -154,6 +155,8 @@ static void cdns2_ep_stall_flush(struct cdns2_endpoint *pep)
struct cdns2_device *pdev = pep->pdev; struct cdns2_device *pdev = pep->pdev;
int val; int val;
trace_cdns2_ep_halt(pep, 1, 1);
writel(DMA_EP_CMD_DFLUSH, &pdev->adma_regs->ep_cmd); writel(DMA_EP_CMD_DFLUSH, &pdev->adma_regs->ep_cmd);
/* Wait for DFLUSH cleared. */ /* Wait for DFLUSH cleared. */
...@@ -247,6 +250,8 @@ void cdns2_gadget_giveback(struct cdns2_endpoint *pep, ...@@ -247,6 +250,8 @@ void cdns2_gadget_giveback(struct cdns2_endpoint *pep,
/* All TRBs have finished, clear the counter. */ /* All TRBs have finished, clear the counter. */
preq->finished_trb = 0; preq->finished_trb = 0;
trace_cdns2_request_giveback(preq);
if (request->complete) { if (request->complete) {
spin_unlock(&pdev->lock); spin_unlock(&pdev->lock);
usb_gadget_giveback_request(&pep->endpoint, request); usb_gadget_giveback_request(&pep->endpoint, request);
...@@ -261,6 +266,8 @@ static void cdns2_wa1_restore_cycle_bit(struct cdns2_endpoint *pep) ...@@ -261,6 +266,8 @@ static void cdns2_wa1_restore_cycle_bit(struct cdns2_endpoint *pep)
{ {
/* Work around for stale data address in TRB. */ /* Work around for stale data address in TRB. */
if (pep->wa1_set) { if (pep->wa1_set) {
trace_cdns2_wa1(pep, "restore cycle bit");
pep->wa1_set = 0; pep->wa1_set = 0;
pep->wa1_trb_index = 0xFFFF; pep->wa1_trb_index = 0xFFFF;
if (pep->wa1_cycle_bit) if (pep->wa1_cycle_bit)
...@@ -285,6 +292,7 @@ static int cdns2_wa1_update_guard(struct cdns2_endpoint *pep, ...@@ -285,6 +292,7 @@ static int cdns2_wa1_update_guard(struct cdns2_endpoint *pep,
pep->wa1_set = 1; pep->wa1_set = 1;
pep->wa1_trb = trb; pep->wa1_trb = trb;
pep->wa1_trb_index = pep->ring.enqueue; pep->wa1_trb_index = pep->ring.enqueue;
trace_cdns2_wa1(pep, "set guard");
return 0; return 0;
} }
} }
...@@ -317,6 +325,7 @@ static int cdns2_prepare_ring(struct cdns2_device *pdev, ...@@ -317,6 +325,7 @@ static int cdns2_prepare_ring(struct cdns2_device *pdev,
if (num_trbs > ring->free_trbs) { if (num_trbs > ring->free_trbs) {
pep->ep_state |= EP_RING_FULL; pep->ep_state |= EP_RING_FULL;
trace_cdns2_no_room_on_ring("Ring full\n");
return -ENOBUFS; return -ENOBUFS;
} }
...@@ -360,6 +369,7 @@ static void cdns2_dbg_request_trbs(struct cdns2_endpoint *pep, ...@@ -360,6 +369,7 @@ static void cdns2_dbg_request_trbs(struct cdns2_endpoint *pep,
int i = 0; int i = 0;
while (i < num_trbs) { while (i < num_trbs) {
trace_cdns2_queue_trb(pep, trb + i);
if (trb + i == link_trb) { if (trb + i == link_trb) {
trb = pep->ring.trbs; trb = pep->ring.trbs;
num_trbs = num_trbs - i; num_trbs = num_trbs - i;
...@@ -678,6 +688,8 @@ static void cdns2_ep_tx_bulk(struct cdns2_endpoint *pep, ...@@ -678,6 +688,8 @@ static void cdns2_ep_tx_bulk(struct cdns2_endpoint *pep,
static void cdns2_set_drdy(struct cdns2_device *pdev, static void cdns2_set_drdy(struct cdns2_device *pdev,
struct cdns2_endpoint *pep) struct cdns2_endpoint *pep)
{ {
trace_cdns2_ring(pep);
/* /*
* Memory barrier - Cycle Bit must be set before doorbell. * Memory barrier - Cycle Bit must be set before doorbell.
*/ */
...@@ -692,6 +704,8 @@ static void cdns2_set_drdy(struct cdns2_device *pdev, ...@@ -692,6 +704,8 @@ static void cdns2_set_drdy(struct cdns2_device *pdev,
writel(DMA_EP_STS_TRBERR, &pdev->adma_regs->ep_sts); writel(DMA_EP_STS_TRBERR, &pdev->adma_regs->ep_sts);
writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd); writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd);
} }
trace_cdns2_doorbell_epx(pep, readl(&pdev->adma_regs->ep_traddr));
} }
static int cdns2_prepare_first_isoc_transfer(struct cdns2_device *pdev, static int cdns2_prepare_first_isoc_transfer(struct cdns2_device *pdev,
...@@ -927,6 +941,7 @@ static bool cdns2_trb_handled(struct cdns2_endpoint *pep, ...@@ -927,6 +941,7 @@ static bool cdns2_trb_handled(struct cdns2_endpoint *pep,
} }
finish: finish:
trace_cdns2_request_handled(preq, current_index, handled);
return handled; return handled;
} }
...@@ -942,6 +957,7 @@ static void cdns2_skip_isoc_td(struct cdns2_device *pdev, ...@@ -942,6 +957,7 @@ static void cdns2_skip_isoc_td(struct cdns2_device *pdev,
for (i = preq->finished_trb ; i < preq->num_of_trb; i++) { for (i = preq->finished_trb ; i < preq->num_of_trb; i++) {
preq->finished_trb++; preq->finished_trb++;
trace_cdns2_complete_trb(pep, trb);
cdns2_ep_inc_deq(&pep->ring); cdns2_ep_inc_deq(&pep->ring);
trb = cdns2_next_trb(pep, trb); trb = cdns2_next_trb(pep, trb);
} }
...@@ -969,6 +985,7 @@ static void cdns2_transfer_completed(struct cdns2_device *pdev, ...@@ -969,6 +985,7 @@ static void cdns2_transfer_completed(struct cdns2_device *pdev,
*/ */
while (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK && while (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK &&
le32_to_cpu(trb->length)) { le32_to_cpu(trb->length)) {
trace_cdns2_complete_trb(pep, trb);
cdns2_ep_inc_deq(&pep->ring); cdns2_ep_inc_deq(&pep->ring);
trb = pep->ring.trbs + pep->ring.dequeue; trb = pep->ring.trbs + pep->ring.dequeue;
} }
...@@ -986,6 +1003,7 @@ static void cdns2_transfer_completed(struct cdns2_device *pdev, ...@@ -986,6 +1003,7 @@ static void cdns2_transfer_completed(struct cdns2_device *pdev,
request_handled = true; request_handled = true;
trb = pep->ring.trbs + pep->ring.dequeue; trb = pep->ring.trbs + pep->ring.dequeue;
trace_cdns2_complete_trb(pep, trb);
if (pep->dir && pep->type == USB_ENDPOINT_XFER_ISOC) if (pep->dir && pep->type == USB_ENDPOINT_XFER_ISOC)
/* /*
...@@ -1037,12 +1055,17 @@ static void cdns2_rearm_transfer(struct cdns2_endpoint *pep, u8 rearm) ...@@ -1037,12 +1055,17 @@ static void cdns2_rearm_transfer(struct cdns2_endpoint *pep, u8 rearm)
cdns2_wa1_restore_cycle_bit(pep); cdns2_wa1_restore_cycle_bit(pep);
if (rearm) { if (rearm) {
trace_cdns2_ring(pep);
/* Cycle Bit must be updated before arming DMA. */ /* Cycle Bit must be updated before arming DMA. */
dma_wmb(); dma_wmb();
writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd); writel(DMA_EP_CMD_DRDY, &pdev->adma_regs->ep_cmd);
cdns2_wakeup(pdev); cdns2_wakeup(pdev);
trace_cdns2_doorbell_epx(pep,
readl(&pdev->adma_regs->ep_traddr));
} }
} }
...@@ -1055,6 +1078,8 @@ static void cdns2_handle_epx_interrupt(struct cdns2_endpoint *pep) ...@@ -1055,6 +1078,8 @@ static void cdns2_handle_epx_interrupt(struct cdns2_endpoint *pep)
cdns2_select_ep(pdev, pep->endpoint.address); cdns2_select_ep(pdev, pep->endpoint.address);
trace_cdns2_epx_irq(pdev, pep);
ep_sts_reg = readl(&pdev->adma_regs->ep_sts); ep_sts_reg = readl(&pdev->adma_regs->ep_sts);
writel(ep_sts_reg, &pdev->adma_regs->ep_sts); writel(ep_sts_reg, &pdev->adma_regs->ep_sts);
...@@ -1196,6 +1221,8 @@ static irqreturn_t cdns2_thread_usb_irq_handler(struct cdns2_device *pdev) ...@@ -1196,6 +1221,8 @@ static irqreturn_t cdns2_thread_usb_irq_handler(struct cdns2_device *pdev)
if (!ext_irq && !usb_irq) if (!ext_irq && !usb_irq)
return IRQ_NONE; return IRQ_NONE;
trace_cdns2_usb_irq(usb_irq, ext_irq);
if (ext_irq & EXTIRQ_WAKEUP) { if (ext_irq & EXTIRQ_WAKEUP) {
if (pdev->gadget_driver && pdev->gadget_driver->resume) { if (pdev->gadget_driver && pdev->gadget_driver->resume) {
spin_unlock(&pdev->lock); spin_unlock(&pdev->lock);
...@@ -1274,6 +1301,8 @@ static irqreturn_t cdns2_thread_irq_handler(int irq, void *data) ...@@ -1274,6 +1301,8 @@ static irqreturn_t cdns2_thread_irq_handler(int irq, void *data)
if (!dma_ep_ists) if (!dma_ep_ists)
goto unlock; goto unlock;
trace_cdns2_dma_ep_ists(dma_ep_ists);
/* Handle default endpoint OUT. */ /* Handle default endpoint OUT. */
if (dma_ep_ists & DMA_EP_ISTS_EP_OUT0) if (dma_ep_ists & DMA_EP_ISTS_EP_OUT0)
cdns2_handle_ep0_interrupt(pdev, USB_DIR_OUT); cdns2_handle_ep0_interrupt(pdev, USB_DIR_OUT);
...@@ -1461,6 +1490,8 @@ static int cdns2_ep_config(struct cdns2_endpoint *pep, bool enable) ...@@ -1461,6 +1490,8 @@ static int cdns2_ep_config(struct cdns2_endpoint *pep, bool enable)
if (enable) if (enable)
writel(DMA_EP_CFG_ENABLE, &pdev->adma_regs->ep_cfg); writel(DMA_EP_CFG_ENABLE, &pdev->adma_regs->ep_cfg);
trace_cdns2_epx_hw_cfg(pdev, pep);
dev_dbg(pdev->dev, "Configure %s: with MPS: %08x, ep con: %02x\n", dev_dbg(pdev->dev, "Configure %s: with MPS: %08x, ep con: %02x\n",
pep->name, max_packet_size, ep_cfg); pep->name, max_packet_size, ep_cfg);
...@@ -1479,6 +1510,8 @@ struct usb_request *cdns2_gadget_ep_alloc_request(struct usb_ep *ep, ...@@ -1479,6 +1510,8 @@ struct usb_request *cdns2_gadget_ep_alloc_request(struct usb_ep *ep,
preq->pep = pep; preq->pep = pep;
trace_cdns2_alloc_request(preq);
return &preq->request; return &preq->request;
} }
...@@ -1487,6 +1520,7 @@ void cdns2_gadget_ep_free_request(struct usb_ep *ep, ...@@ -1487,6 +1520,7 @@ void cdns2_gadget_ep_free_request(struct usb_ep *ep,
{ {
struct cdns2_request *preq = to_cdns2_request(request); struct cdns2_request *preq = to_cdns2_request(request);
trace_cdns2_free_request(preq);
kfree(preq); kfree(preq);
} }
...@@ -1552,6 +1586,8 @@ static int cdns2_gadget_ep_enable(struct usb_ep *ep, ...@@ -1552,6 +1586,8 @@ static int cdns2_gadget_ep_enable(struct usb_ep *ep,
goto exit; goto exit;
} }
trace_cdns2_gadget_ep_enable(pep);
pep->ep_state &= ~(EP_STALLED | EP_STALL_PENDING); pep->ep_state &= ~(EP_STALLED | EP_STALL_PENDING);
pep->ep_state |= EP_ENABLED; pep->ep_state |= EP_ENABLED;
pep->wa1_set = 0; pep->wa1_set = 0;
...@@ -1592,6 +1628,8 @@ static int cdns2_gadget_ep_disable(struct usb_ep *ep) ...@@ -1592,6 +1628,8 @@ static int cdns2_gadget_ep_disable(struct usb_ep *ep)
spin_lock_irqsave(&pdev->lock, flags); spin_lock_irqsave(&pdev->lock, flags);
trace_cdns2_gadget_ep_disable(pep);
cdns2_select_ep(pdev, ep->desc->bEndpointAddress); cdns2_select_ep(pdev, ep->desc->bEndpointAddress);
clear_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE); clear_reg_bit_32(&pdev->adma_regs->ep_cfg, DMA_EP_CFG_ENABLE);
...@@ -1640,10 +1678,13 @@ static int cdns2_ep_enqueue(struct cdns2_endpoint *pep, ...@@ -1640,10 +1678,13 @@ static int cdns2_ep_enqueue(struct cdns2_endpoint *pep,
request->status = -EINPROGRESS; request->status = -EINPROGRESS;
ret = usb_gadget_map_request_by_dev(pdev->dev, request, pep->dir); ret = usb_gadget_map_request_by_dev(pdev->dev, request, pep->dir);
if (ret) if (ret) {
trace_cdns2_request_enqueue_error(preq);
return ret; return ret;
}
list_add_tail(&preq->list, &pep->deferred_list); list_add_tail(&preq->list, &pep->deferred_list);
trace_cdns2_request_enqueue(preq);
if (!(pep->ep_state & EP_STALLED) && !(pep->ep_state & EP_STALL_PENDING)) if (!(pep->ep_state & EP_STALLED) && !(pep->ep_state & EP_STALL_PENDING))
cdns2_start_all_request(pdev, pep); cdns2_start_all_request(pdev, pep);
...@@ -1722,6 +1763,7 @@ int cdns2_gadget_ep_dequeue(struct usb_ep *ep, ...@@ -1722,6 +1763,7 @@ int cdns2_gadget_ep_dequeue(struct usb_ep *ep,
spin_lock_irqsave(&pep->pdev->lock, flags); spin_lock_irqsave(&pep->pdev->lock, flags);
cur_preq = to_cdns2_request(request); cur_preq = to_cdns2_request(request);
trace_cdns2_request_dequeue(cur_preq);
list_for_each_entry_safe(preq, preq_temp, &pep->pending_list, list) { list_for_each_entry_safe(preq, preq_temp, &pep->pending_list, list) {
if (cur_preq == preq) { if (cur_preq == preq) {
...@@ -1758,6 +1800,7 @@ int cdns2_gadget_ep_dequeue(struct usb_ep *ep, ...@@ -1758,6 +1800,7 @@ int cdns2_gadget_ep_dequeue(struct usb_ep *ep,
& TRB_CYCLE) | TRB_CHAIN | & TRB_CYCLE) | TRB_CHAIN |
TRB_TYPE(TRB_LINK)); TRB_TYPE(TRB_LINK));
trace_cdns2_queue_trb(pep, link_trb);
link_trb = cdns2_next_trb(pep, link_trb); link_trb = cdns2_next_trb(pep, link_trb);
} }
...@@ -1807,6 +1850,8 @@ int cdns2_halt_endpoint(struct cdns2_device *pdev, ...@@ -1807,6 +1850,8 @@ int cdns2_halt_endpoint(struct cdns2_device *pdev,
} }
} }
trace_cdns2_ep_halt(pep, 0, 0);
/* Resets Sequence Number */ /* Resets Sequence Number */
writeb(dir | pep->num, &pdev->epx_regs->endprst); writeb(dir | pep->num, &pdev->epx_regs->endprst);
writeb(dir | ENDPRST_TOGRST | pep->num, writeb(dir | ENDPRST_TOGRST | pep->num,
...@@ -1825,6 +1870,7 @@ int cdns2_halt_endpoint(struct cdns2_device *pdev, ...@@ -1825,6 +1870,7 @@ int cdns2_halt_endpoint(struct cdns2_device *pdev,
cdns2_start_all_request(pdev, pep); cdns2_start_all_request(pdev, pep);
} else { } else {
trace_cdns2_ep_halt(pep, 1, 0);
set_reg_bit_8(conf, EPX_CON_STALL); set_reg_bit_8(conf, EPX_CON_STALL);
writeb(dir | pep->num, &pdev->epx_regs->endprst); writeb(dir | pep->num, &pdev->epx_regs->endprst);
writeb(dir | ENDPRST_FIFORST | pep->num, writeb(dir | ENDPRST_FIFORST | pep->num,
...@@ -1848,6 +1894,7 @@ static int cdns2_gadget_ep_set_halt(struct usb_ep *ep, int value) ...@@ -1848,6 +1894,7 @@ static int cdns2_gadget_ep_set_halt(struct usb_ep *ep, int value)
preq = cdns2_next_preq(&pep->pending_list); preq = cdns2_next_preq(&pep->pending_list);
if (value && preq) { if (value && preq) {
trace_cdns2_ep_busy_try_halt_again(pep);
ret = -EAGAIN; ret = -EAGAIN;
goto done; goto done;
} }
...@@ -2011,6 +2058,8 @@ static int cdns2_gadget_pullup(struct usb_gadget *gadget, int is_on) ...@@ -2011,6 +2058,8 @@ static int cdns2_gadget_pullup(struct usb_gadget *gadget, int is_on)
struct cdns2_device *pdev = gadget_to_cdns2_device(gadget); struct cdns2_device *pdev = gadget_to_cdns2_device(gadget);
unsigned long flags; unsigned long flags;
trace_cdns2_pullup(is_on);
/* /*
* Disable events handling while controller is being * Disable events handling while controller is being
* enabled/disabled. * enabled/disabled.
...@@ -2336,6 +2385,7 @@ int cdns2_gadget_suspend(struct cdns2_device *pdev) ...@@ -2336,6 +2385,7 @@ int cdns2_gadget_suspend(struct cdns2_device *pdev)
spin_lock_irqsave(&pdev->lock, flags); spin_lock_irqsave(&pdev->lock, flags);
pdev->gadget.speed = USB_SPEED_UNKNOWN; pdev->gadget.speed = USB_SPEED_UNKNOWN;
trace_cdns2_device_state("notattached");
usb_gadget_set_state(&pdev->gadget, USB_STATE_NOTATTACHED); usb_gadget_set_state(&pdev->gadget, USB_STATE_NOTATTACHED);
cdns2_enable_l1(pdev, 0); cdns2_enable_l1(pdev, 0);
......
// SPDX-License-Identifier: GPL-2.0
/*
* USBHS device controller driver Trace Support
*
* Copyright (C) 2023 Cadence.
*
* Author: Pawel Laszczak <pawell@cadence.com>
*/
#define CREATE_TRACE_POINTS
#include "cdns2-trace.h"
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment