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

Merge tag 'coresight-next-v6.19' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next

Suzuki writes:

coresight: Updates for Linux v6.19

The changes for Linux v6.19 include :
- Support for static TPDM
- Fixes to TMC-ETR with CATU where buffer wasn't available to CATU in perf mode
- Clean ups to the component operations to accept coresight_path
- Fixes to the ETM4x/ETM3x driver

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

* tag 'coresight-next-v6.19' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux:
coresight: etm4x: Remove the state_needs_restore flag
coresight: etm4x: Remove the redundant DSB
coresight: etm4x: Properly control filter in CPU idle with FEAT_TRF
coresight: etm4x: Add context synchronization before enabling trace
coresight: etm4x: Correct polling IDLE bit
coresight: etm3x: Always set tracer's device mode on target CPU
coresight: etm4x: Always set tracer's device mode on target CPU
coresight: Change device mode to atomic type
coresight: change the sink_ops to accept coresight_path
coresight: change helper_ops to accept coresight_path
coresight: tmc: add the handle of the event to the path
coresight: tpdm: remove redundant check for drvdata
coresight: tpdm: add static tpdm support
dt-bindings: arm: document the static TPDM compatible
coresight: ETR: Fix ETR buffer use-after-free issue

+402 -187
+20 -3
Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
··· 36 36 $nodename: 37 37 pattern: "^tpdm(@[0-9a-f]+)$" 38 38 compatible: 39 - items: 40 - - const: qcom,coresight-tpdm 41 - - const: arm,primecell 39 + oneOf: 40 + - items: 41 + - const: qcom,coresight-static-tpdm 42 + - items: 43 + - const: qcom,coresight-tpdm 44 + - const: arm,primecell 42 45 43 46 reg: 44 47 maxItems: 1 ··· 147 144 tpdm_ipcc_out_funnel_center: endpoint { 148 145 remote-endpoint = <&funnel_center_in_tpdm_ipcc>; 149 146 }; 147 + }; 148 + }; 149 + }; 150 + 151 + turing-llm-tpdm { 152 + compatible = "qcom,coresight-static-tpdm"; 153 + 154 + qcom,cmb-element-bits = <32>; 155 + 156 + out-ports { 157 + port { 158 + turing_llm_tpdm_out: endpoint { 159 + remote-endpoint = <&turing0_funnel_in1>; 160 + }; 150 161 }; 151 162 }; 152 163 };
+5 -5
drivers/hwtracing/coresight/coresight-catu.c
··· 397 397 } 398 398 399 399 static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode, 400 - void *data) 400 + struct coresight_path *path) 401 401 { 402 402 int rc; 403 403 u32 control, mode; ··· 425 425 etrdev = coresight_find_input_type( 426 426 csdev->pdata, CORESIGHT_DEV_TYPE_SINK, etr_subtype); 427 427 if (etrdev) { 428 - etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, data); 428 + etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, path); 429 429 if (IS_ERR(etr_buf)) 430 430 return PTR_ERR(etr_buf); 431 431 } ··· 455 455 } 456 456 457 457 static int catu_enable(struct coresight_device *csdev, enum cs_mode mode, 458 - void *data) 458 + struct coresight_path *path) 459 459 { 460 460 int rc = 0; 461 461 struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev); ··· 463 463 guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock); 464 464 if (csdev->refcnt == 0) { 465 465 CS_UNLOCK(catu_drvdata->base); 466 - rc = catu_enable_hw(catu_drvdata, mode, data); 466 + rc = catu_enable_hw(catu_drvdata, mode, path); 467 467 CS_LOCK(catu_drvdata->base); 468 468 } 469 469 if (!rc) ··· 488 488 return rc; 489 489 } 490 490 491 - static int catu_disable(struct coresight_device *csdev, void *__unused) 491 + static int catu_disable(struct coresight_device *csdev, struct coresight_path *path) 492 492 { 493 493 int rc = 0; 494 494 struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
+17 -13
drivers/hwtracing/coresight/coresight-core.c
··· 300 300 EXPORT_SYMBOL_GPL(coresight_add_helper); 301 301 302 302 static int coresight_enable_sink(struct coresight_device *csdev, 303 - enum cs_mode mode, void *data) 303 + enum cs_mode mode, 304 + struct coresight_path *path) 304 305 { 305 - return sink_ops(csdev)->enable(csdev, mode, data); 306 + return sink_ops(csdev)->enable(csdev, mode, path); 306 307 } 307 308 308 309 static void coresight_disable_sink(struct coresight_device *csdev) ··· 356 355 } 357 356 358 357 static int coresight_enable_helper(struct coresight_device *csdev, 359 - enum cs_mode mode, void *data) 358 + enum cs_mode mode, 359 + struct coresight_path *path) 360 360 { 361 - return helper_ops(csdev)->enable(csdev, mode, data); 361 + return helper_ops(csdev)->enable(csdev, mode, path); 362 362 } 363 363 364 - static void coresight_disable_helper(struct coresight_device *csdev, void *data) 364 + static void coresight_disable_helper(struct coresight_device *csdev, 365 + struct coresight_path *path) 365 366 { 366 - helper_ops(csdev)->disable(csdev, data); 367 + helper_ops(csdev)->disable(csdev, path); 367 368 } 368 369 369 - static void coresight_disable_helpers(struct coresight_device *csdev, void *data) 370 + static void coresight_disable_helpers(struct coresight_device *csdev, 371 + struct coresight_path *path) 370 372 { 371 373 int i; 372 374 struct coresight_device *helper; ··· 377 373 for (i = 0; i < csdev->pdata->nr_outconns; ++i) { 378 374 helper = csdev->pdata->out_conns[i]->dest_dev; 379 375 if (helper && coresight_is_helper(helper)) 380 - coresight_disable_helper(helper, data); 376 + coresight_disable_helper(helper, path); 381 377 } 382 378 } 383 379 ··· 483 479 EXPORT_SYMBOL_GPL(coresight_disable_path); 484 480 485 481 static int coresight_enable_helpers(struct coresight_device *csdev, 486 - enum cs_mode mode, void *data) 482 + enum cs_mode mode, 483 + struct coresight_path *path) 487 484 { 488 485 int i, ret = 0; 489 486 struct coresight_device *helper; ··· 494 489 if (!helper || !coresight_is_helper(helper)) 495 490 continue; 496 491 497 - ret = coresight_enable_helper(helper, mode, data); 492 + ret = coresight_enable_helper(helper, mode, path); 498 493 if (ret) 499 494 return ret; 500 495 } ··· 502 497 return 0; 503 498 } 504 499 505 - int coresight_enable_path(struct coresight_path *path, enum cs_mode mode, 506 - void *sink_data) 500 + int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) 507 501 { 508 502 int ret = 0; 509 503 u32 type; ··· 532 528 533 529 switch (type) { 534 530 case CORESIGHT_DEV_TYPE_SINK: 535 - ret = coresight_enable_sink(csdev, mode, sink_data); 531 + ret = coresight_enable_sink(csdev, mode, path); 536 532 /* 537 533 * Sink is the first component turned on. If we 538 534 * failed to enable the sink, there are no components
+3 -6
drivers/hwtracing/coresight/coresight-ctcu-core.c
··· 156 156 return __ctcu_set_etr_traceid(csdev, traceid, port_num, enable); 157 157 } 158 158 159 - static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode, void *data) 159 + static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode, 160 + struct coresight_path *path) 160 161 { 161 - struct coresight_path *path = (struct coresight_path *)data; 162 - 163 162 return ctcu_set_etr_traceid(csdev, path, true); 164 163 } 165 164 166 - static int ctcu_disable(struct coresight_device *csdev, void *data) 165 + static int ctcu_disable(struct coresight_device *csdev, struct coresight_path *path) 167 166 { 168 - struct coresight_path *path = (struct coresight_path *)data; 169 - 170 167 return ctcu_set_etr_traceid(csdev, path, false); 171 168 } 172 169
+3 -2
drivers/hwtracing/coresight/coresight-cti-core.c
··· 799 799 } 800 800 801 801 /** cti ect operations **/ 802 - int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data) 802 + int cti_enable(struct coresight_device *csdev, enum cs_mode mode, 803 + struct coresight_path *path) 803 804 { 804 805 struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev); 805 806 806 807 return cti_enable_hw(drvdata); 807 808 } 808 809 809 - int cti_disable(struct coresight_device *csdev, void *data) 810 + int cti_disable(struct coresight_device *csdev, struct coresight_path *path) 810 811 { 811 812 struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev); 812 813
+3 -2
drivers/hwtracing/coresight/coresight-cti.h
··· 216 216 const char *assoc_dev_name); 217 217 struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, 218 218 int out_sigs); 219 - int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data); 220 - int cti_disable(struct coresight_device *csdev, void *data); 219 + int cti_enable(struct coresight_device *csdev, enum cs_mode mode, 220 + struct coresight_path *path); 221 + int cti_disable(struct coresight_device *csdev, struct coresight_path *path); 221 222 void cti_write_all_hw_regs(struct cti_drvdata *drvdata); 222 223 void cti_write_intack(struct device *dev, u32 ackval); 223 224 void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
+1 -1
drivers/hwtracing/coresight/coresight-dummy.c
··· 52 52 } 53 53 54 54 static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode, 55 - void *data) 55 + struct coresight_path *path) 56 56 { 57 57 dev_dbg(csdev->dev.parent, "Dummy sink enabled\n"); 58 58
+4 -4
drivers/hwtracing/coresight/coresight-etb10.c
··· 167 167 return ret; 168 168 } 169 169 170 - static int etb_enable_perf(struct coresight_device *csdev, void *data) 170 + static int etb_enable_perf(struct coresight_device *csdev, struct coresight_path *path) 171 171 { 172 172 int ret = 0; 173 173 pid_t pid; 174 174 unsigned long flags; 175 175 struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 176 - struct perf_output_handle *handle = data; 176 + struct perf_output_handle *handle = path->handle; 177 177 struct cs_buffers *buf = etm_perf_sink_config(handle); 178 178 179 179 raw_spin_lock_irqsave(&drvdata->spinlock, flags); ··· 224 224 } 225 225 226 226 static int etb_enable(struct coresight_device *csdev, enum cs_mode mode, 227 - void *data) 227 + struct coresight_path *path) 228 228 { 229 229 int ret; 230 230 ··· 233 233 ret = etb_enable_sysfs(csdev); 234 234 break; 235 235 case CS_MODE_PERF: 236 - ret = etb_enable_perf(csdev, data); 236 + ret = etb_enable_perf(csdev, path); 237 237 break; 238 238 default: 239 239 ret = -EINVAL;
+2 -1
drivers/hwtracing/coresight/coresight-etm-perf.c
··· 520 520 goto out; 521 521 522 522 path = etm_event_cpu_path(event_data, cpu); 523 + path->handle = handle; 523 524 /* We need a sink, no need to continue without one */ 524 525 sink = coresight_get_sink(path); 525 526 if (WARN_ON_ONCE(!sink)) 526 527 goto fail_end_stop; 527 528 528 529 /* Nothing will happen without a path */ 529 - if (coresight_enable_path(path, CS_MODE_PERF, handle)) 530 + if (coresight_enable_path(path, CS_MODE_PERF)) 530 531 goto fail_end_stop; 531 532 532 533 /* Finally enable the tracer */
+40 -19
drivers/hwtracing/coresight/coresight-etm3x-core.c
··· 439 439 int rc; 440 440 }; 441 441 442 - static void etm_enable_hw_smp_call(void *info) 442 + static void etm_enable_sysfs_smp_call(void *info) 443 443 { 444 444 struct etm_enable_arg *arg = info; 445 + struct coresight_device *csdev; 445 446 446 447 if (WARN_ON(!arg)) 447 448 return; 449 + 450 + csdev = arg->drvdata->csdev; 451 + if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) { 452 + /* Someone is already using the tracer */ 453 + arg->rc = -EBUSY; 454 + return; 455 + } 456 + 448 457 arg->rc = etm_enable_hw(arg->drvdata); 458 + 459 + /* The tracer didn't start */ 460 + if (arg->rc) 461 + coresight_set_mode(csdev, CS_MODE_DISABLED); 449 462 } 450 463 451 464 static int etm_cpu_id(struct coresight_device *csdev) ··· 478 465 struct coresight_path *path) 479 466 { 480 467 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 468 + int ret; 481 469 482 470 if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) 483 471 return -EINVAL; 472 + 473 + if (!coresight_take_mode(csdev, CS_MODE_PERF)) 474 + return -EBUSY; 484 475 485 476 /* Configure the tracer based on the session's specifics */ 486 477 etm_parse_event_config(drvdata, event); 487 478 drvdata->traceid = path->trace_id; 488 479 489 480 /* And enable it */ 490 - return etm_enable_hw(drvdata); 481 + ret = etm_enable_hw(drvdata); 482 + 483 + /* Failed to start tracer; roll back to DISABLED mode */ 484 + if (ret) 485 + coresight_set_mode(csdev, CS_MODE_DISABLED); 486 + 487 + return ret; 491 488 } 492 489 493 490 static int etm_enable_sysfs(struct coresight_device *csdev, struct coresight_path *path) ··· 517 494 if (cpu_online(drvdata->cpu)) { 518 495 arg.drvdata = drvdata; 519 496 ret = smp_call_function_single(drvdata->cpu, 520 - etm_enable_hw_smp_call, &arg, 1); 497 + etm_enable_sysfs_smp_call, &arg, 1); 521 498 if (!ret) 522 499 ret = arg.rc; 523 500 if (!ret) ··· 540 517 enum cs_mode mode, struct coresight_path *path) 541 518 { 542 519 int ret; 543 - struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 544 - 545 - if (!coresight_take_mode(csdev, mode)) { 546 - /* Someone is already using the tracer */ 547 - return -EBUSY; 548 - } 549 520 550 521 switch (mode) { 551 522 case CS_MODE_SYSFS: ··· 552 535 ret = -EINVAL; 553 536 } 554 537 555 - /* The tracer didn't start */ 556 - if (ret) 557 - coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); 558 - 559 538 return ret; 560 539 } 561 540 562 - static void etm_disable_hw(void *info) 541 + static void etm_disable_hw(struct etm_drvdata *drvdata) 563 542 { 564 543 int i; 565 - struct etm_drvdata *drvdata = info; 566 544 struct etm_config *config = &drvdata->config; 567 545 struct coresight_device *csdev = drvdata->csdev; 568 546 ··· 577 565 578 566 dev_dbg(&drvdata->csdev->dev, 579 567 "cpu: %d disable smp call done\n", drvdata->cpu); 568 + } 569 + 570 + static void etm_disable_sysfs_smp_call(void *info) 571 + { 572 + struct etm_drvdata *drvdata = info; 573 + 574 + etm_disable_hw(drvdata); 575 + 576 + coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); 580 577 } 581 578 582 579 static void etm_disable_perf(struct coresight_device *csdev) ··· 608 587 coresight_disclaim_device_unlocked(csdev); 609 588 610 589 CS_LOCK(drvdata->csa.base); 590 + 591 + coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); 611 592 612 593 /* 613 594 * perf will release trace ids when _free_aux() ··· 635 612 * Executing etm_disable_hw on the cpu whose ETM is being disabled 636 613 * ensures that register writes occur when cpu is powered. 637 614 */ 638 - smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1); 615 + smp_call_function_single(drvdata->cpu, etm_disable_sysfs_smp_call, 616 + drvdata, 1); 639 617 640 618 spin_unlock(&drvdata->spinlock); 641 619 cpus_read_unlock(); ··· 676 652 WARN_ON_ONCE(mode); 677 653 return; 678 654 } 679 - 680 - if (mode) 681 - coresight_set_mode(csdev, CS_MODE_DISABLED); 682 655 } 683 656 684 657 static const struct coresight_ops_source etm_source_ops = {
+95 -45
drivers/hwtracing/coresight/coresight-etm4x-core.c
··· 446 446 etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR); 447 447 448 448 etm4x_allow_trace(drvdata); 449 + 450 + /* 451 + * According to software usage PKLXF in Arm ARM (ARM DDI 0487 L.a), 452 + * execute a Context synchronization event to guarantee the trace unit 453 + * will observe the new values of the System registers. 454 + */ 455 + if (!csa->io_mem) 456 + isb(); 457 + 449 458 /* Enable the trace unit */ 450 459 etm4x_relaxed_write32(csa, 1, TRCPRGCTLR); 451 460 452 - /* Synchronize the register updates for sysreg access */ 461 + /* 462 + * As recommended by section 4.3.7 ("Synchronization when using system 463 + * instructions to progrom the trace unit") of ARM IHI 0064H.b, the 464 + * self-hosted trace analyzer must perform a Context synchronization 465 + * event between writing to the TRCPRGCTLR and reading the TRCSTATR. 466 + */ 453 467 if (!csa->io_mem) 454 468 isb(); 455 469 ··· 475 461 } 476 462 477 463 /* 478 - * As recommended by section 4.3.7 ("Synchronization when using the 479 - * memory-mapped interface") of ARM IHI 0064D 464 + * As recommended in section 4.3.7 (Synchronization of register updates) 465 + * of ARM IHI 0064H.b, the self-hosted trace analyzer always executes an 466 + * ISB instruction after programming the trace unit registers. 467 + * 468 + * For the memory-mapped interface, the registers are mapped as Device 469 + * type (Device-nGnRE). Reading back the value of any register in the 470 + * trace unit ensures that all writes have completed. Therefore, polling 471 + * on TRCSTATR guarantees that the writing TRCPRGCTLR is complete, and 472 + * no explicit dsb() is required at here. 480 473 */ 481 - dsb(sy); 482 474 isb(); 483 475 484 476 return 0; ··· 609 589 return rc; 610 590 } 611 591 612 - static void etm4_enable_hw_smp_call(void *info) 592 + static void etm4_enable_sysfs_smp_call(void *info) 613 593 { 614 594 struct etm4_enable_arg *arg = info; 595 + struct coresight_device *csdev; 615 596 616 597 if (WARN_ON(!arg)) 617 598 return; 599 + 600 + csdev = arg->drvdata->csdev; 601 + if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) { 602 + /* Someone is already using the tracer */ 603 + arg->rc = -EBUSY; 604 + return; 605 + } 606 + 618 607 arg->rc = etm4_enable_hw(arg->drvdata); 608 + 609 + /* The tracer didn't start */ 610 + if (arg->rc) 611 + coresight_set_mode(csdev, CS_MODE_DISABLED); 619 612 } 620 613 621 614 /* ··· 841 808 struct perf_event *event, 842 809 struct coresight_path *path) 843 810 { 844 - int ret = 0; 845 811 struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 812 + int ret; 846 813 847 - if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) { 848 - ret = -EINVAL; 849 - goto out; 850 - } 814 + if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) 815 + return -EINVAL; 816 + 817 + if (!coresight_take_mode(csdev, CS_MODE_PERF)) 818 + return -EBUSY; 851 819 852 820 /* Configure the tracer based on the session's specifics */ 853 821 ret = etm4_parse_event_config(csdev, event); ··· 864 830 ret = etm4_enable_hw(drvdata); 865 831 866 832 out: 833 + /* Failed to start tracer; roll back to DISABLED mode */ 834 + if (ret) 835 + coresight_set_mode(csdev, CS_MODE_DISABLED); 867 836 return ret; 868 837 } 869 838 ··· 898 861 */ 899 862 arg.drvdata = drvdata; 900 863 ret = smp_call_function_single(drvdata->cpu, 901 - etm4_enable_hw_smp_call, &arg, 1); 864 + etm4_enable_sysfs_smp_call, &arg, 1); 902 865 if (!ret) 903 866 ret = arg.rc; 904 867 if (!ret) ··· 919 882 { 920 883 int ret; 921 884 922 - if (!coresight_take_mode(csdev, mode)) { 923 - /* Someone is already using the tracer */ 924 - return -EBUSY; 925 - } 926 - 927 885 switch (mode) { 928 886 case CS_MODE_SYSFS: 929 887 ret = etm4_enable_sysfs(csdev, path); ··· 929 897 default: 930 898 ret = -EINVAL; 931 899 } 932 - 933 - /* The tracer didn't start */ 934 - if (ret) 935 - coresight_set_mode(csdev, CS_MODE_DISABLED); 936 900 937 901 return ret; 938 902 } ··· 951 923 */ 952 924 etm4x_prohibit_trace(drvdata); 953 925 /* 954 - * Make sure everything completes before disabling, as recommended 955 - * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register, 956 - * SSTATUS") of ARM IHI 0064D 926 + * Prevent being speculative at the point of disabling the trace unit, 927 + * as recommended by section 7.3.77 ("TRCVICTLR, ViewInst Main Control 928 + * Register, SSTATUS") of ARM IHI 0064D 957 929 */ 958 930 dsb(sy); 931 + /* 932 + * According to software usage VKHHY in Arm ARM (ARM DDI 0487 L.a), 933 + * execute a Context synchronization event to guarantee no new 934 + * program-flow trace is generated. 935 + */ 959 936 isb(); 960 937 /* Trace synchronization barrier, is a nop if not supported */ 961 938 tsb_csync(); ··· 980 947 dev_err(etm_dev, 981 948 "timeout while waiting for PM stable Trace Status\n"); 982 949 /* 983 - * As recommended by section 4.3.7 (Synchronization of register updates) 984 - * of ARM IHI 0064H.b. 950 + * As recommended in section 4.3.7 (Synchronization of register updates) 951 + * of ARM IHI 0064H.b, the self-hosted trace analyzer always executes an 952 + * ISB instruction after programming the trace unit registers. 953 + * 954 + * For the memory-mapped interface, the registers are mapped as Device 955 + * type (Device-nGnRE). Reading back the value of any register in the 956 + * trace unit ensures that all writes have completed. Therefore, polling 957 + * on TRCSTATR guarantees that the writing TRCPRGCTLR is complete, and 958 + * no explicit dsb() is required at here. 985 959 */ 986 960 isb(); 987 961 } 988 962 989 - static void etm4_disable_hw(void *info) 963 + static void etm4_disable_hw(struct etmv4_drvdata *drvdata) 990 964 { 991 965 u32 control; 992 - struct etmv4_drvdata *drvdata = info; 993 966 struct etmv4_config *config = &drvdata->config; 994 967 struct coresight_device *csdev = drvdata->csdev; 995 968 struct csdev_access *csa = &csdev->access; ··· 1032 993 "cpu: %d disable smp call done\n", drvdata->cpu); 1033 994 } 1034 995 996 + static void etm4_disable_sysfs_smp_call(void *info) 997 + { 998 + struct etmv4_drvdata *drvdata = info; 999 + 1000 + etm4_disable_hw(drvdata); 1001 + 1002 + coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); 1003 + } 1004 + 1035 1005 static int etm4_disable_perf(struct coresight_device *csdev, 1036 1006 struct perf_event *event) 1037 1007 { ··· 1070 1022 /* TRCVICTLR::SSSTATUS, bit[9] */ 1071 1023 filters->ssstatus = (control & BIT(9)); 1072 1024 1025 + coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED); 1026 + 1073 1027 /* 1074 1028 * perf will release trace ids when _free_aux() is 1075 1029 * called at the end of the session. ··· 1097 1047 * Executing etm4_disable_hw on the cpu whose ETM is being disabled 1098 1048 * ensures that register writes occur when cpu is powered. 1099 1049 */ 1100 - smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1); 1050 + smp_call_function_single(drvdata->cpu, etm4_disable_sysfs_smp_call, 1051 + drvdata, 1); 1101 1052 1102 1053 raw_spin_unlock(&drvdata->spinlock); 1103 1054 ··· 1138 1087 etm4_disable_perf(csdev, event); 1139 1088 break; 1140 1089 } 1141 - 1142 - if (mode) 1143 - coresight_set_mode(csdev, CS_MODE_DISABLED); 1144 1090 } 1145 1091 1146 1092 static int etm4_resume_perf(struct coresight_device *csdev) ··· 1871 1823 goto out; 1872 1824 } 1873 1825 1826 + if (!drvdata->paused) 1827 + etm4_disable_trace_unit(drvdata); 1828 + 1874 1829 state = drvdata->save_state; 1875 1830 1876 - state->trcprgctlr = etm4x_read32(csa, TRCPRGCTLR); 1877 1831 if (drvdata->nr_pe) 1878 1832 state->trcprocselr = etm4x_read32(csa, TRCPROCSELR); 1879 1833 state->trcconfigr = etm4x_read32(csa, TRCCONFIGR); ··· 1958 1908 state->trcpdcr = etm4x_read32(csa, TRCPDCR); 1959 1909 1960 1910 /* wait for TRCSTATR.IDLE to go up */ 1961 - if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1)) { 1911 + if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 1)) { 1962 1912 dev_err(etm_dev, 1963 1913 "timeout while waiting for Idle Trace Status\n"); 1964 1914 etm4_os_unlock(drvdata); 1965 1915 ret = -EBUSY; 1966 1916 goto out; 1967 1917 } 1968 - 1969 - drvdata->state_needs_restore = true; 1970 1918 1971 1919 /* 1972 1920 * Power can be removed from the trace unit now. We do this to ··· 1983 1935 { 1984 1936 int ret = 0; 1985 1937 1986 - /* Save the TRFCR irrespective of whether the ETM is ON */ 1987 - if (drvdata->trfcr) 1988 - drvdata->save_trfcr = read_trfcr(); 1938 + if (pm_save_enable != PARAM_PM_SAVE_SELF_HOSTED) 1939 + return 0; 1940 + 1989 1941 /* 1990 1942 * Save and restore the ETM Trace registers only if 1991 1943 * the ETM is active. 1992 1944 */ 1993 - if (coresight_get_mode(drvdata->csdev) && drvdata->save_state) 1945 + if (coresight_get_mode(drvdata->csdev)) 1994 1946 ret = __etm4_cpu_save(drvdata); 1995 1947 return ret; 1996 1948 } ··· 2007 1959 etm4_cs_unlock(drvdata, csa); 2008 1960 etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET); 2009 1961 2010 - etm4x_relaxed_write32(csa, state->trcprgctlr, TRCPRGCTLR); 2011 1962 if (drvdata->nr_pe) 2012 1963 etm4x_relaxed_write32(csa, state->trcprocselr, TRCPROCSELR); 2013 1964 etm4x_relaxed_write32(csa, state->trcconfigr, TRCCONFIGR); ··· 2080 2033 if (!drvdata->skip_power_up) 2081 2034 etm4x_relaxed_write32(csa, state->trcpdcr, TRCPDCR); 2082 2035 2083 - drvdata->state_needs_restore = false; 2084 - 2085 2036 /* 2086 2037 * As recommended by section 4.3.7 ("Synchronization when using the 2087 2038 * memory-mapped interface") of ARM IHI 0064D ··· 2089 2044 2090 2045 /* Unlock the OS lock to re-enable trace and external debug access */ 2091 2046 etm4_os_unlock(drvdata); 2047 + 2048 + if (!drvdata->paused) 2049 + etm4_enable_trace_unit(drvdata); 2050 + 2092 2051 etm4_cs_lock(drvdata, csa); 2093 2052 } 2094 2053 2095 2054 static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) 2096 2055 { 2097 - if (drvdata->trfcr) 2098 - write_trfcr(drvdata->save_trfcr); 2099 - if (drvdata->state_needs_restore) 2056 + if (pm_save_enable != PARAM_PM_SAVE_SELF_HOSTED) 2057 + return; 2058 + 2059 + if (coresight_get_mode(drvdata->csdev)) 2100 2060 __etm4_cpu_restore(drvdata); 2101 2061 } 2102 2062
-5
drivers/hwtracing/coresight/coresight-etm4x.h
··· 866 866 * struct etm4_save_state - state to be preserved when ETM is without power 867 867 */ 868 868 struct etmv4_save_state { 869 - u32 trcprgctlr; 870 869 u32 trcprocselr; 871 870 u32 trcconfigr; 872 871 u32 trcauxctlr; ··· 979 980 * at runtime, due to the additional setting of TRFCR_CX when 980 981 * in EL2. Otherwise, 0. 981 982 * @config: structure holding configuration parameters. 982 - * @save_trfcr: Saved TRFCR_EL1 register during a CPU PM event. 983 983 * @save_state: State to be preserved across power loss 984 - * @state_needs_restore: True when there is context to restore after PM exit 985 984 * @skip_power_up: Indicates if an implementation can skip powering up 986 985 * the trace unit. 987 986 * @paused: Indicates if the trace unit is paused. ··· 1034 1037 bool lpoverride; 1035 1038 u64 trfcr; 1036 1039 struct etmv4_config config; 1037 - u64 save_trfcr; 1038 1040 struct etmv4_save_state *save_state; 1039 - bool state_needs_restore; 1040 1041 bool skip_power_up; 1041 1042 bool paused; 1042 1043 DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
+1 -2
drivers/hwtracing/coresight/coresight-priv.h
··· 135 135 } 136 136 137 137 void coresight_disable_path(struct coresight_path *path); 138 - int coresight_enable_path(struct coresight_path *path, enum cs_mode mode, 139 - void *sink_data); 138 + int coresight_enable_path(struct coresight_path *path, enum cs_mode mode); 140 139 struct coresight_device *coresight_get_sink(struct coresight_path *path); 141 140 struct coresight_device *coresight_get_sink_by_id(u32 id); 142 141 struct coresight_device *
+1 -1
drivers/hwtracing/coresight/coresight-sysfs.c
··· 215 215 if (!IS_VALID_CS_TRACE_ID(path->trace_id)) 216 216 goto err_path; 217 217 218 - ret = coresight_enable_path(path, CS_MODE_SYSFS, NULL); 218 + ret = coresight_enable_path(path, CS_MODE_SYSFS); 219 219 if (ret) 220 220 goto err_path; 221 221
+6 -4
drivers/hwtracing/coresight/coresight-tmc-etf.c
··· 246 246 return ret; 247 247 } 248 248 249 - static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) 249 + static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, 250 + struct coresight_path *path) 250 251 { 251 252 int ret = 0; 252 253 pid_t pid; 253 254 unsigned long flags; 254 255 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 255 - struct perf_output_handle *handle = data; 256 + struct perf_output_handle *handle = path->handle; 256 257 struct cs_buffers *buf = etm_perf_sink_config(handle); 257 258 258 259 raw_spin_lock_irqsave(&drvdata->spinlock, flags); ··· 305 304 } 306 305 307 306 static int tmc_enable_etf_sink(struct coresight_device *csdev, 308 - enum cs_mode mode, void *data) 307 + enum cs_mode mode, 308 + struct coresight_path *path) 309 309 { 310 310 int ret; 311 311 ··· 315 313 ret = tmc_enable_etf_sink_sysfs(csdev); 316 314 break; 317 315 case CS_MODE_PERF: 318 - ret = tmc_enable_etf_sink_perf(csdev, data); 316 + ret = tmc_enable_etf_sink_perf(csdev, path); 319 317 break; 320 318 /* We shouldn't be here */ 321 319 default:
+16 -6
drivers/hwtracing/coresight/coresight-tmc-etr.c
··· 1250 1250 * with the lock released. 1251 1251 */ 1252 1252 raw_spin_lock_irqsave(&drvdata->spinlock, flags); 1253 + 1254 + /* 1255 + * If the ETR is already enabled, continue with the existing buffer. 1256 + */ 1257 + if (coresight_get_mode(csdev) == CS_MODE_SYSFS) 1258 + goto out; 1259 + 1253 1260 sysfs_buf = READ_ONCE(drvdata->sysfs_buf); 1254 1261 if (!sysfs_buf || (sysfs_buf->size != drvdata->size)) { 1255 1262 raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); ··· 1332 1325 } 1333 1326 1334 1327 struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev, 1335 - enum cs_mode mode, void *data) 1328 + enum cs_mode mode, 1329 + struct coresight_path *path) 1336 1330 { 1337 - struct perf_output_handle *handle = data; 1331 + struct perf_output_handle *handle = path->handle; 1338 1332 struct etr_perf_buffer *etr_perf; 1339 1333 1340 1334 switch (mode) { ··· 1733 1725 return size; 1734 1726 } 1735 1727 1736 - static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) 1728 + static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, 1729 + struct coresight_path *path) 1737 1730 { 1738 1731 int rc = 0; 1739 1732 pid_t pid; 1740 1733 unsigned long flags; 1741 1734 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 1742 - struct perf_output_handle *handle = data; 1735 + struct perf_output_handle *handle = path->handle; 1743 1736 struct etr_perf_buffer *etr_perf = etm_perf_sink_config(handle); 1744 1737 1745 1738 raw_spin_lock_irqsave(&drvdata->spinlock, flags); ··· 1788 1779 } 1789 1780 1790 1781 static int tmc_enable_etr_sink(struct coresight_device *csdev, 1791 - enum cs_mode mode, void *data) 1782 + enum cs_mode mode, 1783 + struct coresight_path *path) 1792 1784 { 1793 1785 switch (mode) { 1794 1786 case CS_MODE_SYSFS: 1795 1787 return tmc_enable_etr_sink_sysfs(csdev); 1796 1788 case CS_MODE_PERF: 1797 - return tmc_enable_etr_sink_perf(csdev, data); 1789 + return tmc_enable_etr_sink_perf(csdev, path); 1798 1790 default: 1799 1791 return -EINVAL; 1800 1792 }
+2 -1
drivers/hwtracing/coresight/coresight-tmc.h
··· 442 442 void tmc_etr_set_catu_ops(const struct etr_buf_operations *catu); 443 443 void tmc_etr_remove_catu_ops(void); 444 444 struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev, 445 - enum cs_mode mode, void *data); 445 + enum cs_mode mode, 446 + struct coresight_path *path); 446 447 extern const struct attribute_group coresight_etr_group; 447 448 448 449 #endif
-7
drivers/hwtracing/coresight/coresight-tpda.c
··· 22 22 23 23 DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda"); 24 24 25 - static bool coresight_device_is_tpdm(struct coresight_device *csdev) 26 - { 27 - return (coresight_is_device_source(csdev)) && 28 - (csdev->subtype.source_subtype == 29 - CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM); 30 - } 31 - 32 25 static void tpda_clear_element_size(struct coresight_device *csdev) 33 26 { 34 27 struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+142 -32
drivers/hwtracing/coresight/coresight-tpdm.c
··· 470 470 */ 471 471 static void __tpdm_enable(struct tpdm_drvdata *drvdata) 472 472 { 473 + if (coresight_is_static_tpdm(drvdata->csdev)) 474 + return; 475 + 473 476 CS_UNLOCK(drvdata->base); 474 477 475 478 tpdm_enable_dsb(drvdata); ··· 535 532 /* TPDM disable operations */ 536 533 static void __tpdm_disable(struct tpdm_drvdata *drvdata) 537 534 { 535 + if (coresight_is_static_tpdm(drvdata->csdev)) 536 + return; 537 + 538 538 CS_UNLOCK(drvdata->base); 539 539 540 540 tpdm_disable_dsb(drvdata); ··· 597 591 } 598 592 599 593 tpdm_reset_datasets(drvdata); 594 + 595 + return 0; 596 + } 597 + 598 + static int static_tpdm_datasets_setup(struct tpdm_drvdata *drvdata, struct device *dev) 599 + { 600 + /* setup datasets for static TPDM */ 601 + if (fwnode_property_present(dev->fwnode, "qcom,dsb-element-bits") && 602 + (!drvdata->dsb)) { 603 + drvdata->dsb = devm_kzalloc(drvdata->dev, 604 + sizeof(*drvdata->dsb), GFP_KERNEL); 605 + 606 + if (!drvdata->dsb) 607 + return -ENOMEM; 608 + } 609 + 610 + if (fwnode_property_present(dev->fwnode, "qcom,cmb-element-bits") && 611 + (!drvdata->cmb)) { 612 + drvdata->cmb = devm_kzalloc(drvdata->dev, 613 + sizeof(*drvdata->cmb), GFP_KERNEL); 614 + 615 + if (!drvdata->cmb) 616 + return -ENOMEM; 617 + } 600 618 601 619 return 0; 602 620 } ··· 1372 1342 NULL, 1373 1343 }; 1374 1344 1375 - static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) 1345 + static int tpdm_probe(struct device *dev, struct resource *res) 1376 1346 { 1377 1347 void __iomem *base; 1378 - struct device *dev = &adev->dev; 1379 1348 struct coresight_platform_data *pdata; 1380 1349 struct tpdm_drvdata *drvdata; 1381 1350 struct coresight_desc desc = { 0 }; ··· 1383 1354 pdata = coresight_get_platform_data(dev); 1384 1355 if (IS_ERR(pdata)) 1385 1356 return PTR_ERR(pdata); 1386 - adev->dev.platform_data = pdata; 1357 + dev->platform_data = pdata; 1387 1358 1388 1359 /* driver data*/ 1389 1360 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); 1390 1361 if (!drvdata) 1391 1362 return -ENOMEM; 1392 - drvdata->dev = &adev->dev; 1363 + drvdata->dev = dev; 1393 1364 dev_set_drvdata(dev, drvdata); 1394 1365 1395 - base = devm_ioremap_resource(dev, &adev->res); 1396 - if (IS_ERR(base)) 1397 - return PTR_ERR(base); 1366 + if (res) { 1367 + base = devm_ioremap_resource(dev, res); 1368 + if (IS_ERR(base)) 1369 + return PTR_ERR(base); 1398 1370 1399 - drvdata->base = base; 1371 + drvdata->base = base; 1372 + ret = tpdm_datasets_setup(drvdata); 1373 + if (ret) 1374 + return ret; 1400 1375 1401 - ret = tpdm_datasets_setup(drvdata); 1402 - if (ret) 1403 - return ret; 1376 + if (tpdm_has_dsb_dataset(drvdata)) 1377 + of_property_read_u32(drvdata->dev->of_node, 1378 + "qcom,dsb-msrs-num", &drvdata->dsb_msr_num); 1404 1379 1405 - if (drvdata && tpdm_has_dsb_dataset(drvdata)) 1406 - of_property_read_u32(drvdata->dev->of_node, 1407 - "qcom,dsb-msrs-num", &drvdata->dsb_msr_num); 1408 - 1409 - if (drvdata && tpdm_has_cmb_dataset(drvdata)) 1410 - of_property_read_u32(drvdata->dev->of_node, 1411 - "qcom,cmb-msrs-num", &drvdata->cmb_msr_num); 1380 + if (tpdm_has_cmb_dataset(drvdata)) 1381 + of_property_read_u32(drvdata->dev->of_node, 1382 + "qcom,cmb-msrs-num", &drvdata->cmb_msr_num); 1383 + } else { 1384 + ret = static_tpdm_datasets_setup(drvdata, dev); 1385 + if (ret) 1386 + return ret; 1387 + } 1412 1388 1413 1389 /* Set up coresight component description */ 1414 1390 desc.name = coresight_alloc_device_name(&tpdm_devs, dev); ··· 1422 1388 desc.type = CORESIGHT_DEV_TYPE_SOURCE; 1423 1389 desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM; 1424 1390 desc.ops = &tpdm_cs_ops; 1425 - desc.pdata = adev->dev.platform_data; 1426 - desc.dev = &adev->dev; 1391 + desc.pdata = dev->platform_data; 1392 + desc.dev = dev; 1427 1393 desc.access = CSDEV_ACCESS_IOMEM(base); 1428 - desc.groups = tpdm_attr_grps; 1394 + if (res) 1395 + desc.groups = tpdm_attr_grps; 1429 1396 drvdata->csdev = coresight_register(&desc); 1430 1397 if (IS_ERR(drvdata->csdev)) 1431 1398 return PTR_ERR(drvdata->csdev); 1432 1399 1433 1400 spin_lock_init(&drvdata->spinlock); 1434 1401 1435 - /* Decrease pm refcount when probe is done.*/ 1436 - pm_runtime_put(&adev->dev); 1402 + return 0; 1403 + } 1404 + 1405 + static int tpdm_remove(struct device *dev) 1406 + { 1407 + struct tpdm_drvdata *drvdata = dev_get_drvdata(dev); 1408 + 1409 + coresight_unregister(drvdata->csdev); 1437 1410 1438 1411 return 0; 1439 1412 } 1440 1413 1441 - static void tpdm_remove(struct amba_device *adev) 1414 + static int dynamic_tpdm_probe(struct amba_device *adev, 1415 + const struct amba_id *id) 1442 1416 { 1443 - struct tpdm_drvdata *drvdata = dev_get_drvdata(&adev->dev); 1417 + int ret; 1444 1418 1445 - coresight_unregister(drvdata->csdev); 1419 + ret = tpdm_probe(&adev->dev, &adev->res); 1420 + if (!ret) 1421 + pm_runtime_put(&adev->dev); 1422 + 1423 + return ret; 1424 + } 1425 + 1426 + static void dynamic_tpdm_remove(struct amba_device *adev) 1427 + { 1428 + tpdm_remove(&adev->dev); 1446 1429 } 1447 1430 1448 1431 /* 1449 1432 * Different TPDM has different periph id. 1450 1433 * The difference is 0-7 bits' value. So ignore 0-7 bits. 1451 1434 */ 1452 - static const struct amba_id tpdm_ids[] = { 1435 + static const struct amba_id dynamic_tpdm_ids[] = { 1453 1436 { 1454 1437 .id = 0x001f0e00, 1455 1438 .mask = 0x00ffff00, ··· 1474 1423 { 0, 0, NULL }, 1475 1424 }; 1476 1425 1477 - static struct amba_driver tpdm_driver = { 1426 + MODULE_DEVICE_TABLE(amba, dynamic_tpdm_ids); 1427 + 1428 + static struct amba_driver dynamic_tpdm_driver = { 1478 1429 .drv = { 1479 1430 .name = "coresight-tpdm", 1480 1431 .suppress_bind_attrs = true, 1481 1432 }, 1482 - .probe = tpdm_probe, 1483 - .id_table = tpdm_ids, 1484 - .remove = tpdm_remove, 1433 + .probe = dynamic_tpdm_probe, 1434 + .id_table = dynamic_tpdm_ids, 1435 + .remove = dynamic_tpdm_remove, 1485 1436 }; 1486 1437 1487 - module_amba_driver(tpdm_driver); 1438 + static int tpdm_platform_probe(struct platform_device *pdev) 1439 + { 1440 + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1441 + int ret; 1442 + 1443 + pm_runtime_get_noresume(&pdev->dev); 1444 + pm_runtime_set_active(&pdev->dev); 1445 + pm_runtime_enable(&pdev->dev); 1446 + 1447 + ret = tpdm_probe(&pdev->dev, res); 1448 + pm_runtime_put(&pdev->dev); 1449 + if (ret) 1450 + pm_runtime_disable(&pdev->dev); 1451 + 1452 + return ret; 1453 + } 1454 + 1455 + static void tpdm_platform_remove(struct platform_device *pdev) 1456 + { 1457 + struct tpdm_drvdata *drvdata = dev_get_drvdata(&pdev->dev); 1458 + 1459 + if (WARN_ON(!drvdata)) 1460 + return; 1461 + 1462 + tpdm_remove(&pdev->dev); 1463 + pm_runtime_disable(&pdev->dev); 1464 + } 1465 + 1466 + static const struct of_device_id static_tpdm_match[] = { 1467 + {.compatible = "qcom,coresight-static-tpdm"}, 1468 + {} 1469 + }; 1470 + 1471 + MODULE_DEVICE_TABLE(of, static_tpdm_match); 1472 + 1473 + static struct platform_driver static_tpdm_driver = { 1474 + .probe = tpdm_platform_probe, 1475 + .remove = tpdm_platform_remove, 1476 + .driver = { 1477 + .name = "coresight-static-tpdm", 1478 + .of_match_table = static_tpdm_match, 1479 + .suppress_bind_attrs = true, 1480 + }, 1481 + }; 1482 + 1483 + static int __init tpdm_init(void) 1484 + { 1485 + return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver, 1486 + THIS_MODULE); 1487 + } 1488 + 1489 + static void __exit tpdm_exit(void) 1490 + { 1491 + coresight_remove_driver(&dynamic_tpdm_driver, &static_tpdm_driver); 1492 + } 1493 + 1494 + module_init(tpdm_init); 1495 + module_exit(tpdm_exit); 1488 1496 1489 1497 MODULE_LICENSE("GPL"); 1490 1498 MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");
+12
drivers/hwtracing/coresight/coresight-tpdm.h
··· 343 343 enum dataset_mem mem; 344 344 u32 idx; 345 345 }; 346 + 347 + static inline bool coresight_device_is_tpdm(struct coresight_device *csdev) 348 + { 349 + return (coresight_is_device_source(csdev)) && 350 + (csdev->subtype.source_subtype == 351 + CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM); 352 + } 353 + 354 + static inline bool coresight_is_static_tpdm(struct coresight_device *csdev) 355 + { 356 + return (coresight_device_is_tpdm(csdev) && !csdev->access.base); 357 + } 346 358 #endif /* _CORESIGHT_CORESIGHT_TPDM_H */
+1 -1
drivers/hwtracing/coresight/coresight-tpiu.c
··· 75 75 } 76 76 77 77 static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode, 78 - void *__unused) 78 + struct coresight_path *path) 79 79 { 80 80 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 81 81
+2 -2
drivers/hwtracing/coresight/coresight-trbe.c
··· 1013 1013 } 1014 1014 1015 1015 static int arm_trbe_enable(struct coresight_device *csdev, enum cs_mode mode, 1016 - void *data) 1016 + struct coresight_path *path) 1017 1017 { 1018 1018 struct trbe_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 1019 1019 struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev); 1020 - struct perf_output_handle *handle = data; 1020 + struct perf_output_handle *handle = path->handle; 1021 1021 struct trbe_buf *buf = etm_perf_sink_config(handle); 1022 1022 1023 1023 WARN_ON(cpudata->cpu != smp_processor_id());
+5 -4
drivers/hwtracing/coresight/ultrasoc-smb.c
··· 213 213 coresight_set_mode(csdev, CS_MODE_SYSFS); 214 214 } 215 215 216 - static int smb_enable_perf(struct coresight_device *csdev, void *data) 216 + static int smb_enable_perf(struct coresight_device *csdev, 217 + struct coresight_path *path) 217 218 { 218 219 struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent); 219 - struct perf_output_handle *handle = data; 220 + struct perf_output_handle *handle = path->handle; 220 221 struct cs_buffers *buf = etm_perf_sink_config(handle); 221 222 pid_t pid; 222 223 ··· 241 240 } 242 241 243 242 static int smb_enable(struct coresight_device *csdev, enum cs_mode mode, 244 - void *data) 243 + struct coresight_path *path) 245 244 { 246 245 struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent); 247 246 int ret = 0; ··· 262 261 smb_enable_sysfs(csdev); 263 262 break; 264 263 case CS_MODE_PERF: 265 - ret = smb_enable_perf(csdev, data); 264 + ret = smb_enable_perf(csdev, path); 266 265 break; 267 266 default: 268 267 ret = -EINVAL;
+21 -21
include/linux/coresight.h
··· 251 251 * by @coresight_ops. 252 252 * @access: Device i/o access abstraction for this device. 253 253 * @dev: The device entity associated to this component. 254 - * @mode: This tracer's mode, i.e sysFS, Perf or disabled. This is 255 - * actually an 'enum cs_mode', but is stored in an atomic type. 256 - * This is always accessed through local_read() and local_set(), 257 - * but wherever it's done from within the Coresight device's lock, 258 - * a non-atomic read would also work. This is the main point of 259 - * synchronisation between code happening inside the sysfs mode's 260 - * coresight_mutex and outside when running in Perf mode. A compare 261 - * and exchange swap is done to atomically claim one mode or the 262 - * other. 254 + * @mode: The device mode, i.e sysFS, Perf or disabled. This is actually 255 + * an 'enum cs_mode' but stored in an atomic type. Access is always 256 + * through atomic APIs, ensuring SMP-safe synchronisation between 257 + * racing from sysFS and Perf mode. A compare-and-exchange 258 + * operation is done to atomically claim one mode or the other. 263 259 * @refcnt: keep track of what is in use. Only access this outside of the 264 260 * device's spinlock when the coresight_mutex held and mode == 265 261 * CS_MODE_SYSFS. Otherwise it must be accessed from inside the ··· 284 288 const struct coresight_ops *ops; 285 289 struct csdev_access access; 286 290 struct device dev; 287 - local_t mode; 291 + atomic_t mode; 288 292 int refcnt; 289 293 bool orphan; 290 294 /* sink specific fields */ ··· 328 332 329 333 /** 330 334 * struct coresight_path - data needed by enable/disable path 331 - * @path_list: path from source to sink. 332 - * @trace_id: trace_id of the whole path. 335 + * @path_list: path from source to sink. 336 + * @trace_id: trace_id of the whole path. 337 + * @handle: handle of the aux_event. 333 338 */ 334 339 struct coresight_path { 335 - struct list_head path_list; 336 - u8 trace_id; 340 + struct list_head path_list; 341 + u8 trace_id; 342 + struct perf_output_handle *handle; 337 343 }; 338 344 339 345 enum cs_mode { ··· 363 365 */ 364 366 struct coresight_ops_sink { 365 367 int (*enable)(struct coresight_device *csdev, enum cs_mode mode, 366 - void *data); 368 + struct coresight_path *path); 367 369 int (*disable)(struct coresight_device *csdev); 368 370 void *(*alloc_buffer)(struct coresight_device *csdev, 369 371 struct perf_event *event, void **pages, ··· 420 422 */ 421 423 struct coresight_ops_helper { 422 424 int (*enable)(struct coresight_device *csdev, enum cs_mode mode, 423 - void *data); 424 - int (*disable)(struct coresight_device *csdev, void *data); 425 + struct coresight_path *path); 426 + int (*disable)(struct coresight_device *csdev, 427 + struct coresight_path *path); 425 428 }; 426 429 427 430 ··· 620 621 static inline bool coresight_take_mode(struct coresight_device *csdev, 621 622 enum cs_mode new_mode) 622 623 { 623 - return local_cmpxchg(&csdev->mode, CS_MODE_DISABLED, new_mode) == 624 - CS_MODE_DISABLED; 624 + int curr = CS_MODE_DISABLED; 625 + 626 + return atomic_try_cmpxchg_acquire(&csdev->mode, &curr, new_mode); 625 627 } 626 628 627 629 static inline enum cs_mode coresight_get_mode(struct coresight_device *csdev) 628 630 { 629 - return local_read(&csdev->mode); 631 + return atomic_read_acquire(&csdev->mode); 630 632 } 631 633 632 634 static inline void coresight_set_mode(struct coresight_device *csdev, ··· 643 643 WARN(new_mode != CS_MODE_DISABLED && current_mode != CS_MODE_DISABLED && 644 644 current_mode != new_mode, "Device already in use\n"); 645 645 646 - local_set(&csdev->mode, new_mode); 646 + atomic_set_release(&csdev->mode, new_mode); 647 647 } 648 648 649 649 struct coresight_device *coresight_register(struct coresight_desc *desc);