Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf/arm_cspmu: nvidia: Add pmevfiltr2 support

Support NVIDIA PMU that utilizes the optional event filter2 register.

Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Besar Wicaksono and committed by
Will Deacon
decc3684 82dfd72b

+133 -43
+133 -43
drivers/perf/arm_cspmu/nvidia_cspmu.c
··· 40 40 41 41 struct nv_cspmu_ctx { 42 42 const char *name; 43 - u32 filter_mask; 44 - u32 filter_default_val; 43 + 45 44 struct attribute **event_attr; 46 45 struct attribute **format_attr; 46 + 47 + u32 filter_mask; 48 + u32 filter_default_val; 49 + u32 filter2_mask; 50 + u32 filter2_default_val; 51 + 52 + u32 (*get_filter)(const struct perf_event *event); 53 + u32 (*get_filter2)(const struct perf_event *event); 54 + 55 + void *data; 56 + 57 + int (*init_data)(struct arm_cspmu *cspmu); 47 58 }; 48 59 49 60 static struct attribute *scf_pmu_event_attrs[] = { ··· 155 144 static struct attribute *generic_pmu_format_attrs[] = { 156 145 ARM_CSPMU_FORMAT_EVENT_ATTR, 157 146 ARM_CSPMU_FORMAT_FILTER_ATTR, 147 + ARM_CSPMU_FORMAT_FILTER2_ATTR, 158 148 NULL, 159 149 }; 160 150 ··· 196 184 return filter_val; 197 185 } 198 186 187 + static u32 nv_cspmu_event_filter2(const struct perf_event *event) 188 + { 189 + const struct nv_cspmu_ctx *ctx = 190 + to_nv_cspmu_ctx(to_arm_cspmu(event->pmu)); 191 + 192 + const u32 filter_val = event->attr.config2 & ctx->filter2_mask; 193 + 194 + if (filter_val == 0) 195 + return ctx->filter2_default_val; 196 + 197 + return filter_val; 198 + } 199 + 199 200 static void nv_cspmu_set_ev_filter(struct arm_cspmu *cspmu, 200 201 const struct perf_event *event) 201 202 { 202 - u32 filter = nv_cspmu_event_filter(event); 203 - u32 offset = PMEVFILTR + (4 * event->hw.idx); 203 + u32 filter, offset; 204 + const struct nv_cspmu_ctx *ctx = 205 + to_nv_cspmu_ctx(to_arm_cspmu(event->pmu)); 206 + offset = 4 * event->hw.idx; 204 207 205 - writel(filter, cspmu->base0 + offset); 208 + if (ctx->get_filter) { 209 + filter = ctx->get_filter(event); 210 + writel(filter, cspmu->base0 + PMEVFILTR + offset); 211 + } 212 + 213 + if (ctx->get_filter2) { 214 + filter = ctx->get_filter2(event); 215 + writel(filter, cspmu->base0 + PMEVFILT2R + offset); 216 + } 206 217 } 207 218 208 219 static void nv_cspmu_set_cc_filter(struct arm_cspmu *cspmu, ··· 245 210 struct nv_cspmu_match { 246 211 u32 prodid; 247 212 u32 prodid_mask; 248 - u64 filter_mask; 249 - u32 filter_default_val; 250 213 const char *name_pattern; 251 214 enum nv_cspmu_name_fmt name_fmt; 252 - struct attribute **event_attr; 253 - struct attribute **format_attr; 215 + struct nv_cspmu_ctx template_ctx; 216 + struct arm_cspmu_impl_ops ops; 254 217 }; 255 218 256 219 static const struct nv_cspmu_match nv_cspmu_match[] = { 257 220 { 258 221 .prodid = 0x10300000, 259 222 .prodid_mask = NV_PRODID_MASK, 260 - .filter_mask = NV_PCIE_FILTER_ID_MASK, 261 - .filter_default_val = NV_PCIE_FILTER_ID_MASK, 262 223 .name_pattern = "nvidia_pcie_pmu_%u", 263 224 .name_fmt = NAME_FMT_SOCKET, 264 - .event_attr = mcf_pmu_event_attrs, 265 - .format_attr = pcie_pmu_format_attrs 225 + .template_ctx = { 226 + .event_attr = mcf_pmu_event_attrs, 227 + .format_attr = pcie_pmu_format_attrs, 228 + .filter_mask = NV_PCIE_FILTER_ID_MASK, 229 + .filter_default_val = NV_PCIE_FILTER_ID_MASK, 230 + .filter2_mask = 0x0, 231 + .filter2_default_val = 0x0, 232 + .get_filter = nv_cspmu_event_filter, 233 + .get_filter2 = NULL, 234 + .data = NULL, 235 + .init_data = NULL 236 + }, 266 237 }, 267 238 { 268 239 .prodid = 0x10400000, 269 240 .prodid_mask = NV_PRODID_MASK, 270 - .filter_mask = NV_NVL_C2C_FILTER_ID_MASK, 271 - .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK, 272 241 .name_pattern = "nvidia_nvlink_c2c1_pmu_%u", 273 242 .name_fmt = NAME_FMT_SOCKET, 274 - .event_attr = mcf_pmu_event_attrs, 275 - .format_attr = nvlink_c2c_pmu_format_attrs 243 + .template_ctx = { 244 + .event_attr = mcf_pmu_event_attrs, 245 + .format_attr = nvlink_c2c_pmu_format_attrs, 246 + .filter_mask = NV_NVL_C2C_FILTER_ID_MASK, 247 + .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK, 248 + .filter2_mask = 0x0, 249 + .filter2_default_val = 0x0, 250 + .get_filter = nv_cspmu_event_filter, 251 + .get_filter2 = NULL, 252 + .data = NULL, 253 + .init_data = NULL 254 + }, 276 255 }, 277 256 { 278 257 .prodid = 0x10500000, 279 258 .prodid_mask = NV_PRODID_MASK, 280 - .filter_mask = NV_NVL_C2C_FILTER_ID_MASK, 281 - .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK, 282 259 .name_pattern = "nvidia_nvlink_c2c0_pmu_%u", 283 260 .name_fmt = NAME_FMT_SOCKET, 284 - .event_attr = mcf_pmu_event_attrs, 285 - .format_attr = nvlink_c2c_pmu_format_attrs 261 + .template_ctx = { 262 + .event_attr = mcf_pmu_event_attrs, 263 + .format_attr = nvlink_c2c_pmu_format_attrs, 264 + .filter_mask = NV_NVL_C2C_FILTER_ID_MASK, 265 + .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK, 266 + .filter2_mask = 0x0, 267 + .filter2_default_val = 0x0, 268 + .get_filter = nv_cspmu_event_filter, 269 + .get_filter2 = NULL, 270 + .data = NULL, 271 + .init_data = NULL 272 + }, 286 273 }, 287 274 { 288 275 .prodid = 0x10600000, 289 276 .prodid_mask = NV_PRODID_MASK, 290 - .filter_mask = NV_CNVL_FILTER_ID_MASK, 291 - .filter_default_val = NV_CNVL_FILTER_ID_MASK, 292 277 .name_pattern = "nvidia_cnvlink_pmu_%u", 293 278 .name_fmt = NAME_FMT_SOCKET, 294 - .event_attr = mcf_pmu_event_attrs, 295 - .format_attr = cnvlink_pmu_format_attrs 279 + .template_ctx = { 280 + .event_attr = mcf_pmu_event_attrs, 281 + .format_attr = cnvlink_pmu_format_attrs, 282 + .filter_mask = NV_CNVL_FILTER_ID_MASK, 283 + .filter_default_val = NV_CNVL_FILTER_ID_MASK, 284 + .filter2_mask = 0x0, 285 + .filter2_default_val = 0x0, 286 + .get_filter = nv_cspmu_event_filter, 287 + .get_filter2 = NULL, 288 + .data = NULL, 289 + .init_data = NULL 290 + }, 296 291 }, 297 292 { 298 293 .prodid = 0x2CF00000, 299 294 .prodid_mask = NV_PRODID_MASK, 300 - .filter_mask = 0x0, 301 - .filter_default_val = 0x0, 302 295 .name_pattern = "nvidia_scf_pmu_%u", 303 296 .name_fmt = NAME_FMT_SOCKET, 304 - .event_attr = scf_pmu_event_attrs, 305 - .format_attr = scf_pmu_format_attrs 297 + .template_ctx = { 298 + .event_attr = scf_pmu_event_attrs, 299 + .format_attr = scf_pmu_format_attrs, 300 + .filter_mask = 0x0, 301 + .filter_default_val = 0x0, 302 + .filter2_mask = 0x0, 303 + .filter2_default_val = 0x0, 304 + .get_filter = nv_cspmu_event_filter, 305 + .get_filter2 = NULL, 306 + .data = NULL, 307 + .init_data = NULL 308 + }, 306 309 }, 307 310 { 308 311 .prodid = 0, 309 312 .prodid_mask = 0, 310 - .filter_mask = NV_GENERIC_FILTER_ID_MASK, 311 - .filter_default_val = NV_GENERIC_FILTER_ID_MASK, 312 313 .name_pattern = "nvidia_uncore_pmu_%u", 313 314 .name_fmt = NAME_FMT_GENERIC, 314 - .event_attr = generic_pmu_event_attrs, 315 - .format_attr = generic_pmu_format_attrs 315 + .template_ctx = { 316 + .event_attr = generic_pmu_event_attrs, 317 + .format_attr = generic_pmu_format_attrs, 318 + .filter_mask = NV_GENERIC_FILTER_ID_MASK, 319 + .filter_default_val = NV_GENERIC_FILTER_ID_MASK, 320 + .filter2_mask = NV_GENERIC_FILTER_ID_MASK, 321 + .filter2_default_val = NV_GENERIC_FILTER_ID_MASK, 322 + .get_filter = nv_cspmu_event_filter, 323 + .get_filter2 = nv_cspmu_event_filter2, 324 + .data = NULL, 325 + .init_data = NULL 326 + }, 316 327 }, 317 328 }; 318 329 ··· 391 310 return name; 392 311 } 393 312 313 + #define SET_OP(name, impl, match, default_op) \ 314 + do { \ 315 + if (match->ops.name) \ 316 + impl->name = match->ops.name; \ 317 + else if (default_op != NULL) \ 318 + impl->name = default_op; \ 319 + } while (false) 320 + 394 321 static int nv_cspmu_init_ops(struct arm_cspmu *cspmu) 395 322 { 396 323 struct nv_cspmu_ctx *ctx; ··· 419 330 break; 420 331 } 421 332 422 - ctx->name = nv_cspmu_format_name(cspmu, match); 423 - ctx->filter_mask = match->filter_mask; 424 - ctx->filter_default_val = match->filter_default_val; 425 - ctx->event_attr = match->event_attr; 426 - ctx->format_attr = match->format_attr; 333 + /* Initialize the context with the matched template. */ 334 + memcpy(ctx, &match->template_ctx, sizeof(struct nv_cspmu_ctx)); 335 + ctx->name = nv_cspmu_format_name(cspmu, match); 427 336 428 337 cspmu->impl.ctx = ctx; 429 338 430 339 /* NVIDIA specific callbacks. */ 431 - impl_ops->set_cc_filter = nv_cspmu_set_cc_filter; 432 - impl_ops->set_ev_filter = nv_cspmu_set_ev_filter; 433 - impl_ops->get_event_attrs = nv_cspmu_get_event_attrs; 434 - impl_ops->get_format_attrs = nv_cspmu_get_format_attrs; 435 - impl_ops->get_name = nv_cspmu_get_name; 340 + SET_OP(set_cc_filter, impl_ops, match, nv_cspmu_set_cc_filter); 341 + SET_OP(set_ev_filter, impl_ops, match, nv_cspmu_set_ev_filter); 342 + SET_OP(get_event_attrs, impl_ops, match, nv_cspmu_get_event_attrs); 343 + SET_OP(get_format_attrs, impl_ops, match, nv_cspmu_get_format_attrs); 344 + SET_OP(get_name, impl_ops, match, nv_cspmu_get_name); 345 + 346 + if (ctx->init_data) 347 + return ctx->init_data(cspmu); 436 348 437 349 return 0; 438 350 }