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

drivers/perf: hisi: Refactor the event configuration of L3C PMU

The event register is configured using hisi_pmu::base directly since
only one address space is supported for L3C PMU. We need to extend if
events configuration locates in different address space. In order to
make preparation for such hardware, extract the event register
configuration to separate function using hw_perf_event::event_base as
each event's base address. Implement a private
hisi_uncore_ops::get_event_idx() callback for initialize the event_base
besides get the hardware index.

No functional changes intended.

Acked-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Yicong Yang and committed by
Will Deacon
b3abb08d ede339ff

+84 -45
+84 -45
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
··· 60 60 HISI_PMU_EVENT_ATTR_EXTRACTOR(datasrc_skt, config1, 16, 16); 61 61 HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_core, config2, 15, 0); 62 62 63 - static void hisi_l3c_pmu_config_req_tracetag(struct perf_event *event) 63 + static int hisi_l3c_pmu_get_event_idx(struct perf_event *event) 64 64 { 65 65 struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); 66 + unsigned long *used_mask = l3c_pmu->pmu_events.used_mask; 67 + u32 num_counters = l3c_pmu->num_counters; 68 + int idx; 69 + 70 + idx = find_first_zero_bit(used_mask, num_counters); 71 + if (idx == num_counters) 72 + return -EAGAIN; 73 + 74 + set_bit(idx, used_mask); 75 + event->hw.event_base = (unsigned long)l3c_pmu->base; 76 + 77 + return idx; 78 + } 79 + 80 + static u32 hisi_l3c_pmu_event_readl(struct hw_perf_event *hwc, u32 reg) 81 + { 82 + return readl((void __iomem *)hwc->event_base + reg); 83 + } 84 + 85 + static void hisi_l3c_pmu_event_writel(struct hw_perf_event *hwc, u32 reg, u32 val) 86 + { 87 + writel(val, (void __iomem *)hwc->event_base + reg); 88 + } 89 + 90 + static u64 hisi_l3c_pmu_event_readq(struct hw_perf_event *hwc, u32 reg) 91 + { 92 + return readq((void __iomem *)hwc->event_base + reg); 93 + } 94 + 95 + static void hisi_l3c_pmu_event_writeq(struct hw_perf_event *hwc, u32 reg, u64 val) 96 + { 97 + writeq(val, (void __iomem *)hwc->event_base + reg); 98 + } 99 + 100 + static void hisi_l3c_pmu_config_req_tracetag(struct perf_event *event) 101 + { 102 + struct hw_perf_event *hwc = &event->hw; 66 103 u32 tt_req = hisi_get_tt_req(event); 67 104 68 105 if (tt_req) { 69 106 u32 val; 70 107 71 108 /* Set request-type for tracetag */ 72 - val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL); 109 + val = hisi_l3c_pmu_event_readl(hwc, L3C_TRACETAG_CTRL); 73 110 val |= tt_req << L3C_TRACETAG_REQ_SHIFT; 74 111 val |= L3C_TRACETAG_REQ_EN; 75 - writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL); 112 + hisi_l3c_pmu_event_writel(hwc, L3C_TRACETAG_CTRL, val); 76 113 77 114 /* Enable request-tracetag statistics */ 78 - val = readl(l3c_pmu->base + L3C_PERF_CTRL); 115 + val = hisi_l3c_pmu_event_readl(hwc, L3C_PERF_CTRL); 79 116 val |= L3C_TRACETAG_EN; 80 - writel(val, l3c_pmu->base + L3C_PERF_CTRL); 117 + hisi_l3c_pmu_event_writel(hwc, L3C_PERF_CTRL, val); 81 118 } 82 119 } 83 120 84 121 static void hisi_l3c_pmu_clear_req_tracetag(struct perf_event *event) 85 122 { 86 - struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); 123 + struct hw_perf_event *hwc = &event->hw; 87 124 u32 tt_req = hisi_get_tt_req(event); 88 125 89 126 if (tt_req) { 90 127 u32 val; 91 128 92 129 /* Clear request-type */ 93 - val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL); 130 + val = hisi_l3c_pmu_event_readl(hwc, L3C_TRACETAG_CTRL); 94 131 val &= ~(tt_req << L3C_TRACETAG_REQ_SHIFT); 95 132 val &= ~L3C_TRACETAG_REQ_EN; 96 - writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL); 133 + hisi_l3c_pmu_event_writel(hwc, L3C_TRACETAG_CTRL, val); 97 134 98 135 /* Disable request-tracetag statistics */ 99 - val = readl(l3c_pmu->base + L3C_PERF_CTRL); 136 + val = hisi_l3c_pmu_event_readl(hwc, L3C_PERF_CTRL); 100 137 val &= ~L3C_TRACETAG_EN; 101 - writel(val, l3c_pmu->base + L3C_PERF_CTRL); 138 + hisi_l3c_pmu_event_writel(hwc, L3C_PERF_CTRL, val); 102 139 } 103 140 } 104 141 105 142 static void hisi_l3c_pmu_write_ds(struct perf_event *event, u32 ds_cfg) 106 143 { 107 - struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); 108 144 struct hw_perf_event *hwc = &event->hw; 109 145 u32 reg, reg_idx, shift, val; 110 146 int idx = hwc->idx; ··· 156 120 reg_idx = idx % 4; 157 121 shift = 8 * reg_idx; 158 122 159 - val = readl(l3c_pmu->base + reg); 123 + val = hisi_l3c_pmu_event_readl(hwc, reg); 160 124 val &= ~(L3C_DATSRC_MASK << shift); 161 125 val |= ds_cfg << shift; 162 - writel(val, l3c_pmu->base + reg); 126 + hisi_l3c_pmu_event_writel(hwc, reg, val); 163 127 } 164 128 165 129 static void hisi_l3c_pmu_config_ds(struct perf_event *event) 166 130 { 167 - struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); 131 + struct hw_perf_event *hwc = &event->hw; 168 132 u32 ds_cfg = hisi_get_datasrc_cfg(event); 169 133 u32 ds_skt = hisi_get_datasrc_skt(event); 170 134 ··· 174 138 if (ds_skt) { 175 139 u32 val; 176 140 177 - val = readl(l3c_pmu->base + L3C_DATSRC_CTRL); 141 + val = hisi_l3c_pmu_event_readl(hwc, L3C_DATSRC_CTRL); 178 142 val |= L3C_DATSRC_SKT_EN; 179 - writel(val, l3c_pmu->base + L3C_DATSRC_CTRL); 143 + hisi_l3c_pmu_event_writel(hwc, L3C_DATSRC_CTRL, val); 180 144 } 181 145 } 182 146 183 147 static void hisi_l3c_pmu_clear_ds(struct perf_event *event) 184 148 { 185 - struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); 149 + struct hw_perf_event *hwc = &event->hw; 186 150 u32 ds_cfg = hisi_get_datasrc_cfg(event); 187 151 u32 ds_skt = hisi_get_datasrc_skt(event); 188 152 ··· 192 156 if (ds_skt) { 193 157 u32 val; 194 158 195 - val = readl(l3c_pmu->base + L3C_DATSRC_CTRL); 159 + val = hisi_l3c_pmu_event_readl(hwc, L3C_DATSRC_CTRL); 196 160 val &= ~L3C_DATSRC_SKT_EN; 197 - writel(val, l3c_pmu->base + L3C_DATSRC_CTRL); 161 + hisi_l3c_pmu_event_writel(hwc, L3C_DATSRC_CTRL, val); 198 162 } 199 163 } 200 164 201 165 static void hisi_l3c_pmu_config_core_tracetag(struct perf_event *event) 202 166 { 203 - struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); 167 + struct hw_perf_event *hwc = &event->hw; 204 168 u32 core = hisi_get_tt_core(event); 205 169 206 170 if (core) { 207 171 u32 val; 208 172 209 173 /* Config and enable core information */ 210 - writel(core, l3c_pmu->base + L3C_CORE_CTRL); 211 - val = readl(l3c_pmu->base + L3C_PERF_CTRL); 174 + hisi_l3c_pmu_event_writel(hwc, L3C_CORE_CTRL, core); 175 + val = hisi_l3c_pmu_event_readl(hwc, L3C_PERF_CTRL); 212 176 val |= L3C_CORE_EN; 213 - writel(val, l3c_pmu->base + L3C_PERF_CTRL); 177 + hisi_l3c_pmu_event_writel(hwc, L3C_PERF_CTRL, val); 214 178 215 179 /* Enable core-tracetag statistics */ 216 - val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL); 180 + val = hisi_l3c_pmu_event_readl(hwc, L3C_TRACETAG_CTRL); 217 181 val |= L3C_TRACETAG_CORE_EN; 218 - writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL); 182 + hisi_l3c_pmu_event_writel(hwc, L3C_TRACETAG_CTRL, val); 219 183 } 220 184 } 221 185 222 186 static void hisi_l3c_pmu_clear_core_tracetag(struct perf_event *event) 223 187 { 224 - struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); 188 + struct hw_perf_event *hwc = &event->hw; 225 189 u32 core = hisi_get_tt_core(event); 226 190 227 191 if (core) { 228 192 u32 val; 229 193 230 194 /* Clear core information */ 231 - writel(L3C_COER_NONE, l3c_pmu->base + L3C_CORE_CTRL); 232 - val = readl(l3c_pmu->base + L3C_PERF_CTRL); 195 + hisi_l3c_pmu_event_writel(hwc, L3C_CORE_CTRL, L3C_COER_NONE); 196 + val = hisi_l3c_pmu_event_readl(hwc, L3C_PERF_CTRL); 233 197 val &= ~L3C_CORE_EN; 234 - writel(val, l3c_pmu->base + L3C_PERF_CTRL); 198 + hisi_l3c_pmu_event_writel(hwc, L3C_PERF_CTRL, val); 235 199 236 200 /* Disable core-tracetag statistics */ 237 - val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL); 201 + val = hisi_l3c_pmu_event_readl(hwc, L3C_TRACETAG_CTRL); 238 202 val &= ~L3C_TRACETAG_CORE_EN; 239 - writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL); 203 + hisi_l3c_pmu_event_writel(hwc, L3C_TRACETAG_CTRL, val); 240 204 } 241 205 } 242 206 ··· 275 239 static u64 hisi_l3c_pmu_read_counter(struct hisi_pmu *l3c_pmu, 276 240 struct hw_perf_event *hwc) 277 241 { 278 - return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx)); 242 + return hisi_l3c_pmu_event_readq(hwc, hisi_l3c_pmu_get_counter_offset(hwc->idx)); 279 243 } 280 244 281 245 static void hisi_l3c_pmu_write_counter(struct hisi_pmu *l3c_pmu, 282 246 struct hw_perf_event *hwc, u64 val) 283 247 { 284 - writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx)); 248 + hisi_l3c_pmu_event_writeq(hwc, hisi_l3c_pmu_get_counter_offset(hwc->idx), val); 285 249 } 286 250 287 251 static void hisi_l3c_pmu_write_evtype(struct hisi_pmu *l3c_pmu, int idx, 288 252 u32 type) 289 253 { 254 + struct hw_perf_event *hwc = &l3c_pmu->pmu_events.hw_events[idx]->hw; 290 255 u32 reg, reg_idx, shift, val; 291 256 292 257 /* ··· 302 265 shift = 8 * reg_idx; 303 266 304 267 /* Write event code to L3C_EVENT_TYPEx Register */ 305 - val = readl(l3c_pmu->base + reg); 268 + val = hisi_l3c_pmu_event_readl(hwc, reg); 306 269 val &= ~(L3C_EVTYPE_NONE << shift); 307 270 val |= (type << shift); 308 - writel(val, l3c_pmu->base + reg); 271 + hisi_l3c_pmu_event_writel(hwc, reg, val); 309 272 } 310 273 311 274 static void hisi_l3c_pmu_start_counters(struct hisi_pmu *l3c_pmu) ··· 340 303 u32 val; 341 304 342 305 /* Enable counter index in L3C_EVENT_CTRL register */ 343 - val = readl(l3c_pmu->base + L3C_EVENT_CTRL); 306 + val = hisi_l3c_pmu_event_readl(hwc, L3C_EVENT_CTRL); 344 307 val |= (1 << hwc->idx); 345 - writel(val, l3c_pmu->base + L3C_EVENT_CTRL); 308 + hisi_l3c_pmu_event_writel(hwc, L3C_EVENT_CTRL, val); 346 309 } 347 310 348 311 static void hisi_l3c_pmu_disable_counter(struct hisi_pmu *l3c_pmu, ··· 351 314 u32 val; 352 315 353 316 /* Clear counter index in L3C_EVENT_CTRL register */ 354 - val = readl(l3c_pmu->base + L3C_EVENT_CTRL); 317 + val = hisi_l3c_pmu_event_readl(hwc, L3C_EVENT_CTRL); 355 318 val &= ~(1 << hwc->idx); 356 - writel(val, l3c_pmu->base + L3C_EVENT_CTRL); 319 + hisi_l3c_pmu_event_writel(hwc, L3C_EVENT_CTRL, val); 357 320 } 358 321 359 322 static void hisi_l3c_pmu_enable_counter_int(struct hisi_pmu *l3c_pmu, ··· 361 324 { 362 325 u32 val; 363 326 364 - val = readl(l3c_pmu->base + L3C_INT_MASK); 327 + val = hisi_l3c_pmu_event_readl(hwc, L3C_INT_MASK); 365 328 /* Write 0 to enable interrupt */ 366 329 val &= ~(1 << hwc->idx); 367 - writel(val, l3c_pmu->base + L3C_INT_MASK); 330 + hisi_l3c_pmu_event_writel(hwc, L3C_INT_MASK, val); 368 331 } 369 332 370 333 static void hisi_l3c_pmu_disable_counter_int(struct hisi_pmu *l3c_pmu, ··· 372 335 { 373 336 u32 val; 374 337 375 - val = readl(l3c_pmu->base + L3C_INT_MASK); 338 + val = hisi_l3c_pmu_event_readl(hwc, L3C_INT_MASK); 376 339 /* Write 1 to mask interrupt */ 377 340 val |= (1 << hwc->idx); 378 - writel(val, l3c_pmu->base + L3C_INT_MASK); 341 + hisi_l3c_pmu_event_writel(hwc, L3C_INT_MASK, val); 379 342 } 380 343 381 344 static u32 hisi_l3c_pmu_get_int_status(struct hisi_pmu *l3c_pmu) ··· 385 348 386 349 static void hisi_l3c_pmu_clear_int_status(struct hisi_pmu *l3c_pmu, int idx) 387 350 { 388 - writel(1 << idx, l3c_pmu->base + L3C_INT_CLEAR); 351 + struct hw_perf_event *hwc = &l3c_pmu->pmu_events.hw_events[idx]->hw; 352 + 353 + hisi_l3c_pmu_event_writel(hwc, L3C_INT_CLEAR, 1 << idx); 389 354 } 390 355 391 356 static int hisi_l3c_pmu_init_data(struct platform_device *pdev, ··· 513 474 514 475 static const struct hisi_uncore_ops hisi_uncore_l3c_ops = { 515 476 .write_evtype = hisi_l3c_pmu_write_evtype, 516 - .get_event_idx = hisi_uncore_pmu_get_event_idx, 477 + .get_event_idx = hisi_l3c_pmu_get_event_idx, 517 478 .start_counters = hisi_l3c_pmu_start_counters, 518 479 .stop_counters = hisi_l3c_pmu_stop_counters, 519 480 .enable_counter = hisi_l3c_pmu_enable_counter,