diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index a544b81dee21..8dacd85f511a 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -52,9 +52,6 @@ struct etr_perf_buffer { /* Lower limit for ETR hardware buffer */ #define TMC_ETR_PERF_MIN_BUF_SIZE SZ_1M -/* SW USB reserved memory size */ -#define TMC_ETR_SW_USB_BUF_SIZE SZ_64M - /* * The TMC ETR SG has a page size of 4K. The SG table contains pointers * to 4KB buffers. However, the OS may use a PAGE_SIZE different from diff --git a/drivers/hwtracing/coresight/coresight-tmc-usb.c b/drivers/hwtracing/coresight/coresight-tmc-usb.c index c92e23257323..fc21d43452b2 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-usb.c +++ b/drivers/hwtracing/coresight/coresight-tmc-usb.c @@ -17,6 +17,7 @@ #include "coresight-tmc.h" #define USB_BLK_SIZE 65536 +#define USB_TOTAL_IRQ (TMC_ETR_SW_USB_BUF_SIZE/USB_BLK_SIZE) #define USB_SG_NUM (USB_BLK_SIZE / PAGE_SIZE) #define USB_BUF_NUM 255 #define USB_TIME_OUT (5 * HZ) @@ -51,6 +52,8 @@ static int usb_bypass_start(struct byte_cntr *byte_cntr_data) return offset; } byte_cntr_data->offset = offset; + tmcdrvdata->usb_data->drop_data_size = 0; + tmcdrvdata->usb_data->data_overwritten = false; /*Ensure usbch is ready*/ if (!tmcdrvdata->usb_data->usbch) { @@ -104,8 +107,11 @@ static void usb_bypass_stop(struct byte_cntr *byte_cntr_data) pr_info("coresight: stop usb bypass\n"); coresight_csr_set_byte_cntr(byte_cntr_data->csr, byte_cntr_data->irqctrl_offset, 0); dev_dbg(&byte_cntr_data->tmcdrvdata->csdev->dev, - "write to usb data total size: %lld bytes, irq_cnt: %lld, offset: %ld\n", - byte_cntr_data->total_size, byte_cntr_data->total_irq, byte_cntr_data->offset); + "write to usb data total size: %lld bytes, total irq_cnt: %lld, current irq cnt: %d, offset: %ld, drop_data: %lld\n", + byte_cntr_data->total_size, byte_cntr_data->total_irq, + atomic_read(&byte_cntr_data->irq_cnt), + byte_cntr_data->offset, + byte_cntr_data->tmcdrvdata->usb_data->drop_data_size); byte_cntr_data->total_irq = 0; mutex_unlock(&byte_cntr_data->usb_bypass_lock); @@ -129,6 +135,11 @@ static int usb_transfer_small_packet(struct byte_cntr *drvdata, size_t *small_si goto out; } + if (unlikely(atomic_read(&drvdata->irq_cnt) > USB_TOTAL_IRQ)) { + tmcdrvdata->usb_data->data_overwritten = true; + dev_err_ratelimited(&tmcdrvdata->csdev->dev, "ETR data is overwritten.\n"); + } + req_size = ((w_offset < drvdata->offset) ? etr_buf->size : 0) + w_offset - drvdata->offset; req_size = ((req_size + *small_size) < USB_BLK_SIZE) ? req_size : @@ -180,9 +191,10 @@ static int usb_transfer_small_packet(struct byte_cntr *drvdata, size_t *small_si drvdata->total_size += actual; atomic_dec(&drvdata->usb_free_buf); } else { - dev_dbg(&tmcdrvdata->csdev->dev, + dev_err_ratelimited(&tmcdrvdata->csdev->dev, "Drop data, offset = %d, len = %d\n", drvdata->offset, req_size); + tmcdrvdata->usb_data->drop_data_size += actual; kfree(usb_req); drvdata->usb_req = NULL; } @@ -227,6 +239,11 @@ static void usb_read_work_fn(struct work_struct *work) } } + if (unlikely(atomic_read(&drvdata->irq_cnt) > USB_TOTAL_IRQ)) { + tmcdrvdata->usb_data->data_overwritten = true; + dev_err_ratelimited(&tmcdrvdata->csdev->dev, "ETR data is overwritten.\n"); + } + req_size = USB_BLK_SIZE - small_size; small_size = 0; actual_total = 0; @@ -298,10 +315,11 @@ static void usb_read_work_fn(struct work_struct *work) atomic_dec(&drvdata->usb_free_buf); } else { - dev_dbg(&tmcdrvdata->csdev->dev, + dev_err_ratelimited(&tmcdrvdata->csdev->dev, "Drop data, offset = %d, seq = %d, irq = %d\n", drvdata->offset, seq, atomic_read(&drvdata->irq_cnt)); + tmcdrvdata->usb_data->drop_data_size += actual_total; kfree(usb_req->sg); kfree(usb_req); drvdata->usb_req = NULL; @@ -425,8 +443,10 @@ void tmc_usb_disable(struct tmc_usb_data *usb_data) { struct tmc_drvdata *tmcdrvdata = usb_data->tmcdrvdata; - if (usb_data->usb_mode == TMC_ETR_USB_SW) + if (usb_data->usb_mode == TMC_ETR_USB_SW) { usb_bypass_stop(tmcdrvdata->byte_cntr); + flush_work(&tmcdrvdata->byte_cntr->read_work); + } if (usb_data->usbch) usb_qdss_close(usb_data->usbch); @@ -452,7 +472,8 @@ int tmc_etr_usb_init(struct amba_device *adev, if (tmc_etr_support_usb_bypass(dev)) { usb_data->usb_mode = TMC_ETR_USB_SW; - + usb_data->drop_data_size = 0; + usb_data->data_overwritten = false; if (!byte_cntr_data) return -EINVAL; diff --git a/drivers/hwtracing/coresight/coresight-tmc-usb.h b/drivers/hwtracing/coresight/coresight-tmc-usb.h index ac5f87525879..8a509afef64b 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-usb.h +++ b/drivers/hwtracing/coresight/coresight-tmc-usb.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CORESIGHT_TMC_USB_H @@ -18,9 +18,11 @@ enum tmc_etr_usb_mode { }; struct tmc_usb_data { - struct usb_qdss_ch *usbch; enum tmc_etr_usb_mode usb_mode; + struct usb_qdss_ch *usbch; struct tmc_drvdata *tmcdrvdata; + bool data_overwritten; + u64 drop_data_size; }; extern int tmc_usb_enable(struct tmc_usb_data *usb_data); diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 5fb9c7e72707..a30956c8296f 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -134,6 +134,9 @@ enum tmc_mem_intf_width { #define CORESIGHT_SOC_600_ETR_CAPS \ (TMC_ETR_SAVE_RESTORE | TMC_ETR_AXI_ARCACHE) +/* SW USB reserved memory size */ +#define TMC_ETR_SW_USB_BUF_SIZE SZ_64M + enum etr_mode { ETR_MODE_FLAT, /* Uses contiguous flat buffer */ ETR_MODE_ETR_SG, /* Uses in-built TMC ETR SG mechanism */