diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 696b48a9b26e..16ad22fec060 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1443,44 +1443,8 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct etr_buf *sysfs_buf = NULL, *new_buf = NULL, *free_buf = NULL; - /* - * If we are enabling the ETR from disabled state, we need to make - * sure we have a buffer with the right size. The etr_buf is not reset - * immediately after we stop the tracing in SYSFS mode as we wait for - * the user to collect the data. We may be able to reuse the existing - * buffer, provided the size matches. Any allocation has to be done - * with the lock released. - */ spin_lock_irqsave(&drvdata->spinlock, flags); - sysfs_buf = READ_ONCE(drvdata->sysfs_buf); - if (!sysfs_buf || (sysfs_buf->size != drvdata->size) - || !drvdata->usbch) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - - if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM || - (drvdata->byte_cntr->sw_usb && - drvdata->out_mode == TMC_ETR_OUT_MODE_USB)) { - /* - * ETR DDR memory is not allocated until user enables - * tmc at least once. If user specifies different ETR - * DDR size than the default size or switches between - * contiguous or scatter-gather memory type after - * enabling tmc; the new selection will be honored from - * next tmc enable session. - */ - /* Allocate memory with the locks released */ - free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata); - if (IS_ERR(new_buf)) - return -ENOMEM; - coresight_cti_map_trigout(drvdata->cti_flush, - drvdata->cti_flush_trig_num, 0); - coresight_cti_map_trigin(drvdata->cti_reset, - drvdata->cti_reset_trig_num, 0); - } - spin_lock_irqsave(&drvdata->spinlock, flags); - } - - if (drvdata->reading || drvdata->mode == CS_MODE_PERF) { + if (drvdata->reading) { ret = -EBUSY; goto unlock_out; } @@ -1495,18 +1459,48 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) goto unlock_out; } - /* - * If we don't have a buffer or it doesn't match the requested size, - * use the buffer allocated above. Otherwise reuse the existing buffer. - */ - sysfs_buf = READ_ONCE(drvdata->sysfs_buf); - if (!sysfs_buf || (new_buf && sysfs_buf->size != new_buf->size)) { - free_buf = sysfs_buf; - drvdata->sysfs_buf = new_buf; - } - if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM || - (drvdata->out_mode == TMC_ETR_OUT_MODE_USB - && drvdata->byte_cntr->sw_usb)) { + if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM + || (drvdata->out_mode == TMC_ETR_OUT_MODE_USB + && drvdata->byte_cntr->sw_usb)) { + /* + * If we are enabling the ETR from disabled state, we need to make + * sure we have a buffer with the right size. The etr_buf is not reset + * immediately after we stop the tracing in SYSFS mode as we wait for + * the user to collect the data. We may be able to reuse the existing + * buffer, provided the size matches. Any allocation has to be done + * with the lock released. + */ + sysfs_buf = READ_ONCE(drvdata->sysfs_buf); + if (!sysfs_buf || (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM + && sysfs_buf->size != drvdata->size) + || (drvdata->out_mode == TMC_ETR_OUT_MODE_USB + && drvdata->byte_cntr->sw_usb + && sysfs_buf->size != TMC_ETR_SW_USB_BUF_SIZE)) { + + spin_unlock_irqrestore(&drvdata->spinlock, flags); + /* + * ETR DDR memory is not allocated until user enables + * tmc at least once. If user specifies different ETR + * DDR size than the default size or switches between + * contiguous or scatter-gather memory type after + * enabling tmc; the new selection will be honored from + * next tmc enable session. + */ + /* Allocate memory with the locks released */ + new_buf = tmc_etr_setup_sysfs_buf(drvdata); + if (IS_ERR(new_buf)) + return -ENOMEM; + spin_lock_irqsave(&drvdata->spinlock, flags); + } + + /* + * If we don't have a buffer or it doesn't match the requested size, + * use the buffer allocated above. Otherwise reuse the existing buffer. + */ + if (new_buf) { + free_buf = sysfs_buf; + drvdata->sysfs_buf = new_buf; + } ret = tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf); if (ret) goto unlock_out; @@ -1537,6 +1531,20 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) } atomic_inc(csdev->refcnt); + + if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) + tmc_etr_byte_cntr_start(drvdata->byte_cntr); + + if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM || + (drvdata->byte_cntr->sw_usb && + drvdata->out_mode == TMC_ETR_OUT_MODE_USB)) { + coresight_cti_map_trigout(drvdata->cti_flush, + drvdata->cti_flush_trig_num, 0); + coresight_cti_map_trigin(drvdata->cti_reset, + drvdata->cti_reset_trig_num, 0); + } + + dev_info(&csdev->dev, "TMC-ETR enabled\n"); goto out; unlock_out: @@ -1547,13 +1555,6 @@ out: if (free_buf) tmc_etr_free_sysfs_buf(free_buf); - if (!ret) { - if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) - tmc_etr_byte_cntr_start(drvdata->byte_cntr); - - dev_info(&csdev->dev, "TMC-ETR enabled\n"); - } - return ret; }