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.

coresight: Refactor etm4_config_timestamp_event()

Remove some of the magic numbers and try to clarify some of the
documentation so it's clearer how this sets up the timestamp interval.

Return errors directly instead of jumping to out and returning ret,
nothing needs to be cleaned up at the end and it only obscures the flow
and return value.

Add utilities for programming resource selectors that do compile time
checks for constants or WARN_ONs for non-constant values. FIELD_PREP
includes compile time checks so we only need to add an additional
BUILD_BUG_ON for resource == 0 in pair mode.

Tested-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20251128-james-cs-syncfreq-v8-3-4d319764cc58@linaro.org

authored by

James Clark and committed by
Suzuki K Poulose
b02450de 38f4c427

+112 -38
+63 -33
drivers/hwtracing/coresight/coresight-etm4x-core.c
··· 642 642 * TRCRSCTLR1 (always true) used to get the counter to decrement. From 643 643 * there a resource selector is configured with the counter and the 644 644 * timestamp control register to use the resource selector to trigger the 645 - * event that will insert a timestamp packet in the stream. 645 + * event that will insert a timestamp packet in the stream: 646 + * 647 + * +--------------+ 648 + * | Resource 1 | fixed "always-true" resource 649 + * +--------------+ 650 + * | 651 + * +------v-------+ 652 + * | Counter x | (reload to 1 on underflow) 653 + * +--------------+ 654 + * | 655 + * +------v--------------+ 656 + * | Resource Selector y | (trigger on counter x == 0) 657 + * +---------------------+ 658 + * | 659 + * +------v---------------+ 660 + * | Timestamp Generator | (timestamp on resource y) 661 + * +----------------------+ 646 662 */ 647 663 static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata) 648 664 { 649 - int ctridx, ret = -EINVAL; 650 - int counter, rselector; 651 - u32 val = 0; 665 + int ctridx; 666 + int rselector; 652 667 struct etmv4_config *config = &drvdata->config; 653 668 654 669 /* No point in trying if we don't have at least one counter */ 655 670 if (!drvdata->nr_cntr) 656 - goto out; 671 + return -EINVAL; 657 672 658 673 /* Find a counter that hasn't been initialised */ 659 674 for (ctridx = 0; ctridx < drvdata->nr_cntr; ctridx++) ··· 678 663 /* All the counters have been configured already, bail out */ 679 664 if (ctridx == drvdata->nr_cntr) { 680 665 pr_debug("%s: no available counter found\n", __func__); 681 - ret = -ENOSPC; 682 - goto out; 666 + return -ENOSPC; 683 667 } 684 668 685 669 /* 686 - * Searching for an available resource selector to use, starting at 687 - * '2' since every implementation has at least 2 resource selector. 688 - * ETMIDR4 gives the number of resource selector _pairs_, 689 - * hence multiply by 2. 670 + * Searching for an available resource selector to use, starting at '2' 671 + * since resource 0 is the fixed 'always returns false' resource and 1 672 + * is the fixed 'always returns true' resource. See IHI0064H_b '7.3.64 673 + * TRCRSCTLRn, Resource Selection Control Registers, n=2-31'. If there 674 + * are no resources, there would also be no counters so wouldn't get 675 + * here. 676 + * 677 + * ETMIDR4 gives the number of resource selector _pairs_, hence multiply 678 + * by 2. 690 679 */ 691 680 for (rselector = 2; rselector < drvdata->nr_resource * 2; rselector++) 692 681 if (!config->res_ctrl[rselector]) ··· 699 680 if (rselector == drvdata->nr_resource * 2) { 700 681 pr_debug("%s: no available resource selector found\n", 701 682 __func__); 702 - ret = -ENOSPC; 703 - goto out; 683 + return -ENOSPC; 704 684 } 705 - 706 - /* Remember what counter we used */ 707 - counter = 1 << ctridx; 708 685 709 686 /* 710 687 * Initialise original and reload counter value to the smallest ··· 709 694 config->cntr_val[ctridx] = 1; 710 695 config->cntrldvr[ctridx] = 1; 711 696 712 - /* Set the trace counter control register */ 713 - val = 0x1 << 16 | /* Bit 16, reload counter automatically */ 714 - 0x0 << 7 | /* Select single resource selector */ 715 - 0x1; /* Resource selector 1, i.e always true */ 697 + /* 698 + * Trace Counter Control Register TRCCNTCTLRn 699 + * 700 + * CNTCHAIN = 0, don't reload on the previous counter 701 + * RLDSELF = true, reload counter automatically on underflow 702 + * RLDEVENT = RES_SEL_FALSE (0), reload on single false resource (never reload) 703 + * CNTEVENT = RES_SEL_TRUE (1), count single fixed 'always true' resource (always decrement) 704 + */ 705 + config->cntr_ctrl[ctridx] = TRCCNTCTLRn_RLDSELF | 706 + FIELD_PREP(TRCCNTCTLRn_RLDEVENT_MASK, 707 + etm4_res_sel_single(ETM4_RES_SEL_FALSE)) | 708 + FIELD_PREP(TRCCNTCTLRn_CNTEVENT_MASK, 709 + etm4_res_sel_single(ETM4_RES_SEL_TRUE)); 716 710 717 - config->cntr_ctrl[ctridx] = val; 711 + /* 712 + * Resource Selection Control Register TRCRSCTLRn 713 + * 714 + * PAIRINV = 0, INV = 0, don't invert 715 + * GROUP = 2, SELECT = ctridx, trigger when counter 'ctridx' reaches 0 716 + * 717 + * Multiple counters can be selected, and each bit signifies a counter, 718 + * so set bit 'ctridx' to select our counter. 719 + */ 720 + config->res_ctrl[rselector] = FIELD_PREP(TRCRSCTLRn_GROUP_MASK, 2) | 721 + FIELD_PREP(TRCRSCTLRn_SELECT_MASK, 1 << ctridx); 718 722 719 - val = 0x2 << 16 | /* Group 0b0010 - Counter and sequencers */ 720 - counter << 0; /* Counter to use */ 723 + /* 724 + * Global Timestamp Control Register TRCTSCTLR 725 + * 726 + * EVENT = generate timestamp on single resource 'rselector' 727 + */ 728 + config->ts_ctrl = FIELD_PREP(TRCTSCTLR_EVENT_MASK, 729 + etm4_res_sel_single(rselector)); 721 730 722 - config->res_ctrl[rselector] = val; 723 - 724 - val = 0x0 << 7 | /* Select single resource selector */ 725 - rselector; /* Resource selector */ 726 - 727 - config->ts_ctrl = val; 728 - 729 - ret = 0; 730 - out: 731 - return ret; 731 + return 0; 732 732 } 733 733 734 734 static int etm4_parse_event_config(struct coresight_device *csdev,
+49 -5
drivers/hwtracing/coresight/coresight-etm4x.h
··· 225 225 #define TRCRSCTLRn_GROUP_MASK GENMASK(19, 16) 226 226 #define TRCRSCTLRn_SELECT_MASK GENMASK(15, 0) 227 227 228 + #define TRCCNTCTLRn_CNTCHAIN BIT(17) 229 + #define TRCCNTCTLRn_RLDSELF BIT(16) 230 + #define TRCCNTCTLRn_RLDEVENT_MASK GENMASK(15, 8) 231 + #define TRCCNTCTLRn_CNTEVENT_MASK GENMASK(7, 0) 232 + 233 + #define TRCTSCTLR_EVENT_MASK GENMASK(7, 0) 234 + 235 + #define ETM4_RES_SEL_FALSE 0 /* Fixed function 'always false' resource selector */ 236 + #define ETM4_RES_SEL_TRUE 1 /* Fixed function 'always true' resource selector */ 237 + 238 + #define ETM4_RES_SEL_SINGLE_MASK GENMASK(4, 0) 239 + #define ETM4_RES_SEL_PAIR_MASK GENMASK(3, 0) 240 + #define ETM4_RES_SEL_TYPE_PAIR BIT(7) 241 + 242 + /* 243 + * Utilities for programming EVENT resource selectors, e.g. TRCCNTCTLRn_RLDEVENT. 244 + * 245 + * Resource selectors have a common format across registers: 246 + * 247 + * 7 6 5 4 0 248 + * +------+------+-------+ 249 + * | TYPE | RES0 | SEL | 250 + * +------+------+-------+ 251 + * 252 + * Where TYPE indicates whether the selector is for a single event or a pair. 253 + * When TYPE is pair, SEL is 4 bits wide and using pair 0 is UNPREDICTABLE. 254 + * Otherwise for single it's 5 bits wide. 255 + */ 256 + static inline u32 etm4_res_sel_single(u8 res_sel_idx) 257 + { 258 + WARN_ON_ONCE(!FIELD_FIT(ETM4_RES_SEL_SINGLE_MASK, res_sel_idx)); 259 + return FIELD_PREP(ETM4_RES_SEL_SINGLE_MASK, res_sel_idx); 260 + } 261 + 262 + static inline u32 etm4_res_sel_pair(u8 res_sel_idx) 263 + { 264 + if (__builtin_constant_p(res_sel_idx)) 265 + BUILD_BUG_ON(res_sel_idx == 0); 266 + WARN_ON_ONCE(!FIELD_FIT(ETM4_RES_SEL_PAIR_MASK, res_sel_idx) || 267 + (res_sel_idx == 0)); 268 + return FIELD_PREP(ETM4_RES_SEL_PAIR_MASK, res_sel_idx) | 269 + ETM4_RES_SEL_TYPE_PAIR; 270 + } 271 + 228 272 /* 229 273 * System instructions to access ETM registers. 230 274 * See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions ··· 868 824 u32 eventctrl0; 869 825 u32 eventctrl1; 870 826 u32 stall_ctrl; 871 - u32 ts_ctrl; 827 + u32 ts_ctrl; /* TRCTSCTLR */ 872 828 u32 ccctlr; 873 829 u32 bb_ctrl; 874 830 u32 vinst_ctrl; ··· 881 837 u32 seq_rst; 882 838 u32 seq_state; 883 839 u8 cntr_idx; 884 - u32 cntrldvr[ETMv4_MAX_CNTR]; 885 - u32 cntr_ctrl[ETMv4_MAX_CNTR]; 886 - u32 cntr_val[ETMv4_MAX_CNTR]; 840 + u32 cntrldvr[ETMv4_MAX_CNTR]; /* TRCCNTRLDVRn */ 841 + u32 cntr_ctrl[ETMv4_MAX_CNTR]; /* TRCCNTCTLRn */ 842 + u32 cntr_val[ETMv4_MAX_CNTR]; /* TRCCNTVRn */ 887 843 u8 res_idx; 888 - u32 res_ctrl[ETM_MAX_RES_SEL]; 844 + u32 res_ctrl[ETM_MAX_RES_SEL]; /* TRCRSCTLRn */ 889 845 u8 ss_idx; 890 846 u32 ss_ctrl[ETM_MAX_SS_CMP]; 891 847 u32 ss_status[ETM_MAX_SS_CMP];