diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/boardobj/boardobjgrp.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/pmu/pmu_ipc.c | 100 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/pmu.h | 40 |
4 files changed, 113 insertions, 33 deletions
diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp.c b/drivers/gpu/nvgpu/boardobj/boardobjgrp.c index 9530e460..3249bf32 100644 --- a/drivers/gpu/nvgpu/boardobj/boardobjgrp.c +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp.c | |||
@@ -977,7 +977,7 @@ static u32 boardobjgrp_pmucmdsend_rpc(struct gk20a *g, | |||
977 | status = nvgpu_pmu_rpc_execute(pmu, &(rpc.hdr), | 977 | status = nvgpu_pmu_rpc_execute(pmu, &(rpc.hdr), |
978 | (sizeof(rpc) - sizeof(rpc.scratch)), | 978 | (sizeof(rpc) - sizeof(rpc.scratch)), |
979 | pcmd->dmem_buffer_size, | 979 | pcmd->dmem_buffer_size, |
980 | NULL, NULL); | 980 | NULL, NULL, copy_out); |
981 | 981 | ||
982 | if (status) { | 982 | if (status) { |
983 | nvgpu_err(g, "Failed to execute RPC, status=0x%x", status); | 983 | nvgpu_err(g, "Failed to execute RPC, status=0x%x", status); |
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c b/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c index 72337a1d..bb4edf38 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c | |||
@@ -953,7 +953,7 @@ int nvgpu_pmu_process_message(struct nvgpu_pmu *pmu) | |||
953 | } | 953 | } |
954 | 954 | ||
955 | int pmu_wait_message_cond(struct nvgpu_pmu *pmu, u32 timeout_ms, | 955 | int pmu_wait_message_cond(struct nvgpu_pmu *pmu, u32 timeout_ms, |
956 | u32 *var, u32 val) | 956 | void *var, u8 val) |
957 | { | 957 | { |
958 | struct gk20a *g = gk20a_from_pmu(pmu); | 958 | struct gk20a *g = gk20a_from_pmu(pmu); |
959 | struct nvgpu_timeout timeout; | 959 | struct nvgpu_timeout timeout; |
@@ -962,7 +962,7 @@ int pmu_wait_message_cond(struct nvgpu_pmu *pmu, u32 timeout_ms, | |||
962 | nvgpu_timeout_init(g, &timeout, timeout_ms, NVGPU_TIMER_CPU_TIMER); | 962 | nvgpu_timeout_init(g, &timeout, timeout_ms, NVGPU_TIMER_CPU_TIMER); |
963 | 963 | ||
964 | do { | 964 | do { |
965 | if (*var == val) | 965 | if (*(u8 *)var == val) |
966 | return 0; | 966 | return 0; |
967 | 967 | ||
968 | if (gk20a_pmu_is_interrupted(pmu)) | 968 | if (gk20a_pmu_is_interrupted(pmu)) |
@@ -980,11 +980,12 @@ static void pmu_rpc_handler(struct gk20a *g, struct pmu_msg *msg, | |||
980 | { | 980 | { |
981 | struct nv_pmu_rpc_header rpc; | 981 | struct nv_pmu_rpc_header rpc; |
982 | struct nvgpu_pmu *pmu = &g->pmu; | 982 | struct nvgpu_pmu *pmu = &g->pmu; |
983 | struct nv_pmu_rpc_struct_perfmon_query *rpc_param; | 983 | struct rpc_handler_payload *rpc_payload = |
984 | (struct rpc_handler_payload *)param; | ||
985 | struct nv_pmu_rpc_struct_perfmon_query *rpc_param; | ||
984 | 986 | ||
985 | memset(&rpc, 0, sizeof(struct nv_pmu_rpc_header)); | 987 | memset(&rpc, 0, sizeof(struct nv_pmu_rpc_header)); |
986 | if (param) | 988 | memcpy(&rpc, rpc_payload->rpc_buff, sizeof(struct nv_pmu_rpc_header)); |
987 | memcpy(&rpc, param, sizeof(struct nv_pmu_rpc_header)); | ||
988 | 989 | ||
989 | if (rpc.flcn_status) { | 990 | if (rpc.flcn_status) { |
990 | nvgpu_err(g, " failed RPC response, status=0x%x, func=0x%x", | 991 | nvgpu_err(g, " failed RPC response, status=0x%x, func=0x%x", |
@@ -1026,7 +1027,8 @@ static void pmu_rpc_handler(struct gk20a *g, struct pmu_msg *msg, | |||
1026 | case NV_PMU_RPC_ID_PERFMON_T18X_QUERY: | 1027 | case NV_PMU_RPC_ID_PERFMON_T18X_QUERY: |
1027 | nvgpu_pmu_dbg(g, | 1028 | nvgpu_pmu_dbg(g, |
1028 | "reply NV_PMU_RPC_ID_PERFMON_QUERY"); | 1029 | "reply NV_PMU_RPC_ID_PERFMON_QUERY"); |
1029 | rpc_param = (struct nv_pmu_rpc_struct_perfmon_query *)param; | 1030 | rpc_param = (struct nv_pmu_rpc_struct_perfmon_query *) |
1031 | rpc_payload->rpc_buff; | ||
1030 | pmu->load = rpc_param->sample_buffer[0]; | 1032 | pmu->load = rpc_param->sample_buffer[0]; |
1031 | pmu->perfmon_query = 1; | 1033 | pmu->perfmon_query = 1; |
1032 | /* set perfmon_query to 1 after load is copied */ | 1034 | /* set perfmon_query to 1 after load is copied */ |
@@ -1042,32 +1044,62 @@ static void pmu_rpc_handler(struct gk20a *g, struct pmu_msg *msg, | |||
1042 | 1044 | ||
1043 | exit: | 1045 | exit: |
1044 | /* free allocated memory */ | 1046 | /* free allocated memory */ |
1045 | if (param) | 1047 | if (rpc_payload->is_mem_free_set) |
1046 | nvgpu_kfree(g, param); | 1048 | nvgpu_kfree(g, rpc_payload); |
1047 | } | 1049 | } |
1048 | 1050 | ||
1049 | int nvgpu_pmu_rpc_execute(struct nvgpu_pmu *pmu, struct nv_pmu_rpc_header *rpc, | 1051 | int nvgpu_pmu_rpc_execute(struct nvgpu_pmu *pmu, struct nv_pmu_rpc_header *rpc, |
1050 | u16 size_rpc, u16 size_scratch, pmu_callback caller_cb, | 1052 | u16 size_rpc, u16 size_scratch, pmu_callback caller_cb, |
1051 | void *caller_cb_param) | 1053 | void *caller_cb_param, bool is_copy_back) |
1052 | { | 1054 | { |
1053 | struct gk20a *g = pmu->g; | 1055 | struct gk20a *g = pmu->g; |
1054 | struct pmu_cmd cmd; | 1056 | struct pmu_cmd cmd; |
1055 | struct pmu_payload payload; | 1057 | struct pmu_payload payload; |
1056 | pmu_callback callback = caller_cb; | 1058 | struct rpc_handler_payload *rpc_payload = NULL; |
1059 | pmu_callback callback = NULL; | ||
1057 | void *rpc_buff = NULL; | 1060 | void *rpc_buff = NULL; |
1058 | void *cb_param = caller_cb_param; | ||
1059 | u32 seq = 0; | 1061 | u32 seq = 0; |
1060 | int status = 0; | 1062 | int status = 0; |
1061 | 1063 | ||
1062 | if (!pmu->pmu_ready) { | 1064 | if (!pmu->pmu_ready) { |
1063 | nvgpu_warn(g, "PMU is not ready to process RPC"); | 1065 | nvgpu_warn(g, "PMU is not ready to process RPC"); |
1064 | return -EINVAL; | 1066 | status = EINVAL; |
1067 | goto exit; | ||
1065 | } | 1068 | } |
1066 | 1069 | ||
1067 | rpc_buff = nvgpu_kzalloc(g, size_rpc); | 1070 | if (caller_cb == NULL) { |
1068 | if (!rpc_buff) | 1071 | rpc_payload = nvgpu_kzalloc(g, |
1069 | return -ENOMEM; | 1072 | sizeof(struct rpc_handler_payload) + size_rpc); |
1073 | if (!rpc_payload) { | ||
1074 | status = ENOMEM; | ||
1075 | goto exit; | ||
1076 | } | ||
1077 | |||
1078 | rpc_payload->rpc_buff = (u8 *)rpc_payload + | ||
1079 | sizeof(struct rpc_handler_payload); | ||
1080 | rpc_payload->is_mem_free_set = | ||
1081 | is_copy_back ? false : true; | ||
1082 | |||
1083 | /* assign default RPC handler*/ | ||
1084 | callback = pmu_rpc_handler; | ||
1085 | } else { | ||
1086 | if (caller_cb_param == NULL) { | ||
1087 | nvgpu_err(g, "Invalid cb param addr"); | ||
1088 | status = EINVAL; | ||
1089 | goto exit; | ||
1090 | } | ||
1091 | rpc_payload = nvgpu_kzalloc(g, | ||
1092 | sizeof(struct rpc_handler_payload)); | ||
1093 | if (!rpc_payload) { | ||
1094 | status = ENOMEM; | ||
1095 | goto exit; | ||
1096 | } | ||
1097 | rpc_payload->rpc_buff = caller_cb_param; | ||
1098 | rpc_payload->is_mem_free_set = true; | ||
1099 | callback = caller_cb; | ||
1100 | } | ||
1070 | 1101 | ||
1102 | rpc_buff = rpc_payload->rpc_buff; | ||
1071 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | 1103 | memset(&cmd, 0, sizeof(struct pmu_cmd)); |
1072 | memset(&payload, 0, sizeof(struct pmu_payload)); | 1104 | memset(&payload, 0, sizeof(struct pmu_payload)); |
1073 | 1105 | ||
@@ -1081,24 +1113,38 @@ int nvgpu_pmu_rpc_execute(struct nvgpu_pmu *pmu, struct nv_pmu_rpc_header *rpc, | |||
1081 | payload.rpc.size_rpc = size_rpc; | 1113 | payload.rpc.size_rpc = size_rpc; |
1082 | payload.rpc.size_scratch = size_scratch; | 1114 | payload.rpc.size_scratch = size_scratch; |
1083 | 1115 | ||
1084 | /* assign default RPC handler & buffer */ | ||
1085 | if (!callback && !cb_param) { | ||
1086 | callback = pmu_rpc_handler; | ||
1087 | cb_param = rpc_buff; | ||
1088 | } | ||
1089 | |||
1090 | status = nvgpu_pmu_cmd_post(g, &cmd, NULL, &payload, | 1116 | status = nvgpu_pmu_cmd_post(g, &cmd, NULL, &payload, |
1091 | PMU_COMMAND_QUEUE_LPQ, pmu_rpc_handler, | 1117 | PMU_COMMAND_QUEUE_LPQ, callback, |
1092 | cb_param, &seq, ~0); | 1118 | rpc_payload, &seq, ~0); |
1093 | if (status) { | 1119 | if (status) { |
1094 | nvgpu_err(g, "Failed to execute RPC status=0x%x, func=0x%x", | 1120 | nvgpu_err(g, "Failed to execute RPC status=0x%x, func=0x%x", |
1095 | status, rpc->function); | 1121 | status, rpc->function); |
1122 | goto exit; | ||
1096 | } | 1123 | } |
1097 | 1124 | ||
1098 | /* if caller passed buff then free allocated RPC buffer */ | 1125 | /* |
1099 | if (caller_cb_param) | 1126 | * Option act like blocking call, which waits till RPC request |
1100 | nvgpu_kfree(g, rpc_buff); | 1127 | * executes on PMU & copy back processed data to rpc_buff |
1128 | * to read data back in nvgpu | ||
1129 | */ | ||
1130 | if (is_copy_back) { | ||
1131 | /* clear buff */ | ||
1132 | memset(rpc_buff, 0, size_rpc); | ||
1133 | /* wait till RPC execute in PMU & ACK */ | ||
1134 | pmu_wait_message_cond(pmu, gk20a_get_gr_idle_timeout(g), | ||
1135 | &((struct nv_pmu_rpc_header *)rpc_buff)->function, | ||
1136 | rpc->function); | ||
1137 | /* copy back data to caller */ | ||
1138 | memcpy(rpc, rpc_buff, size_rpc); | ||
1139 | /* free allocated memory */ | ||
1140 | nvgpu_kfree(g, rpc_payload); | ||
1141 | } | ||
1101 | 1142 | ||
1102 | return status; | 1143 | exit: |
1144 | if (status) { | ||
1145 | if (rpc_payload) | ||
1146 | nvgpu_kfree(g, rpc_payload); | ||
1147 | } | ||
1103 | 1148 | ||
1149 | return status; | ||
1104 | } | 1150 | } |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index 5bd43510..27d27007 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * GK20A PMU (aka. gPMU outside gk20a context) | 4 | * GK20A PMU (aka. gPMU outside gk20a context) |
5 | * | 5 | * |
6 | * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. | 6 | * Copyright (c) 2011-2018, NVIDIA CORPORATION. All rights reserved. |
7 | * | 7 | * |
8 | * Permission is hereby granted, free of charge, to any person obtaining a | 8 | * Permission is hereby granted, free of charge, to any person obtaining a |
9 | * copy of this software and associated documentation files (the "Software"), | 9 | * copy of this software and associated documentation files (the "Software"), |
@@ -69,7 +69,7 @@ void gk20a_pmu_dump_falcon_stats(struct nvgpu_pmu *pmu); | |||
69 | 69 | ||
70 | void pmu_enable_irq(struct nvgpu_pmu *pmu, bool enable); | 70 | void pmu_enable_irq(struct nvgpu_pmu *pmu, bool enable); |
71 | int pmu_wait_message_cond(struct nvgpu_pmu *pmu, u32 timeout_ms, | 71 | int pmu_wait_message_cond(struct nvgpu_pmu *pmu, u32 timeout_ms, |
72 | u32 *var, u32 val); | 72 | void *var, u8 val); |
73 | void pmu_handle_fecs_boot_acr_msg(struct gk20a *g, struct pmu_msg *msg, | 73 | void pmu_handle_fecs_boot_acr_msg(struct gk20a *g, struct pmu_msg *msg, |
74 | void *param, u32 handle, u32 status); | 74 | void *param, u32 handle, u32 status); |
75 | void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, | 75 | void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, |
diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu.h b/drivers/gpu/nvgpu/include/nvgpu/pmu.h index 76a54fa1..507b8133 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmu.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmu.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
@@ -154,12 +154,45 @@ enum { | |||
154 | \ | 154 | \ |
155 | _stat = nvgpu_pmu_rpc_execute(_pmu, &((_prpc)->hdr), \ | 155 | _stat = nvgpu_pmu_rpc_execute(_pmu, &((_prpc)->hdr), \ |
156 | (sizeof(*(_prpc)) - sizeof((_prpc)->scratch)),\ | 156 | (sizeof(*(_prpc)) - sizeof((_prpc)->scratch)),\ |
157 | (_size), NULL, NULL); \ | 157 | (_size), NULL, NULL, false); \ |
158 | } while (0) | ||
159 | |||
160 | /* RPC blocking call to copy back data from PMU to _prpc */ | ||
161 | #define PMU_RPC_EXECUTE_CPB(_stat, _pmu, _unit, _func, _prpc, _size)\ | ||
162 | do { \ | ||
163 | memset(&((_prpc)->hdr), 0, sizeof((_prpc)->hdr));\ | ||
164 | \ | ||
165 | (_prpc)->hdr.unit_id = PMU_UNIT_##_unit; \ | ||
166 | (_prpc)->hdr.function = NV_PMU_RPC_ID_##_unit##_##_func;\ | ||
167 | (_prpc)->hdr.flags = 0x0; \ | ||
168 | \ | ||
169 | _stat = nvgpu_pmu_rpc_execute(_pmu, &((_prpc)->hdr), \ | ||
170 | (sizeof(*(_prpc)) - sizeof((_prpc)->scratch)),\ | ||
171 | (_size), NULL, NULL, true); \ | ||
172 | } while (0) | ||
173 | |||
174 | /* RPC non-blocking with call_back handler option */ | ||
175 | #define PMU_RPC_EXECUTE_CB(_stat, _pmu, _unit, _func, _prpc, _size, _cb, _cbp)\ | ||
176 | do { \ | ||
177 | memset(&((_prpc)->hdr), 0, sizeof((_prpc)->hdr));\ | ||
178 | \ | ||
179 | (_prpc)->hdr.unit_id = PMU_UNIT_##_unit; \ | ||
180 | (_prpc)->hdr.function = NV_PMU_RPC_ID_##_unit##_##_func;\ | ||
181 | (_prpc)->hdr.flags = 0x0; \ | ||
182 | \ | ||
183 | _stat = nvgpu_pmu_rpc_execute(_pmu, &((_prpc)->hdr), \ | ||
184 | (sizeof(*(_prpc)) - sizeof((_prpc)->scratch)),\ | ||
185 | (_size), _cb, _cbp, false); \ | ||
158 | } while (0) | 186 | } while (0) |
159 | 187 | ||
160 | typedef void (*pmu_callback)(struct gk20a *, struct pmu_msg *, void *, u32, | 188 | typedef void (*pmu_callback)(struct gk20a *, struct pmu_msg *, void *, u32, |
161 | u32); | 189 | u32); |
162 | 190 | ||
191 | struct rpc_handler_payload { | ||
192 | void *rpc_buff; | ||
193 | bool is_mem_free_set; | ||
194 | }; | ||
195 | |||
163 | struct pmu_rpc_desc { | 196 | struct pmu_rpc_desc { |
164 | void *prpc; | 197 | void *prpc; |
165 | u16 size_rpc; | 198 | u16 size_rpc; |
@@ -500,6 +533,7 @@ bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos); | |||
500 | 533 | ||
501 | /* PMU RPC */ | 534 | /* PMU RPC */ |
502 | int nvgpu_pmu_rpc_execute(struct nvgpu_pmu *pmu, struct nv_pmu_rpc_header *rpc, | 535 | int nvgpu_pmu_rpc_execute(struct nvgpu_pmu *pmu, struct nv_pmu_rpc_header *rpc, |
503 | u16 size_rpc, u16 size_scratch, pmu_callback callback, void *cb_param); | 536 | u16 size_rpc, u16 size_scratch, pmu_callback callback, void *cb_param, |
537 | bool is_copy_back); | ||
504 | 538 | ||
505 | #endif /* __NVGPU_PMU_H__ */ | 539 | #endif /* __NVGPU_PMU_H__ */ |