From nobody Fri Dec 26 15:31:21 2025 Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC8DF210F2; Fri, 5 Jan 2024 05:59:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="L9dVk3o6" Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 4052r2PF027805; Thu, 4 Jan 2024 21:59:23 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=3GDzSjBgHcB+jHB78Mm0ENTzeM2tk1jL6FHqPzBwYi8=; b=L9d Vk3o6g/8qMNgIchi39/avwDFybfwYa78FeXEpnReX7Tfdgi+xd0lyP6Pr/xWhvEu 8roxzDX/UVQZmWnkWMo9TqdEXgjmAX/waqK8fqpir9GCFIm8qfFQMo/SOn2kNRzh BMriTHgS+NahaHMBARLMX8ZEyrpI3N6flrD2eybPHArE9djjxjke5UaHawHpyVNe lMMStLBMoiCuKIT51fjO/ek+gNwWPAhVItJROy7a+trQi9M2RvTxOYZZfRnI3M/7 za0ZEXVVUf2Mrg3vhEgOUaYTmwFVGs4Kj3Xz613Xng1runiVwOORUYim4bDJh1Al eOEUwlWxlwi2oFmz/KA== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ve9c7gdr8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 04 Jan 2024 21:59:23 -0800 (PST) Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Thu, 4 Jan 2024 21:59:21 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Thu, 4 Jan 2024 21:59:21 -0800 Received: from virtx40.. (unknown [10.28.34.196]) by maili.marvell.com (Postfix) with ESMTP id CFDB53F70A1; Thu, 4 Jan 2024 21:59:16 -0800 (PST) From: Linu Cherian To: , , , CC: , , , , , , , , , Linu Cherian , Anil Kumar Reddy , Tanmay Jagdale Subject: [PATCH v6 5/7] coresight: tmc: Add support for reading tracedata from previous boot Date: Fri, 5 Jan 2024 11:28:38 +0530 Message-ID: <20240105055840.1977897-6-lcherian@marvell.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240105055840.1977897-1-lcherian@marvell.com> References: <20240105055840.1977897-1-lcherian@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: IpRMjee5chU8NjOcD4qSJ0xhw4ynwHo3 X-Proofpoint-ORIG-GUID: IpRMjee5chU8NjOcD4qSJ0xhw4ynwHo3 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-09_02,2023-12-07_01,2023-05-22_02 Content-Type: text/plain; charset="utf-8" * Introduce a new mode CS_MODE_READ_PREVBOOT for reading tracedata captured in previous boot. * Add special handlers for preparing ETR/ETF for this special mode * User can read the trace data as below For example, for reading trace data from tmc_etf sink 1. cd /sys/bus/coresight/devices/tmc_etfXX/ 2. Change mode to READ_PREVBOOT #echo 1 > read_prevboot 3. Dump trace buffer data to a file, #dd if=3D/dev/tmc_etfXX of=3D~/cstrace.bin 4. Reset back to normal mode #echo 0 > read_prevboot Signed-off-by: Anil Kumar Reddy Signed-off-by: Tanmay Jagdale Signed-off-by: Linu Cherian --- Changelog from v5: * Fixed issues reported by CONFIG_DEBUG_ATOMIC_SLEEP in tmc_etr_setup_prevb= oot_buf and tmc_etb_setup_prevboot_buf - Kmalloc invoked with spinlock taken is now done with GFP_ATOMIC - Removed the requirement for memremap with spinlock taken. This is by making a assumption that the trace buffer address used for capturing trace data during kernel crash/hang would be same as that used for trace data retrieval in the subsequent boot. Added additional verification to ensure this. * Fixed a memory leak in tmc_read_unprepare_etr in READ_PREVBOOT mode .../coresight/coresight-etm4x-core.c | 1 + .../hwtracing/coresight/coresight-tmc-core.c | 96 ++++++++++- .../hwtracing/coresight/coresight-tmc-etf.c | 73 +++++++++ .../hwtracing/coresight/coresight-tmc-etr.c | 154 +++++++++++++++++- drivers/hwtracing/coresight/coresight-tmc.h | 6 + include/linux/coresight.h | 13 ++ 6 files changed, 341 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/h= wtracing/coresight/coresight-etm4x-core.c index 34aee59dd147..c26b5f72a494 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -1010,6 +1010,7 @@ static void etm4_disable(struct coresight_device *csd= ev, =20 switch (mode) { case CS_MODE_DISABLED: + case CS_MODE_READ_PREVBOOT: break; case CS_MODE_SYSFS: etm4_disable_sysfs(csdev); diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwt= racing/coresight/coresight-tmc-core.c index 4d7530d6ac91..e6525c3dcf66 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -103,6 +103,60 @@ u32 tmc_get_memwidth_mask(struct tmc_drvdata *drvdata) return mask; } =20 +int tmc_read_prepare_prevboot(struct tmc_drvdata *drvdata) +{ + int ret =3D 0; + struct tmc_crash_metadata *mdata; + struct coresight_device *csdev =3D drvdata->csdev; + + if (!drvdata->crash_mdata.vaddr) { + ret =3D -ENOMEM; + goto out; + } + + mdata =3D drvdata->crash_mdata.vaddr; + /* Check data integrity of metadata */ + if (mdata->crc32_mdata !=3D find_crash_metadata_crc(mdata)) { + dev_dbg(&drvdata->csdev->dev, + "CRC mismatch in tmc crash metadata\n"); + ret =3D -EINVAL; + goto out; + } + /* Check data integrity of tracedata */ + if (mdata->crc32_tdata !=3D find_crash_tracedata_crc(drvdata, mdata)) { + dev_dbg(&drvdata->csdev->dev, + "CRC mismatch in tmc crash tracedata\n"); + ret =3D -EINVAL; + goto out; + } + /* Check for valid metadata */ + if (!mdata->valid) { + dev_dbg(&drvdata->csdev->dev, + "Data invalid in tmc crash metadata\n"); + ret =3D -EINVAL; + goto out; + } + + /* Sink specific prevboot mode preparation */ + ret =3D prevboot_ops(csdev)->prepare(csdev); + if (ret) + goto out; + + if (mdata->sts & 0x1) + coresight_insert_barrier_packet(drvdata->buf); + +out: + return ret; +} + +int tmc_read_unprepare_prevboot(struct tmc_drvdata *drvdata) +{ + struct coresight_device *csdev =3D drvdata->csdev; + + /* Sink specific prevboot mode preparation */ + return prevboot_ops(csdev)->unprepare(csdev); +} + static int tmc_read_prepare(struct tmc_drvdata *drvdata) { int ret =3D 0; @@ -153,6 +207,10 @@ static int tmc_open(struct inode *inode, struct file *= file) struct tmc_drvdata *drvdata =3D container_of(file->private_data, struct tmc_drvdata, miscdev); =20 + /* Advertise if we are opening with a special mode */ + if (drvdata->mode =3D=3D CS_MODE_READ_PREVBOOT) + dev_dbg(&drvdata->csdev->dev, "TMC read mode for previous boot\n"); + ret =3D tmc_read_prepare(drvdata); if (ret) return ret; @@ -331,9 +389,44 @@ static ssize_t buffer_size_store(struct device *dev, =20 static DEVICE_ATTR_RW(buffer_size); =20 +static ssize_t read_prevboot_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tmc_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + + return sprintf(buf, "%#x\n", (drvdata->mode =3D=3D CS_MODE_READ_PREVBOOT)= ); +} + +static ssize_t read_prevboot_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + unsigned long val, flags; + struct tmc_drvdata *drvdata =3D dev_get_drvdata(dev->parent); + + ret =3D kstrtoul(buf, 0, &val); + if (ret) + return ret; + + spin_lock_irqsave(&drvdata->spinlock, flags); + + if (val && (drvdata->mode =3D=3D CS_MODE_DISABLED)) + drvdata->mode =3D CS_MODE_READ_PREVBOOT; + else if (!val && (drvdata->mode =3D=3D CS_MODE_READ_PREVBOOT)) + drvdata->mode =3D CS_MODE_DISABLED; + + spin_unlock_irqrestore(&drvdata->spinlock, flags); + + return size; +} + +static DEVICE_ATTR_RW(read_prevboot); + static struct attribute *coresight_tmc_attrs[] =3D { &dev_attr_trigger_cntr.attr, &dev_attr_buffer_size.attr, + &dev_attr_read_prevboot.attr, NULL, }; =20 @@ -635,7 +728,8 @@ static void tmc_shutdown(struct amba_device *adev) =20 spin_lock_irqsave(&drvdata->spinlock, flags); =20 - if (drvdata->mode =3D=3D CS_MODE_DISABLED) + if (drvdata->mode =3D=3D CS_MODE_DISABLED || + drvdata->mode =3D=3D CS_MODE_READ_PREVBOOT) goto out; =20 if (drvdata->config_type =3D=3D TMC_CONFIG_TYPE_ETR) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtr= acing/coresight/coresight-tmc-etf.c index b53cef7628ff..72c2315f4e23 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -648,6 +648,56 @@ static int tmc_panic_sync_etf(struct coresight_device = *csdev) return 0; } =20 +static int tmc_etb_setup_prevboot_buf(struct tmc_drvdata *drvdata) +{ + unsigned long size; + struct tmc_crash_metadata *mdata; + struct device *dev =3D &drvdata->csdev->dev; + + mdata =3D drvdata->crash_mdata.vaddr; + size =3D mdata->size << 2; + + /* + * Buffer address given by metadata for retrieval of trace data + * from previous boot is expected to be same as the reserved + * trace buffer memory region provided through DTS + */ + if (is_tmc_reserved_region_valid(dev->parent) + && (drvdata->crash_tbuf.paddr =3D=3D mdata->trc_paddr)) + drvdata->buf =3D drvdata->crash_tbuf.vaddr; + else { + dev_dbg(dev, "Trace buffer address of previous boot invalid\n"); + return -EINVAL; + } + + drvdata->len =3D size; + return 0; +} + +static void tmc_etb_free_prevboot_buf(struct tmc_drvdata *drvdata) +{ + void *buf =3D drvdata->buf; + + if (!buf) + return; + drvdata->buf =3D NULL; +} + +static int tmc_etb_prepare_prevboot(struct coresight_device *csdev) +{ + struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); + + return tmc_etb_setup_prevboot_buf(drvdata); +} + +static int tmc_etb_unprepare_prevboot(struct coresight_device *csdev) +{ + struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); + + tmc_etb_free_prevboot_buf(drvdata); + return 0; +} + static const struct coresight_ops_sink tmc_etf_sink_ops =3D { .enable =3D tmc_enable_etf_sink, .disable =3D tmc_disable_etf_sink, @@ -665,6 +715,11 @@ static const struct coresight_ops_panic tmc_etf_sync_o= ps =3D { .sync =3D tmc_panic_sync_etf, }; =20 +static const struct coresight_ops_prevboot tmc_etf_prevboot_ops =3D { + .prepare =3D tmc_etb_prepare_prevboot, + .unprepare =3D tmc_etb_unprepare_prevboot, +}; + const struct coresight_ops tmc_etb_cs_ops =3D { .sink_ops =3D &tmc_etf_sink_ops, }; @@ -673,6 +728,7 @@ const struct coresight_ops tmc_etf_cs_ops =3D { .sink_ops =3D &tmc_etf_sink_ops, .link_ops =3D &tmc_etf_link_ops, .panic_ops =3D &tmc_etf_sync_ops, + .prevboot_ops =3D &tmc_etf_prevboot_ops, }; =20 int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) @@ -693,6 +749,14 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) goto out; } =20 + if (drvdata->mode =3D=3D CS_MODE_READ_PREVBOOT) { + ret =3D tmc_read_prepare_prevboot(drvdata); + if (ret) + goto out; + else + goto mode_valid; + } + /* Don't interfere if operated from Perf */ if (drvdata->mode =3D=3D CS_MODE_PERF) { ret =3D -EINVAL; @@ -716,6 +780,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) __tmc_etb_disable_hw(drvdata); } =20 +mode_valid: drvdata->reading =3D true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); @@ -735,8 +800,16 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) drvdata->config_type !=3D TMC_CONFIG_TYPE_ETF)) return -EINVAL; =20 + spin_lock_irqsave(&drvdata->spinlock, flags); =20 + if (drvdata->mode =3D=3D CS_MODE_READ_PREVBOOT) { + tmc_read_unprepare_prevboot(drvdata); + drvdata->reading =3D false; + spin_unlock_irqrestore(&drvdata->spinlock, flags); + return 0; + } + /* Re-enable the TMC if need be */ if (drvdata->mode =3D=3D CS_MODE_SYSFS) { /* There is no point in reading a TMC in HW FIFO mode */ diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtr= acing/coresight/coresight-tmc-etr.c index 23eb35f50571..ab7521bbb2f5 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1166,7 +1166,12 @@ ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *= drvdata, { s64 offset; ssize_t actual =3D len; - struct etr_buf *etr_buf =3D drvdata->sysfs_buf; + struct etr_buf *etr_buf; + + if (drvdata->mode =3D=3D CS_MODE_READ_PREVBOOT) + etr_buf =3D drvdata->prevboot_buf; + else + etr_buf =3D drvdata->sysfs_buf; =20 if (pos + actual > etr_buf->len) actual =3D etr_buf->len - pos; @@ -1873,6 +1878,130 @@ static int tmc_panic_sync_etr(struct coresight_devi= ce *csdev) return 0; } =20 +static int tmc_etr_setup_prevboot_buf(struct tmc_drvdata *drvdata) +{ + int rc =3D 0; + u64 trace_addr; + struct etr_buf *etr_buf; + struct etr_flat_buf *resrv_buf; + struct tmc_crash_metadata *mdata; + struct device *dev =3D &drvdata->csdev->dev; + + mdata =3D drvdata->crash_mdata.vaddr; + + etr_buf =3D kzalloc(sizeof(*etr_buf), GFP_ATOMIC); + if (!etr_buf) { + rc =3D -ENOMEM; + goto out; + } + etr_buf->size =3D drvdata->crash_tbuf.size; + + resrv_buf =3D kzalloc(sizeof(*resrv_buf), GFP_ATOMIC); + if (!resrv_buf) { + rc =3D -ENOMEM; + goto rmem_err; + } + + /* + * Buffer address given by metadata for retrieval of trace data + * from previous boot is expected to be same as the reserved + * trace buffer memory region provided through DTS + */ + if (is_tmc_reserved_region_valid(dev->parent) + && (drvdata->crash_tbuf.paddr =3D=3D mdata->trc_paddr)) + resrv_buf->vaddr =3D drvdata->crash_tbuf.vaddr; + else { + dev_dbg(dev, "Trace buffer address of previous boot invalid\n"); + rc =3D -EINVAL; + goto map_err; + } + + resrv_buf->size =3D etr_buf->size; + resrv_buf->dev =3D &drvdata->csdev->dev; + etr_buf->hwaddr =3D trace_addr; + etr_buf->mode =3D ETR_MODE_RESRV; + etr_buf->private =3D resrv_buf; + etr_buf->ops =3D etr_buf_ops[ETR_MODE_RESRV]; + + drvdata->prevboot_buf =3D etr_buf; + + return 0; + +map_err: + kfree(resrv_buf); + +rmem_err: + kfree(etr_buf); + +out: + return rc; +} + +static int tmc_etr_sync_prevboot_buf(struct tmc_drvdata *drvdata) +{ + u32 status; + u64 rrp, rwp, dba; + struct tmc_crash_metadata *mdata; + struct etr_buf *etr_buf =3D drvdata->prevboot_buf; + + mdata =3D drvdata->crash_mdata.vaddr; + + rrp =3D mdata->rrp; + rwp =3D mdata->rwp; + dba =3D mdata->dba; + status =3D mdata->sts; + + etr_buf->full =3D !!(status & TMC_STS_FULL); + + /* Sync the buffer pointers */ + etr_buf->offset =3D rrp - dba; + if (etr_buf->full) + etr_buf->len =3D etr_buf->size; + else + etr_buf->len =3D rwp - rrp; + + /* Additional sanity checks for validating metadata */ + if ((etr_buf->offset > etr_buf->size) || + (etr_buf->len > etr_buf->size)) { + dev_dbg(&drvdata->csdev->dev, + "Offset and length invalid in tmc crash metadata\n"); + return -EINVAL; + } + + return 0; +} + +static void tmc_etr_free_prevboot_buf(struct tmc_drvdata *drvdata) +{ + struct etr_buf *etr_buf =3D drvdata->prevboot_buf; + + if (!etr_buf) + return; + drvdata->prevboot_buf =3D NULL; +} + +static int tmc_etr_prepare_prevboot(struct coresight_device *csdev) +{ + int ret =3D 0; + struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); + + ret =3D tmc_etr_setup_prevboot_buf(drvdata); + if (ret) + goto out; + ret =3D tmc_etr_sync_prevboot_buf(drvdata); + +out: + return ret; +} + +static int tmc_etr_unprepare_prevboot(struct coresight_device *csdev) +{ + struct tmc_drvdata *drvdata =3D dev_get_drvdata(csdev->dev.parent); + + tmc_etr_free_prevboot_buf(drvdata); + return 0; +} + static const struct coresight_ops_sink tmc_etr_sink_ops =3D { .enable =3D tmc_enable_etr_sink, .disable =3D tmc_disable_etr_sink, @@ -1885,9 +2014,15 @@ static const struct coresight_ops_panic tmc_etr_sync= _ops =3D { .sync =3D tmc_panic_sync_etr, }; =20 +static const struct coresight_ops_prevboot tmc_etr_prevboot_ops =3D { + .prepare =3D tmc_etr_prepare_prevboot, + .unprepare =3D tmc_etr_unprepare_prevboot, +}; + const struct coresight_ops tmc_etr_cs_ops =3D { .sink_ops =3D &tmc_etr_sink_ops, .panic_ops =3D &tmc_etr_sync_ops, + .prevboot_ops =3D &tmc_etr_prevboot_ops, }; =20 int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) @@ -1899,12 +2034,21 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdat= a) if (WARN_ON_ONCE(drvdata->config_type !=3D TMC_CONFIG_TYPE_ETR)) return -EINVAL; =20 + spin_lock_irqsave(&drvdata->spinlock, flags); if (drvdata->reading) { ret =3D -EBUSY; goto out; } =20 + if (drvdata->mode =3D=3D CS_MODE_READ_PREVBOOT) { + ret =3D tmc_read_prepare_prevboot(drvdata); + if (ret) + goto out; + else + goto mode_valid; + } + /* * We can safely allow reads even if the ETR is operating in PERF mode, * since the sysfs session is captured in mode specific data. @@ -1919,6 +2063,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) if (drvdata->mode =3D=3D CS_MODE_SYSFS) __tmc_etr_disable_hw(drvdata); =20 +mode_valid: drvdata->reading =3D true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); @@ -1937,6 +2082,12 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvda= ta) =20 spin_lock_irqsave(&drvdata->spinlock, flags); =20 + if (drvdata->mode =3D=3D CS_MODE_READ_PREVBOOT) { + sysfs_buf =3D drvdata->prevboot_buf; + tmc_read_unprepare_prevboot(drvdata); + goto out; + } + /* RE-enable the TMC if need be */ if (drvdata->mode =3D=3D CS_MODE_SYSFS) { /* @@ -1954,6 +2105,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdat= a) drvdata->sysfs_buf =3D NULL; } =20 +out: drvdata->reading =3D false; spin_unlock_irqrestore(&drvdata->spinlock, flags); =20 diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracin= g/coresight/coresight-tmc.h index 6f13caae6495..6e1e910d5ea4 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -216,6 +216,9 @@ struct tmc_resrv_buf { * @idr_mutex: Access serialisation for idr. * @sysfs_buf: SYSFS buffer for ETR. * @perf_buf: PERF buffer for ETR. + * @prevboot_buf: Previous boot buffer for ETR. This is a special purpose + * buffer that is used only for mapping the trace buffer from + * previous boot and not for capturing trace. * @crash_tbuf: Used by ETR as hardware trace buffer and for trace data * retention (after crash) only when ETR_MODE_RESRV buffer * mode is enabled. Used by ETF for trace data retention @@ -247,6 +250,7 @@ struct tmc_drvdata { struct mutex idr_mutex; struct etr_buf *sysfs_buf; struct etr_buf *perf_buf; + struct etr_buf *prevboot_buf; struct tmc_resrv_buf crash_tbuf; struct tmc_resrv_buf crash_mdata; }; @@ -298,6 +302,8 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata); void tmc_enable_hw(struct tmc_drvdata *drvdata); void tmc_disable_hw(struct tmc_drvdata *drvdata); u32 tmc_get_memwidth_mask(struct tmc_drvdata *drvdata); +int tmc_read_prepare_prevboot(struct tmc_drvdata *drvdata); +int tmc_read_unprepare_prevboot(struct tmc_drvdata *drvdata); =20 /* ETB/ETF functions */ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 4fd518738958..9f84decf1d7a 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -294,6 +294,7 @@ enum cs_mode { CS_MODE_DISABLED, CS_MODE_SYSFS, CS_MODE_PERF, + CS_MODE_READ_PREVBOOT, /* Trace data from previous boot */ }; =20 #define source_ops(csdev) csdev->ops->source_ops @@ -302,6 +303,7 @@ enum cs_mode { #define helper_ops(csdev) csdev->ops->helper_ops #define ect_ops(csdev) csdev->ops->ect_ops #define panic_ops(csdev) csdev->ops->panic_ops +#define prevboot_ops(csdev) csdev->ops->prevboot_ops =20 /** * struct coresight_ops_sink - basic operations for a sink @@ -381,12 +383,23 @@ struct coresight_ops_panic { int (*sync)(struct coresight_device *csdev); }; =20 +/** + * struct coresight_ops_prevboot - Generic device ops for prevboot mode + * + * @prepare : Preparation for prevboot mode + */ +struct coresight_ops_prevboot { + int (*prepare)(struct coresight_device *csdev); + int (*unprepare)(struct coresight_device *csdev); +}; + struct coresight_ops { const struct coresight_ops_sink *sink_ops; const struct coresight_ops_link *link_ops; const struct coresight_ops_source *source_ops; const struct coresight_ops_helper *helper_ops; const struct coresight_ops_panic *panic_ops; + const struct coresight_ops_prevboot *prevboot_ops; }; =20 #if IS_ENABLED(CONFIG_CORESIGHT) --=20 2.34.1