aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing
diff options
context:
space:
mode:
authorSuzuki K Poulose <suzuki.poulose@arm.com>2018-09-20 15:17:51 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-25 14:09:17 -0400
commit96a7f644006ecc05eaaa1a5d09373d0ee63beb0a (patch)
treecea1f6f6136054f0added592fefd9bde95fb24c8 /drivers/hwtracing
parent4f8ef21007531c3d7cb5b826e7b2c8999b65ecae (diff)
coresight: tmc-etr: Handle driver mode specific ETR buffers
Since the ETR could be driven either by SYSFS or by perf, it becomes complicated how we deal with the buffers used for each of these modes. The ETR driver cannot simply free the current attached buffer without knowing the provider (i.e, sysfs vs perf). To solve this issue, we provide: 1) the driver-mode specific etr buffer to be retained in the drvdata 2) the etr_buf for a session should be passed on when enabling the hardware, which will be stored in drvdata->etr_buf. This will be replaced (not free'd) as soon as the hardware is disabled, after necessary sync operation. The advantages of this are : 1) The common code path doesn't need to worry about how to dispose an existing buffer, if it is about to start a new session with a different buffer, possibly in a different mode. 2) The driver mode can control its buffers and can get access to the saved session even when the hardware is operating in a different mode. (e.g, we can still access a trace buffer from a sysfs mode even if the etr is now used in perf mode, without disrupting the current session.) Towards this, we introduce a sysfs specific data which will hold the etr_buf used for sysfs mode of operation, controlled solely by the sysfs mode handling code. Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etr.c58
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc.h2
2 files changed, 40 insertions, 20 deletions
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 11963647e19a..2d6f428176ff 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -895,10 +895,15 @@ static void tmc_sync_etr_buf(struct tmc_drvdata *drvdata)
895 tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset); 895 tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset);
896} 896}
897 897
898static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) 898static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
899 struct etr_buf *etr_buf)
899{ 900{
900 u32 axictl, sts; 901 u32 axictl, sts;
901 struct etr_buf *etr_buf = drvdata->etr_buf; 902
903 /* Callers should provide an appropriate buffer for use */
904 if (WARN_ON(!etr_buf || drvdata->etr_buf))
905 return;
906 drvdata->etr_buf = etr_buf;
902 907
903 /* 908 /*
904 * If this ETR is connected to a CATU, enable it before we turn 909 * If this ETR is connected to a CATU, enable it before we turn
@@ -960,13 +965,16 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
960 * also updating the @bufpp on where to find it. Since the trace data 965 * also updating the @bufpp on where to find it. Since the trace data
961 * starts at anywhere in the buffer, depending on the RRP, we adjust the 966 * starts at anywhere in the buffer, depending on the RRP, we adjust the
962 * @len returned to handle buffer wrapping around. 967 * @len returned to handle buffer wrapping around.
968 *
969 * We are protected here by drvdata->reading != 0, which ensures the
970 * sysfs_buf stays alive.
963 */ 971 */
964ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, 972ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
965 loff_t pos, size_t len, char **bufpp) 973 loff_t pos, size_t len, char **bufpp)
966{ 974{
967 s64 offset; 975 s64 offset;
968 ssize_t actual = len; 976 ssize_t actual = len;
969 struct etr_buf *etr_buf = drvdata->etr_buf; 977 struct etr_buf *etr_buf = drvdata->sysfs_buf;
970 978
971 if (pos + actual > etr_buf->len) 979 if (pos + actual > etr_buf->len)
972 actual = etr_buf->len - pos; 980 actual = etr_buf->len - pos;
@@ -996,7 +1004,14 @@ tmc_etr_free_sysfs_buf(struct etr_buf *buf)
996 1004
997static void tmc_etr_sync_sysfs_buf(struct tmc_drvdata *drvdata) 1005static void tmc_etr_sync_sysfs_buf(struct tmc_drvdata *drvdata)
998{ 1006{
999 tmc_sync_etr_buf(drvdata); 1007 struct etr_buf *etr_buf = drvdata->etr_buf;
1008
1009 if (WARN_ON(drvdata->sysfs_buf != etr_buf)) {
1010 tmc_etr_free_sysfs_buf(drvdata->sysfs_buf);
1011 drvdata->sysfs_buf = NULL;
1012 } else {
1013 tmc_sync_etr_buf(drvdata);
1014 }
1000} 1015}
1001 1016
1002static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) 1017static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
@@ -1017,6 +1032,8 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
1017 1032
1018 /* Disable CATU device if this ETR is connected to one */ 1033 /* Disable CATU device if this ETR is connected to one */
1019 tmc_etr_disable_catu(drvdata); 1034 tmc_etr_disable_catu(drvdata);
1035 /* Reset the ETR buf used by hardware */
1036 drvdata->etr_buf = NULL;
1020} 1037}
1021 1038
1022static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) 1039static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
@@ -1024,7 +1041,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
1024 int ret = 0; 1041 int ret = 0;
1025 unsigned long flags; 1042 unsigned long flags;
1026 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 1043 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
1027 struct etr_buf *new_buf = NULL, *free_buf = NULL; 1044 struct etr_buf *sysfs_buf = NULL, *new_buf = NULL, *free_buf = NULL;
1028 1045
1029 /* 1046 /*
1030 * If we are enabling the ETR from disabled state, we need to make 1047 * If we are enabling the ETR from disabled state, we need to make
@@ -1035,7 +1052,8 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
1035 * with the lock released. 1052 * with the lock released.
1036 */ 1053 */
1037 spin_lock_irqsave(&drvdata->spinlock, flags); 1054 spin_lock_irqsave(&drvdata->spinlock, flags);
1038 if (!drvdata->etr_buf || (drvdata->etr_buf->size != drvdata->size)) { 1055 sysfs_buf = READ_ONCE(drvdata->sysfs_buf);
1056 if (!sysfs_buf || (sysfs_buf->size != drvdata->size)) {
1039 spin_unlock_irqrestore(&drvdata->spinlock, flags); 1057 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1040 1058
1041 /* Allocate memory with the locks released */ 1059 /* Allocate memory with the locks released */
@@ -1064,14 +1082,14 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
1064 * If we don't have a buffer or it doesn't match the requested size, 1082 * If we don't have a buffer or it doesn't match the requested size,
1065 * use the buffer allocated above. Otherwise reuse the existing buffer. 1083 * use the buffer allocated above. Otherwise reuse the existing buffer.
1066 */ 1084 */
1067 if (!drvdata->etr_buf || 1085 sysfs_buf = READ_ONCE(drvdata->sysfs_buf);
1068 (new_buf && drvdata->etr_buf->size != new_buf->size)) { 1086 if (!sysfs_buf || (new_buf && sysfs_buf->size != new_buf->size)) {
1069 free_buf = drvdata->etr_buf; 1087 free_buf = sysfs_buf;
1070 drvdata->etr_buf = new_buf; 1088 drvdata->sysfs_buf = new_buf;
1071 } 1089 }
1072 1090
1073 drvdata->mode = CS_MODE_SYSFS; 1091 drvdata->mode = CS_MODE_SYSFS;
1074 tmc_etr_enable_hw(drvdata); 1092 tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf);
1075out: 1093out:
1076 spin_unlock_irqrestore(&drvdata->spinlock, flags); 1094 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1077 1095
@@ -1156,13 +1174,13 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
1156 goto out; 1174 goto out;
1157 } 1175 }
1158 1176
1159 /* If drvdata::etr_buf is NULL the trace data has been read already */ 1177 /* If sysfs_buf is NULL the trace data has been read already */
1160 if (drvdata->etr_buf == NULL) { 1178 if (!drvdata->sysfs_buf) {
1161 ret = -EINVAL; 1179 ret = -EINVAL;
1162 goto out; 1180 goto out;
1163 } 1181 }
1164 1182
1165 /* Disable the TMC if need be */ 1183 /* Disable the TMC if we are trying to read from a running session */
1166 if (drvdata->mode == CS_MODE_SYSFS) 1184 if (drvdata->mode == CS_MODE_SYSFS)
1167 tmc_etr_disable_hw(drvdata); 1185 tmc_etr_disable_hw(drvdata);
1168 1186
@@ -1176,7 +1194,7 @@ out:
1176int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) 1194int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
1177{ 1195{
1178 unsigned long flags; 1196 unsigned long flags;
1179 struct etr_buf *etr_buf = NULL; 1197 struct etr_buf *sysfs_buf = NULL;
1180 1198
1181 /* config types are set a boot time and never change */ 1199 /* config types are set a boot time and never change */
1182 if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR)) 1200 if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
@@ -1191,22 +1209,22 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
1191 * buffer. Since the tracer is still enabled drvdata::buf can't 1209 * buffer. Since the tracer is still enabled drvdata::buf can't
1192 * be NULL. 1210 * be NULL.
1193 */ 1211 */
1194 tmc_etr_enable_hw(drvdata); 1212 tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf);
1195 } else { 1213 } else {
1196 /* 1214 /*
1197 * The ETR is not tracing and the buffer was just read. 1215 * The ETR is not tracing and the buffer was just read.
1198 * As such prepare to free the trace buffer. 1216 * As such prepare to free the trace buffer.
1199 */ 1217 */
1200 etr_buf = drvdata->etr_buf; 1218 sysfs_buf = drvdata->sysfs_buf;
1201 drvdata->etr_buf = NULL; 1219 drvdata->sysfs_buf = NULL;
1202 } 1220 }
1203 1221
1204 drvdata->reading = false; 1222 drvdata->reading = false;
1205 spin_unlock_irqrestore(&drvdata->spinlock, flags); 1223 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1206 1224
1207 /* Free allocated memory out side of the spinlock */ 1225 /* Free allocated memory out side of the spinlock */
1208 if (etr_buf) 1226 if (sysfs_buf)
1209 tmc_free_etr_buf(etr_buf); 1227 tmc_etr_free_sysfs_buf(sysfs_buf);
1210 1228
1211 return 0; 1229 return 0;
1212} 1230}
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 7027bd60c4cc..872f63e3651b 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -170,6 +170,7 @@ struct etr_buf {
170 * @trigger_cntr: amount of words to store after a trigger. 170 * @trigger_cntr: amount of words to store after a trigger.
171 * @etr_caps: Bitmask of capabilities of the TMC ETR, inferred from the 171 * @etr_caps: Bitmask of capabilities of the TMC ETR, inferred from the
172 * device configuration register (DEVID) 172 * device configuration register (DEVID)
173 * @sysfs_data: SYSFS buffer for ETR.
173 */ 174 */
174struct tmc_drvdata { 175struct tmc_drvdata {
175 void __iomem *base; 176 void __iomem *base;
@@ -189,6 +190,7 @@ struct tmc_drvdata {
189 enum tmc_mem_intf_width memwidth; 190 enum tmc_mem_intf_width memwidth;
190 u32 trigger_cntr; 191 u32 trigger_cntr;
191 u32 etr_caps; 192 u32 etr_caps;
193 struct etr_buf *sysfs_buf;
192}; 194};
193 195
194struct etr_buf_operations { 196struct etr_buf_operations {