diff options
author | Suzuki K Poulose <suzuki.poulose@arm.com> | 2018-09-20 15:18:04 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-09-25 14:09:18 -0400 |
commit | 6276f9cba50f77c5b51b581c11b74a51a3f9e040 (patch) | |
tree | 3f9d35d248d81ab8b630a1595f9510cd967dd429 /drivers/hwtracing | |
parent | b9866bb16882e89b57e2dc826114316357263fb7 (diff) |
coresight: tmc-etr: Refactor for handling errors
Refactor the tmc-etr enable operation to make it easier to
handle errors in enabling the hardware. We need to make
sure that the buffer is compatible with the ETR. This
patch re-arranges to make the error handling easier, by
deferring the hardware enablement until all the errors
are checked. This also avoids turning the CATU on/off
during a sysfs read session.
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.c | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 56fea4ff947e..c42693542ec8 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c | |||
@@ -918,21 +918,10 @@ static void tmc_sync_etr_buf(struct tmc_drvdata *drvdata) | |||
918 | tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset); | 918 | tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset); |
919 | } | 919 | } |
920 | 920 | ||
921 | static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata, | 921 | static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata) |
922 | struct etr_buf *etr_buf) | ||
923 | { | 922 | { |
924 | u32 axictl, sts; | 923 | u32 axictl, sts; |
925 | 924 | struct etr_buf *etr_buf = drvdata->etr_buf; | |
926 | /* Callers should provide an appropriate buffer for use */ | ||
927 | if (WARN_ON(!etr_buf || drvdata->etr_buf)) | ||
928 | return; | ||
929 | drvdata->etr_buf = etr_buf; | ||
930 | |||
931 | /* | ||
932 | * If this ETR is connected to a CATU, enable it before we turn | ||
933 | * this on | ||
934 | */ | ||
935 | tmc_etr_enable_catu(drvdata); | ||
936 | 925 | ||
937 | CS_UNLOCK(drvdata->base); | 926 | CS_UNLOCK(drvdata->base); |
938 | 927 | ||
@@ -952,11 +941,8 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata, | |||
952 | axictl |= TMC_AXICTL_ARCACHE_OS; | 941 | axictl |= TMC_AXICTL_ARCACHE_OS; |
953 | } | 942 | } |
954 | 943 | ||
955 | if (etr_buf->mode == ETR_MODE_ETR_SG) { | 944 | if (etr_buf->mode == ETR_MODE_ETR_SG) |
956 | if (WARN_ON(!tmc_etr_has_cap(drvdata, TMC_ETR_SG))) | ||
957 | return; | ||
958 | axictl |= TMC_AXICTL_SCT_GAT_MODE; | 945 | axictl |= TMC_AXICTL_SCT_GAT_MODE; |
959 | } | ||
960 | 946 | ||
961 | writel_relaxed(axictl, drvdata->base + TMC_AXICTL); | 947 | writel_relaxed(axictl, drvdata->base + TMC_AXICTL); |
962 | tmc_write_dba(drvdata, etr_buf->hwaddr); | 948 | tmc_write_dba(drvdata, etr_buf->hwaddr); |
@@ -982,6 +968,32 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata, | |||
982 | CS_LOCK(drvdata->base); | 968 | CS_LOCK(drvdata->base); |
983 | } | 969 | } |
984 | 970 | ||
971 | static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, | ||
972 | struct etr_buf *etr_buf) | ||
973 | { | ||
974 | /* Callers should provide an appropriate buffer for use */ | ||
975 | if (WARN_ON(!etr_buf)) | ||
976 | return -EINVAL; | ||
977 | |||
978 | if ((etr_buf->mode == ETR_MODE_ETR_SG) && | ||
979 | WARN_ON(!tmc_etr_has_cap(drvdata, TMC_ETR_SG))) | ||
980 | return -EINVAL; | ||
981 | |||
982 | if (WARN_ON(drvdata->etr_buf)) | ||
983 | return -EBUSY; | ||
984 | |||
985 | /* Set the buffer for the session */ | ||
986 | drvdata->etr_buf = etr_buf; | ||
987 | /* | ||
988 | * If this ETR is connected to a CATU, enable it before we turn | ||
989 | * this on. | ||
990 | */ | ||
991 | tmc_etr_enable_catu(drvdata); | ||
992 | |||
993 | __tmc_etr_enable_hw(drvdata); | ||
994 | return 0; | ||
995 | } | ||
996 | |||
985 | /* | 997 | /* |
986 | * Return the available trace data in the buffer (starts at etr_buf->offset, | 998 | * Return the available trace data in the buffer (starts at etr_buf->offset, |
987 | * limited by etr_buf->len) from @pos, with a maximum limit of @len, | 999 | * limited by etr_buf->len) from @pos, with a maximum limit of @len, |
@@ -1037,7 +1049,7 @@ static void tmc_etr_sync_sysfs_buf(struct tmc_drvdata *drvdata) | |||
1037 | } | 1049 | } |
1038 | } | 1050 | } |
1039 | 1051 | ||
1040 | static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) | 1052 | static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata) |
1041 | { | 1053 | { |
1042 | CS_UNLOCK(drvdata->base); | 1054 | CS_UNLOCK(drvdata->base); |
1043 | 1055 | ||
@@ -1053,6 +1065,11 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) | |||
1053 | 1065 | ||
1054 | CS_LOCK(drvdata->base); | 1066 | CS_LOCK(drvdata->base); |
1055 | 1067 | ||
1068 | } | ||
1069 | |||
1070 | static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) | ||
1071 | { | ||
1072 | __tmc_etr_disable_hw(drvdata); | ||
1056 | /* Disable CATU device if this ETR is connected to one */ | 1073 | /* Disable CATU device if this ETR is connected to one */ |
1057 | tmc_etr_disable_catu(drvdata); | 1074 | tmc_etr_disable_catu(drvdata); |
1058 | /* Reset the ETR buf used by hardware */ | 1075 | /* Reset the ETR buf used by hardware */ |
@@ -1111,8 +1128,9 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) | |||
1111 | drvdata->sysfs_buf = new_buf; | 1128 | drvdata->sysfs_buf = new_buf; |
1112 | } | 1129 | } |
1113 | 1130 | ||
1114 | drvdata->mode = CS_MODE_SYSFS; | 1131 | ret = tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf); |
1115 | tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf); | 1132 | if (!ret) |
1133 | drvdata->mode = CS_MODE_SYSFS; | ||
1116 | out: | 1134 | out: |
1117 | spin_unlock_irqrestore(&drvdata->spinlock, flags); | 1135 | spin_unlock_irqrestore(&drvdata->spinlock, flags); |
1118 | 1136 | ||
@@ -1342,8 +1360,9 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) | |||
1342 | 1360 | ||
1343 | etr_perf->head = PERF_IDX2OFF(handle->head, etr_perf); | 1361 | etr_perf->head = PERF_IDX2OFF(handle->head, etr_perf); |
1344 | drvdata->perf_data = etr_perf; | 1362 | drvdata->perf_data = etr_perf; |
1345 | drvdata->mode = CS_MODE_PERF; | 1363 | rc = tmc_etr_enable_hw(drvdata, etr_perf->etr_buf); |
1346 | tmc_etr_enable_hw(drvdata, etr_perf->etr_buf); | 1364 | if (!rc) |
1365 | drvdata->mode = CS_MODE_PERF; | ||
1347 | 1366 | ||
1348 | unlock_out: | 1367 | unlock_out: |
1349 | spin_unlock_irqrestore(&drvdata->spinlock, flags); | 1368 | spin_unlock_irqrestore(&drvdata->spinlock, flags); |
@@ -1425,7 +1444,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) | |||
1425 | 1444 | ||
1426 | /* Disable the TMC if we are trying to read from a running session. */ | 1445 | /* Disable the TMC if we are trying to read from a running session. */ |
1427 | if (drvdata->mode == CS_MODE_SYSFS) | 1446 | if (drvdata->mode == CS_MODE_SYSFS) |
1428 | tmc_etr_disable_hw(drvdata); | 1447 | __tmc_etr_disable_hw(drvdata); |
1429 | 1448 | ||
1430 | drvdata->reading = true; | 1449 | drvdata->reading = true; |
1431 | out: | 1450 | out: |
@@ -1452,7 +1471,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) | |||
1452 | * buffer. Since the tracer is still enabled drvdata::buf can't | 1471 | * buffer. Since the tracer is still enabled drvdata::buf can't |
1453 | * be NULL. | 1472 | * be NULL. |
1454 | */ | 1473 | */ |
1455 | tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf); | 1474 | __tmc_etr_enable_hw(drvdata); |
1456 | } else { | 1475 | } else { |
1457 | /* | 1476 | /* |
1458 | * The ETR is not tracing and the buffer was just read. | 1477 | * The ETR is not tracing and the buffer was just read. |