1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194#include <linux/anon_inodes.h>
195#include <linux/sizes.h>
196#include <linux/uuid.h>
197
198#include "i915_drv.h"
199#include "i915_oa_hsw.h"
200#include "i915_oa_bdw.h"
201#include "i915_oa_chv.h"
202#include "i915_oa_sklgt2.h"
203#include "i915_oa_sklgt3.h"
204#include "i915_oa_sklgt4.h"
205#include "i915_oa_bxt.h"
206#include "i915_oa_kblgt2.h"
207#include "i915_oa_kblgt3.h"
208#include "i915_oa_glk.h"
209#include "i915_oa_cflgt2.h"
210#include "i915_oa_cflgt3.h"
211#include "i915_oa_cnl.h"
212#include "i915_oa_icl.h"
213
214
215
216
217
218#define OA_BUFFER_SIZE SZ_16M
219
220#define OA_TAKEN(tail, head) ((tail - head) & (OA_BUFFER_SIZE - 1))
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263#define OA_TAIL_MARGIN_NSEC 100000ULL
264#define INVALID_TAIL_PTR 0xffffffff
265
266
267
268
269#define POLL_FREQUENCY 200
270#define POLL_PERIOD (NSEC_PER_SEC / POLL_FREQUENCY)
271
272
273static int zero;
274static int one = 1;
275static u32 i915_perf_stream_paranoid = true;
276
277
278
279
280
281
282
283
284
285#define OA_EXPONENT_MAX 31
286
287#define INVALID_CTX_ID 0xffffffff
288
289
290#define OAREPORT_REASON_MASK 0x3f
291#define OAREPORT_REASON_SHIFT 19
292#define OAREPORT_REASON_TIMER (1<<0)
293#define OAREPORT_REASON_CTX_SWITCH (1<<3)
294#define OAREPORT_REASON_CLK_RATIO (1<<5)
295
296
297
298
299
300
301
302
303
304static int oa_sample_rate_hard_limit;
305
306
307
308
309
310
311
312static u32 i915_oa_max_sample_rate = 100000;
313
314
315
316
317
318static const struct i915_oa_format hsw_oa_formats[I915_OA_FORMAT_MAX] = {
319 [I915_OA_FORMAT_A13] = { 0, 64 },
320 [I915_OA_FORMAT_A29] = { 1, 128 },
321 [I915_OA_FORMAT_A13_B8_C8] = { 2, 128 },
322
323 [I915_OA_FORMAT_B4_C8] = { 4, 64 },
324 [I915_OA_FORMAT_A45_B8_C8] = { 5, 256 },
325 [I915_OA_FORMAT_B4_C8_A16] = { 6, 128 },
326 [I915_OA_FORMAT_C4_B8] = { 7, 64 },
327};
328
329static const struct i915_oa_format gen8_plus_oa_formats[I915_OA_FORMAT_MAX] = {
330 [I915_OA_FORMAT_A12] = { 0, 64 },
331 [I915_OA_FORMAT_A12_B8_C8] = { 2, 128 },
332 [I915_OA_FORMAT_A32u40_A4u32_B8_C8] = { 5, 256 },
333 [I915_OA_FORMAT_C4_B8] = { 7, 64 },
334};
335
336#define SAMPLE_OA_REPORT (1<<0)
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352struct perf_open_properties {
353 u32 sample_flags;
354
355 u64 single_context:1;
356 u64 ctx_handle;
357
358
359 int metrics_set;
360 int oa_format;
361 bool oa_periodic;
362 int oa_period_exponent;
363};
364
365static void free_oa_config(struct drm_i915_private *dev_priv,
366 struct i915_oa_config *oa_config)
367{
368 if (!PTR_ERR(oa_config->flex_regs))
369 kfree(oa_config->flex_regs);
370 if (!PTR_ERR(oa_config->b_counter_regs))
371 kfree(oa_config->b_counter_regs);
372 if (!PTR_ERR(oa_config->mux_regs))
373 kfree(oa_config->mux_regs);
374 kfree(oa_config);
375}
376
377static void put_oa_config(struct drm_i915_private *dev_priv,
378 struct i915_oa_config *oa_config)
379{
380 if (!atomic_dec_and_test(&oa_config->ref_count))
381 return;
382
383 free_oa_config(dev_priv, oa_config);
384}
385
386static int get_oa_config(struct drm_i915_private *dev_priv,
387 int metrics_set,
388 struct i915_oa_config **out_config)
389{
390 int ret;
391
392 if (metrics_set == 1) {
393 *out_config = &dev_priv->perf.oa.test_config;
394 atomic_inc(&dev_priv->perf.oa.test_config.ref_count);
395 return 0;
396 }
397
398 ret = mutex_lock_interruptible(&dev_priv->perf.metrics_lock);
399 if (ret)
400 return ret;
401
402 *out_config = idr_find(&dev_priv->perf.metrics_idr, metrics_set);
403 if (!*out_config)
404 ret = -EINVAL;
405 else
406 atomic_inc(&(*out_config)->ref_count);
407
408 mutex_unlock(&dev_priv->perf.metrics_lock);
409
410 return ret;
411}
412
413static u32 gen8_oa_hw_tail_read(struct drm_i915_private *dev_priv)
414{
415 return I915_READ(GEN8_OATAILPTR) & GEN8_OATAILPTR_MASK;
416}
417
418static u32 gen7_oa_hw_tail_read(struct drm_i915_private *dev_priv)
419{
420 u32 oastatus1 = I915_READ(GEN7_OASTATUS1);
421
422 return oastatus1 & GEN7_OASTATUS1_TAIL_MASK;
423}
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449static bool oa_buffer_check_unlocked(struct drm_i915_private *dev_priv)
450{
451 int report_size = dev_priv->perf.oa.oa_buffer.format_size;
452 unsigned long flags;
453 unsigned int aged_idx;
454 u32 head, hw_tail, aged_tail, aging_tail;
455 u64 now;
456
457
458
459
460
461 spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
462
463
464
465
466
467 head = dev_priv->perf.oa.oa_buffer.head;
468
469 aged_idx = dev_priv->perf.oa.oa_buffer.aged_tail_idx;
470 aged_tail = dev_priv->perf.oa.oa_buffer.tails[aged_idx].offset;
471 aging_tail = dev_priv->perf.oa.oa_buffer.tails[!aged_idx].offset;
472
473 hw_tail = dev_priv->perf.oa.ops.oa_hw_tail_read(dev_priv);
474
475
476
477
478 hw_tail &= ~(report_size - 1);
479
480 now = ktime_get_mono_fast_ns();
481
482
483
484
485
486
487
488
489
490
491
492 if (aging_tail != INVALID_TAIL_PTR &&
493 ((now - dev_priv->perf.oa.oa_buffer.aging_timestamp) >
494 OA_TAIL_MARGIN_NSEC)) {
495
496 aged_idx ^= 1;
497 dev_priv->perf.oa.oa_buffer.aged_tail_idx = aged_idx;
498
499 aged_tail = aging_tail;
500
501
502 dev_priv->perf.oa.oa_buffer.tails[!aged_idx].offset = INVALID_TAIL_PTR;
503 aging_tail = INVALID_TAIL_PTR;
504 }
505
506
507
508
509
510
511
512
513
514 if (aging_tail == INVALID_TAIL_PTR &&
515 (aged_tail == INVALID_TAIL_PTR ||
516 OA_TAKEN(hw_tail, aged_tail) >= report_size)) {
517 struct i915_vma *vma = dev_priv->perf.oa.oa_buffer.vma;
518 u32 gtt_offset = i915_ggtt_offset(vma);
519
520
521
522
523
524 if (hw_tail >= gtt_offset &&
525 hw_tail < (gtt_offset + OA_BUFFER_SIZE)) {
526 dev_priv->perf.oa.oa_buffer.tails[!aged_idx].offset =
527 aging_tail = hw_tail;
528 dev_priv->perf.oa.oa_buffer.aging_timestamp = now;
529 } else {
530 DRM_ERROR("Ignoring spurious out of range OA buffer tail pointer = %u\n",
531 hw_tail);
532 }
533 }
534
535 spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
536
537 return aged_tail == INVALID_TAIL_PTR ?
538 false : OA_TAKEN(aged_tail, head) >= report_size;
539}
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556static int append_oa_status(struct i915_perf_stream *stream,
557 char __user *buf,
558 size_t count,
559 size_t *offset,
560 enum drm_i915_perf_record_type type)
561{
562 struct drm_i915_perf_record_header header = { type, 0, sizeof(header) };
563
564 if ((count - *offset) < header.size)
565 return -ENOSPC;
566
567 if (copy_to_user(buf + *offset, &header, sizeof(header)))
568 return -EFAULT;
569
570 (*offset) += header.size;
571
572 return 0;
573}
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592static int append_oa_sample(struct i915_perf_stream *stream,
593 char __user *buf,
594 size_t count,
595 size_t *offset,
596 const u8 *report)
597{
598 struct drm_i915_private *dev_priv = stream->dev_priv;
599 int report_size = dev_priv->perf.oa.oa_buffer.format_size;
600 struct drm_i915_perf_record_header header;
601 u32 sample_flags = stream->sample_flags;
602
603 header.type = DRM_I915_PERF_RECORD_SAMPLE;
604 header.pad = 0;
605 header.size = stream->sample_size;
606
607 if ((count - *offset) < header.size)
608 return -ENOSPC;
609
610 buf += *offset;
611 if (copy_to_user(buf, &header, sizeof(header)))
612 return -EFAULT;
613 buf += sizeof(header);
614
615 if (sample_flags & SAMPLE_OA_REPORT) {
616 if (copy_to_user(buf, report, report_size))
617 return -EFAULT;
618 }
619
620 (*offset) += header.size;
621
622 return 0;
623}
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645static int gen8_append_oa_reports(struct i915_perf_stream *stream,
646 char __user *buf,
647 size_t count,
648 size_t *offset)
649{
650 struct drm_i915_private *dev_priv = stream->dev_priv;
651 int report_size = dev_priv->perf.oa.oa_buffer.format_size;
652 u8 *oa_buf_base = dev_priv->perf.oa.oa_buffer.vaddr;
653 u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma);
654 u32 mask = (OA_BUFFER_SIZE - 1);
655 size_t start_offset = *offset;
656 unsigned long flags;
657 unsigned int aged_tail_idx;
658 u32 head, tail;
659 u32 taken;
660 int ret = 0;
661
662 if (WARN_ON(!stream->enabled))
663 return -EIO;
664
665 spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
666
667 head = dev_priv->perf.oa.oa_buffer.head;
668 aged_tail_idx = dev_priv->perf.oa.oa_buffer.aged_tail_idx;
669 tail = dev_priv->perf.oa.oa_buffer.tails[aged_tail_idx].offset;
670
671 spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
672
673
674
675
676
677 if (tail == INVALID_TAIL_PTR)
678 return -EAGAIN;
679
680
681
682
683
684 head -= gtt_offset;
685 tail -= gtt_offset;
686
687
688
689
690
691
692
693
694 if (WARN_ONCE(head > OA_BUFFER_SIZE || head % report_size ||
695 tail > OA_BUFFER_SIZE || tail % report_size,
696 "Inconsistent OA buffer pointers: head = %u, tail = %u\n",
697 head, tail))
698 return -EIO;
699
700
701 for (;
702 (taken = OA_TAKEN(tail, head));
703 head = (head + report_size) & mask) {
704 u8 *report = oa_buf_base + head;
705 u32 *report32 = (void *)report;
706 u32 ctx_id;
707 u32 reason;
708
709
710
711
712
713
714
715
716
717
718 if (WARN_ON((OA_BUFFER_SIZE - head) < report_size)) {
719 DRM_ERROR("Spurious OA head ptr: non-integral report offset\n");
720 break;
721 }
722
723
724
725
726
727
728
729
730
731
732 reason = ((report32[0] >> OAREPORT_REASON_SHIFT) &
733 OAREPORT_REASON_MASK);
734 if (reason == 0) {
735 if (__ratelimit(&dev_priv->perf.oa.spurious_report_rs))
736 DRM_NOTE("Skipping spurious, invalid OA report\n");
737 continue;
738 }
739
740 ctx_id = report32[2] & dev_priv->perf.oa.specific_ctx_id_mask;
741
742
743
744
745
746
747
748
749
750 if (!(report32[0] & dev_priv->perf.oa.gen8_valid_ctx_bit))
751 ctx_id = report32[2] = INVALID_CTX_ID;
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784 if (!dev_priv->perf.oa.exclusive_stream->ctx ||
785 dev_priv->perf.oa.specific_ctx_id == ctx_id ||
786 (dev_priv->perf.oa.oa_buffer.last_ctx_id ==
787 dev_priv->perf.oa.specific_ctx_id) ||
788 reason & OAREPORT_REASON_CTX_SWITCH) {
789
790
791
792
793
794 if (dev_priv->perf.oa.exclusive_stream->ctx &&
795 dev_priv->perf.oa.specific_ctx_id != ctx_id) {
796 report32[2] = INVALID_CTX_ID;
797 }
798
799 ret = append_oa_sample(stream, buf, count, offset,
800 report);
801 if (ret)
802 break;
803
804 dev_priv->perf.oa.oa_buffer.last_ctx_id = ctx_id;
805 }
806
807
808
809
810
811
812
813
814 report32[0] = 0;
815 }
816
817 if (start_offset != *offset) {
818 spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
819
820
821
822
823
824 head += gtt_offset;
825
826 I915_WRITE(GEN8_OAHEADPTR, head & GEN8_OAHEADPTR_MASK);
827 dev_priv->perf.oa.oa_buffer.head = head;
828
829 spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
830 }
831
832 return ret;
833}
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855static int gen8_oa_read(struct i915_perf_stream *stream,
856 char __user *buf,
857 size_t count,
858 size_t *offset)
859{
860 struct drm_i915_private *dev_priv = stream->dev_priv;
861 u32 oastatus;
862 int ret;
863
864 if (WARN_ON(!dev_priv->perf.oa.oa_buffer.vaddr))
865 return -EIO;
866
867 oastatus = I915_READ(GEN8_OASTATUS);
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883 if (oastatus & GEN8_OASTATUS_OABUFFER_OVERFLOW) {
884 ret = append_oa_status(stream, buf, count, offset,
885 DRM_I915_PERF_RECORD_OA_BUFFER_LOST);
886 if (ret)
887 return ret;
888
889 DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n",
890 dev_priv->perf.oa.period_exponent);
891
892 dev_priv->perf.oa.ops.oa_disable(dev_priv);
893 dev_priv->perf.oa.ops.oa_enable(dev_priv);
894
895
896
897
898
899 oastatus = I915_READ(GEN8_OASTATUS);
900 }
901
902 if (oastatus & GEN8_OASTATUS_REPORT_LOST) {
903 ret = append_oa_status(stream, buf, count, offset,
904 DRM_I915_PERF_RECORD_OA_REPORT_LOST);
905 if (ret)
906 return ret;
907 I915_WRITE(GEN8_OASTATUS,
908 oastatus & ~GEN8_OASTATUS_REPORT_LOST);
909 }
910
911 return gen8_append_oa_reports(stream, buf, count, offset);
912}
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934static int gen7_append_oa_reports(struct i915_perf_stream *stream,
935 char __user *buf,
936 size_t count,
937 size_t *offset)
938{
939 struct drm_i915_private *dev_priv = stream->dev_priv;
940 int report_size = dev_priv->perf.oa.oa_buffer.format_size;
941 u8 *oa_buf_base = dev_priv->perf.oa.oa_buffer.vaddr;
942 u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma);
943 u32 mask = (OA_BUFFER_SIZE - 1);
944 size_t start_offset = *offset;
945 unsigned long flags;
946 unsigned int aged_tail_idx;
947 u32 head, tail;
948 u32 taken;
949 int ret = 0;
950
951 if (WARN_ON(!stream->enabled))
952 return -EIO;
953
954 spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
955
956 head = dev_priv->perf.oa.oa_buffer.head;
957 aged_tail_idx = dev_priv->perf.oa.oa_buffer.aged_tail_idx;
958 tail = dev_priv->perf.oa.oa_buffer.tails[aged_tail_idx].offset;
959
960 spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
961
962
963
964
965 if (tail == INVALID_TAIL_PTR)
966 return -EAGAIN;
967
968
969
970
971 head -= gtt_offset;
972 tail -= gtt_offset;
973
974
975
976
977
978
979
980 if (WARN_ONCE(head > OA_BUFFER_SIZE || head % report_size ||
981 tail > OA_BUFFER_SIZE || tail % report_size,
982 "Inconsistent OA buffer pointers: head = %u, tail = %u\n",
983 head, tail))
984 return -EIO;
985
986
987 for (;
988 (taken = OA_TAKEN(tail, head));
989 head = (head + report_size) & mask) {
990 u8 *report = oa_buf_base + head;
991 u32 *report32 = (void *)report;
992
993
994
995
996
997
998
999
1000
1001 if (WARN_ON((OA_BUFFER_SIZE - head) < report_size)) {
1002 DRM_ERROR("Spurious OA head ptr: non-integral report offset\n");
1003 break;
1004 }
1005
1006
1007
1008
1009
1010
1011
1012 if (report32[0] == 0) {
1013 if (__ratelimit(&dev_priv->perf.oa.spurious_report_rs))
1014 DRM_NOTE("Skipping spurious, invalid OA report\n");
1015 continue;
1016 }
1017
1018 ret = append_oa_sample(stream, buf, count, offset, report);
1019 if (ret)
1020 break;
1021
1022
1023
1024
1025
1026
1027
1028 report32[0] = 0;
1029 }
1030
1031 if (start_offset != *offset) {
1032 spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
1033
1034
1035
1036
1037 head += gtt_offset;
1038
1039 I915_WRITE(GEN7_OASTATUS2,
1040 ((head & GEN7_OASTATUS2_HEAD_MASK) |
1041 GEN7_OASTATUS2_MEM_SELECT_GGTT));
1042 dev_priv->perf.oa.oa_buffer.head = head;
1043
1044 spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
1045 }
1046
1047 return ret;
1048}
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066static int gen7_oa_read(struct i915_perf_stream *stream,
1067 char __user *buf,
1068 size_t count,
1069 size_t *offset)
1070{
1071 struct drm_i915_private *dev_priv = stream->dev_priv;
1072 u32 oastatus1;
1073 int ret;
1074
1075 if (WARN_ON(!dev_priv->perf.oa.oa_buffer.vaddr))
1076 return -EIO;
1077
1078 oastatus1 = I915_READ(GEN7_OASTATUS1);
1079
1080
1081
1082
1083
1084
1085 oastatus1 &= ~dev_priv->perf.oa.gen7_latched_oastatus1;
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107 if (unlikely(oastatus1 & GEN7_OASTATUS1_OABUFFER_OVERFLOW)) {
1108 ret = append_oa_status(stream, buf, count, offset,
1109 DRM_I915_PERF_RECORD_OA_BUFFER_LOST);
1110 if (ret)
1111 return ret;
1112
1113 DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n",
1114 dev_priv->perf.oa.period_exponent);
1115
1116 dev_priv->perf.oa.ops.oa_disable(dev_priv);
1117 dev_priv->perf.oa.ops.oa_enable(dev_priv);
1118
1119 oastatus1 = I915_READ(GEN7_OASTATUS1);
1120 }
1121
1122 if (unlikely(oastatus1 & GEN7_OASTATUS1_REPORT_LOST)) {
1123 ret = append_oa_status(stream, buf, count, offset,
1124 DRM_I915_PERF_RECORD_OA_REPORT_LOST);
1125 if (ret)
1126 return ret;
1127 dev_priv->perf.oa.gen7_latched_oastatus1 |=
1128 GEN7_OASTATUS1_REPORT_LOST;
1129 }
1130
1131 return gen7_append_oa_reports(stream, buf, count, offset);
1132}
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148static int i915_oa_wait_unlocked(struct i915_perf_stream *stream)
1149{
1150 struct drm_i915_private *dev_priv = stream->dev_priv;
1151
1152
1153 if (!dev_priv->perf.oa.periodic)
1154 return -EIO;
1155
1156 return wait_event_interruptible(dev_priv->perf.oa.poll_wq,
1157 oa_buffer_check_unlocked(dev_priv));
1158}
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170static void i915_oa_poll_wait(struct i915_perf_stream *stream,
1171 struct file *file,
1172 poll_table *wait)
1173{
1174 struct drm_i915_private *dev_priv = stream->dev_priv;
1175
1176 poll_wait(file, &dev_priv->perf.oa.poll_wq, wait);
1177}
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191static int i915_oa_read(struct i915_perf_stream *stream,
1192 char __user *buf,
1193 size_t count,
1194 size_t *offset)
1195{
1196 struct drm_i915_private *dev_priv = stream->dev_priv;
1197
1198 return dev_priv->perf.oa.ops.read(stream, buf, count, offset);
1199}
1200
1201static struct intel_context *oa_pin_context(struct drm_i915_private *i915,
1202 struct i915_gem_context *ctx)
1203{
1204 struct intel_engine_cs *engine = i915->engine[RCS];
1205 struct intel_context *ce;
1206 int ret;
1207
1208 ret = i915_mutex_lock_interruptible(&i915->drm);
1209 if (ret)
1210 return ERR_PTR(ret);
1211
1212
1213
1214
1215
1216
1217
1218 ce = intel_context_pin(ctx, engine);
1219 mutex_unlock(&i915->drm.struct_mutex);
1220 if (IS_ERR(ce))
1221 return ce;
1222
1223 i915->perf.oa.pinned_ctx = ce;
1224
1225 return ce;
1226}
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
1239{
1240 struct drm_i915_private *i915 = stream->dev_priv;
1241 struct intel_context *ce;
1242
1243 ce = oa_pin_context(i915, stream->ctx);
1244 if (IS_ERR(ce))
1245 return PTR_ERR(ce);
1246
1247 switch (INTEL_GEN(i915)) {
1248 case 7: {
1249
1250
1251
1252
1253 i915->perf.oa.specific_ctx_id = i915_ggtt_offset(ce->state);
1254 i915->perf.oa.specific_ctx_id_mask = 0;
1255 break;
1256 }
1257
1258 case 8:
1259 case 9:
1260 case 10:
1261 if (USES_GUC_SUBMISSION(i915)) {
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 i915->perf.oa.specific_ctx_id =
1273 lower_32_bits(ce->lrc_desc) >> 12;
1274
1275
1276
1277
1278
1279 i915->perf.oa.specific_ctx_id_mask =
1280 (1U << (GEN8_CTX_ID_WIDTH - 1)) - 1;
1281 } else {
1282 i915->perf.oa.specific_ctx_id_mask =
1283 (1U << GEN8_CTX_ID_WIDTH) - 1;
1284 i915->perf.oa.specific_ctx_id =
1285 upper_32_bits(ce->lrc_desc);
1286 i915->perf.oa.specific_ctx_id &=
1287 i915->perf.oa.specific_ctx_id_mask;
1288 }
1289 break;
1290
1291 case 11: {
1292 i915->perf.oa.specific_ctx_id_mask =
1293 ((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32) |
1294 ((1U << GEN11_ENGINE_INSTANCE_WIDTH) - 1) << (GEN11_ENGINE_INSTANCE_SHIFT - 32) |
1295 ((1 << GEN11_ENGINE_CLASS_WIDTH) - 1) << (GEN11_ENGINE_CLASS_SHIFT - 32);
1296 i915->perf.oa.specific_ctx_id = upper_32_bits(ce->lrc_desc);
1297 i915->perf.oa.specific_ctx_id &=
1298 i915->perf.oa.specific_ctx_id_mask;
1299 break;
1300 }
1301
1302 default:
1303 MISSING_CASE(INTEL_GEN(i915));
1304 }
1305
1306 DRM_DEBUG_DRIVER("filtering on ctx_id=0x%x ctx_id_mask=0x%x\n",
1307 i915->perf.oa.specific_ctx_id,
1308 i915->perf.oa.specific_ctx_id_mask);
1309
1310 return 0;
1311}
1312
1313
1314
1315
1316
1317
1318
1319
1320static void oa_put_render_ctx_id(struct i915_perf_stream *stream)
1321{
1322 struct drm_i915_private *dev_priv = stream->dev_priv;
1323 struct intel_context *ce;
1324
1325 dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID;
1326 dev_priv->perf.oa.specific_ctx_id_mask = 0;
1327
1328 ce = fetch_and_zero(&dev_priv->perf.oa.pinned_ctx);
1329 if (ce) {
1330 mutex_lock(&dev_priv->drm.struct_mutex);
1331 intel_context_unpin(ce);
1332 mutex_unlock(&dev_priv->drm.struct_mutex);
1333 }
1334}
1335
1336static void
1337free_oa_buffer(struct drm_i915_private *i915)
1338{
1339 mutex_lock(&i915->drm.struct_mutex);
1340
1341 i915_gem_object_unpin_map(i915->perf.oa.oa_buffer.vma->obj);
1342 i915_vma_unpin(i915->perf.oa.oa_buffer.vma);
1343 i915_gem_object_put(i915->perf.oa.oa_buffer.vma->obj);
1344
1345 i915->perf.oa.oa_buffer.vma = NULL;
1346 i915->perf.oa.oa_buffer.vaddr = NULL;
1347
1348 mutex_unlock(&i915->drm.struct_mutex);
1349}
1350
1351static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
1352{
1353 struct drm_i915_private *dev_priv = stream->dev_priv;
1354
1355 BUG_ON(stream != dev_priv->perf.oa.exclusive_stream);
1356
1357
1358
1359
1360
1361 mutex_lock(&dev_priv->drm.struct_mutex);
1362 dev_priv->perf.oa.exclusive_stream = NULL;
1363 dev_priv->perf.oa.ops.disable_metric_set(dev_priv);
1364 mutex_unlock(&dev_priv->drm.struct_mutex);
1365
1366 free_oa_buffer(dev_priv);
1367
1368 intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
1369 intel_runtime_pm_put(dev_priv);
1370
1371 if (stream->ctx)
1372 oa_put_render_ctx_id(stream);
1373
1374 put_oa_config(dev_priv, stream->oa_config);
1375
1376 if (dev_priv->perf.oa.spurious_report_rs.missed) {
1377 DRM_NOTE("%d spurious OA report notices suppressed due to ratelimiting\n",
1378 dev_priv->perf.oa.spurious_report_rs.missed);
1379 }
1380}
1381
1382static void gen7_init_oa_buffer(struct drm_i915_private *dev_priv)
1383{
1384 u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma);
1385 unsigned long flags;
1386
1387 spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
1388
1389
1390
1391
1392 I915_WRITE(GEN7_OASTATUS2,
1393 gtt_offset | GEN7_OASTATUS2_MEM_SELECT_GGTT);
1394 dev_priv->perf.oa.oa_buffer.head = gtt_offset;
1395
1396 I915_WRITE(GEN7_OABUFFER, gtt_offset);
1397
1398 I915_WRITE(GEN7_OASTATUS1, gtt_offset | OABUFFER_SIZE_16M);
1399
1400
1401 dev_priv->perf.oa.oa_buffer.tails[0].offset = INVALID_TAIL_PTR;
1402 dev_priv->perf.oa.oa_buffer.tails[1].offset = INVALID_TAIL_PTR;
1403
1404 spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
1405
1406
1407
1408
1409
1410 dev_priv->perf.oa.gen7_latched_oastatus1 = 0;
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423 memset(dev_priv->perf.oa.oa_buffer.vaddr, 0, OA_BUFFER_SIZE);
1424
1425
1426
1427
1428 dev_priv->perf.oa.pollin = false;
1429}
1430
1431static void gen8_init_oa_buffer(struct drm_i915_private *dev_priv)
1432{
1433 u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma);
1434 unsigned long flags;
1435
1436 spin_lock_irqsave(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
1437
1438 I915_WRITE(GEN8_OASTATUS, 0);
1439 I915_WRITE(GEN8_OAHEADPTR, gtt_offset);
1440 dev_priv->perf.oa.oa_buffer.head = gtt_offset;
1441
1442 I915_WRITE(GEN8_OABUFFER_UDW, 0);
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452 I915_WRITE(GEN8_OABUFFER, gtt_offset |
1453 OABUFFER_SIZE_16M | GEN8_OABUFFER_MEM_SELECT_GGTT);
1454 I915_WRITE(GEN8_OATAILPTR, gtt_offset & GEN8_OATAILPTR_MASK);
1455
1456
1457 dev_priv->perf.oa.oa_buffer.tails[0].offset = INVALID_TAIL_PTR;
1458 dev_priv->perf.oa.oa_buffer.tails[1].offset = INVALID_TAIL_PTR;
1459
1460
1461
1462
1463
1464
1465 dev_priv->perf.oa.oa_buffer.last_ctx_id = INVALID_CTX_ID;
1466
1467 spin_unlock_irqrestore(&dev_priv->perf.oa.oa_buffer.ptr_lock, flags);
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481 memset(dev_priv->perf.oa.oa_buffer.vaddr, 0, OA_BUFFER_SIZE);
1482
1483
1484
1485
1486
1487 dev_priv->perf.oa.pollin = false;
1488}
1489
1490static int alloc_oa_buffer(struct drm_i915_private *dev_priv)
1491{
1492 struct drm_i915_gem_object *bo;
1493 struct i915_vma *vma;
1494 int ret;
1495
1496 if (WARN_ON(dev_priv->perf.oa.oa_buffer.vma))
1497 return -ENODEV;
1498
1499 ret = i915_mutex_lock_interruptible(&dev_priv->drm);
1500 if (ret)
1501 return ret;
1502
1503 BUILD_BUG_ON_NOT_POWER_OF_2(OA_BUFFER_SIZE);
1504 BUILD_BUG_ON(OA_BUFFER_SIZE < SZ_128K || OA_BUFFER_SIZE > SZ_16M);
1505
1506 bo = i915_gem_object_create(dev_priv, OA_BUFFER_SIZE);
1507 if (IS_ERR(bo)) {
1508 DRM_ERROR("Failed to allocate OA buffer\n");
1509 ret = PTR_ERR(bo);
1510 goto unlock;
1511 }
1512
1513 ret = i915_gem_object_set_cache_level(bo, I915_CACHE_LLC);
1514 if (ret)
1515 goto err_unref;
1516
1517
1518 vma = i915_gem_object_ggtt_pin(bo, NULL, 0, SZ_16M, 0);
1519 if (IS_ERR(vma)) {
1520 ret = PTR_ERR(vma);
1521 goto err_unref;
1522 }
1523 dev_priv->perf.oa.oa_buffer.vma = vma;
1524
1525 dev_priv->perf.oa.oa_buffer.vaddr =
1526 i915_gem_object_pin_map(bo, I915_MAP_WB);
1527 if (IS_ERR(dev_priv->perf.oa.oa_buffer.vaddr)) {
1528 ret = PTR_ERR(dev_priv->perf.oa.oa_buffer.vaddr);
1529 goto err_unpin;
1530 }
1531
1532 dev_priv->perf.oa.ops.init_oa_buffer(dev_priv);
1533
1534 DRM_DEBUG_DRIVER("OA Buffer initialized, gtt offset = 0x%x, vaddr = %p\n",
1535 i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma),
1536 dev_priv->perf.oa.oa_buffer.vaddr);
1537
1538 goto unlock;
1539
1540err_unpin:
1541 __i915_vma_unpin(vma);
1542
1543err_unref:
1544 i915_gem_object_put(bo);
1545
1546 dev_priv->perf.oa.oa_buffer.vaddr = NULL;
1547 dev_priv->perf.oa.oa_buffer.vma = NULL;
1548
1549unlock:
1550 mutex_unlock(&dev_priv->drm.struct_mutex);
1551 return ret;
1552}
1553
1554static void config_oa_regs(struct drm_i915_private *dev_priv,
1555 const struct i915_oa_reg *regs,
1556 u32 n_regs)
1557{
1558 u32 i;
1559
1560 for (i = 0; i < n_regs; i++) {
1561 const struct i915_oa_reg *reg = regs + i;
1562
1563 I915_WRITE(reg->addr, reg->value);
1564 }
1565}
1566
1567static int hsw_enable_metric_set(struct drm_i915_private *dev_priv,
1568 const struct i915_oa_config *oa_config)
1569{
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579 I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
1580 ~GEN7_DOP_CLOCK_GATE_ENABLE));
1581 I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) |
1582 GEN6_CSUNIT_CLOCK_GATE_DISABLE));
1583
1584 config_oa_regs(dev_priv, oa_config->mux_regs, oa_config->mux_regs_len);
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607 usleep_range(15000, 20000);
1608
1609 config_oa_regs(dev_priv, oa_config->b_counter_regs,
1610 oa_config->b_counter_regs_len);
1611
1612 return 0;
1613}
1614
1615static void hsw_disable_metric_set(struct drm_i915_private *dev_priv)
1616{
1617 I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) &
1618 ~GEN6_CSUNIT_CLOCK_GATE_DISABLE));
1619 I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) |
1620 GEN7_DOP_CLOCK_GATE_ENABLE));
1621
1622 I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) &
1623 ~GT_NOA_ENABLE));
1624}
1625
1626
1627
1628
1629
1630
1631
1632
1633static void gen8_update_reg_state_unlocked(struct i915_gem_context *ctx,
1634 u32 *reg_state,
1635 const struct i915_oa_config *oa_config)
1636{
1637 struct drm_i915_private *dev_priv = ctx->i915;
1638 u32 ctx_oactxctrl = dev_priv->perf.oa.ctx_oactxctrl_offset;
1639 u32 ctx_flexeu0 = dev_priv->perf.oa.ctx_flexeu0_offset;
1640
1641 u32 flex_mmio[] = {
1642 i915_mmio_reg_offset(EU_PERF_CNTL0),
1643 i915_mmio_reg_offset(EU_PERF_CNTL1),
1644 i915_mmio_reg_offset(EU_PERF_CNTL2),
1645 i915_mmio_reg_offset(EU_PERF_CNTL3),
1646 i915_mmio_reg_offset(EU_PERF_CNTL4),
1647 i915_mmio_reg_offset(EU_PERF_CNTL5),
1648 i915_mmio_reg_offset(EU_PERF_CNTL6),
1649 };
1650 int i;
1651
1652 reg_state[ctx_oactxctrl] = i915_mmio_reg_offset(GEN8_OACTXCONTROL);
1653 reg_state[ctx_oactxctrl+1] = (dev_priv->perf.oa.period_exponent <<
1654 GEN8_OA_TIMER_PERIOD_SHIFT) |
1655 (dev_priv->perf.oa.periodic ?
1656 GEN8_OA_TIMER_ENABLE : 0) |
1657 GEN8_OA_COUNTER_RESUME;
1658
1659 for (i = 0; i < ARRAY_SIZE(flex_mmio); i++) {
1660 u32 state_offset = ctx_flexeu0 + i * 2;
1661 u32 mmio = flex_mmio[i];
1662
1663
1664
1665
1666
1667
1668 u32 value = 0;
1669
1670 if (oa_config) {
1671 u32 j;
1672
1673 for (j = 0; j < oa_config->flex_regs_len; j++) {
1674 if (i915_mmio_reg_offset(oa_config->flex_regs[j].addr) == mmio) {
1675 value = oa_config->flex_regs[j].value;
1676 break;
1677 }
1678 }
1679 }
1680
1681 reg_state[state_offset] = mmio;
1682 reg_state[state_offset+1] = value;
1683 }
1684}
1685
1686
1687
1688
1689
1690static int gen8_emit_oa_config(struct i915_request *rq,
1691 const struct i915_oa_config *oa_config)
1692{
1693 struct drm_i915_private *dev_priv = rq->i915;
1694
1695 u32 flex_mmio[] = {
1696 i915_mmio_reg_offset(EU_PERF_CNTL0),
1697 i915_mmio_reg_offset(EU_PERF_CNTL1),
1698 i915_mmio_reg_offset(EU_PERF_CNTL2),
1699 i915_mmio_reg_offset(EU_PERF_CNTL3),
1700 i915_mmio_reg_offset(EU_PERF_CNTL4),
1701 i915_mmio_reg_offset(EU_PERF_CNTL5),
1702 i915_mmio_reg_offset(EU_PERF_CNTL6),
1703 };
1704 u32 *cs;
1705 int i;
1706
1707 cs = intel_ring_begin(rq, ARRAY_SIZE(flex_mmio) * 2 + 4);
1708 if (IS_ERR(cs))
1709 return PTR_ERR(cs);
1710
1711 *cs++ = MI_LOAD_REGISTER_IMM(ARRAY_SIZE(flex_mmio) + 1);
1712
1713 *cs++ = i915_mmio_reg_offset(GEN8_OACTXCONTROL);
1714 *cs++ = (dev_priv->perf.oa.period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
1715 (dev_priv->perf.oa.periodic ? GEN8_OA_TIMER_ENABLE : 0) |
1716 GEN8_OA_COUNTER_RESUME;
1717
1718 for (i = 0; i < ARRAY_SIZE(flex_mmio); i++) {
1719 u32 mmio = flex_mmio[i];
1720
1721
1722
1723
1724
1725
1726
1727 u32 value = 0;
1728
1729 if (oa_config) {
1730 u32 j;
1731
1732 for (j = 0; j < oa_config->flex_regs_len; j++) {
1733 if (i915_mmio_reg_offset(oa_config->flex_regs[j].addr) == mmio) {
1734 value = oa_config->flex_regs[j].value;
1735 break;
1736 }
1737 }
1738 }
1739
1740 *cs++ = mmio;
1741 *cs++ = value;
1742 }
1743
1744 *cs++ = MI_NOOP;
1745 intel_ring_advance(rq, cs);
1746
1747 return 0;
1748}
1749
1750static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_priv,
1751 const struct i915_oa_config *oa_config)
1752{
1753 struct intel_engine_cs *engine = dev_priv->engine[RCS];
1754 struct i915_timeline *timeline;
1755 struct i915_request *rq;
1756 int ret;
1757
1758 lockdep_assert_held(&dev_priv->drm.struct_mutex);
1759
1760 i915_retire_requests(dev_priv);
1761
1762 rq = i915_request_alloc(engine, dev_priv->kernel_context);
1763 if (IS_ERR(rq))
1764 return PTR_ERR(rq);
1765
1766 ret = gen8_emit_oa_config(rq, oa_config);
1767 if (ret) {
1768 i915_request_add(rq);
1769 return ret;
1770 }
1771
1772
1773 list_for_each_entry(timeline, &dev_priv->gt.timelines, link) {
1774 struct i915_request *prev;
1775
1776 prev = i915_gem_active_raw(&timeline->last_request,
1777 &dev_priv->drm.struct_mutex);
1778 if (prev)
1779 i915_request_await_dma_fence(rq, &prev->fence);
1780 }
1781
1782 i915_request_add(rq);
1783
1784 return 0;
1785}
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv,
1812 const struct i915_oa_config *oa_config)
1813{
1814 struct intel_engine_cs *engine = dev_priv->engine[RCS];
1815 struct i915_gem_context *ctx;
1816 int ret;
1817 unsigned int wait_flags = I915_WAIT_LOCKED;
1818
1819 lockdep_assert_held(&dev_priv->drm.struct_mutex);
1820
1821
1822 ret = gen8_switch_to_updated_kernel_context(dev_priv, oa_config);
1823 if (ret)
1824 goto out;
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839 ret = i915_gem_wait_for_idle(dev_priv,
1840 wait_flags,
1841 MAX_SCHEDULE_TIMEOUT);
1842 if (ret)
1843 goto out;
1844
1845
1846 list_for_each_entry(ctx, &dev_priv->contexts.list, link) {
1847 struct intel_context *ce = to_intel_context(ctx, engine);
1848 u32 *regs;
1849
1850
1851 if (!ce->state)
1852 continue;
1853
1854 regs = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB);
1855 if (IS_ERR(regs)) {
1856 ret = PTR_ERR(regs);
1857 goto out;
1858 }
1859
1860 ce->state->obj->mm.dirty = true;
1861 regs += LRC_STATE_PN * PAGE_SIZE / sizeof(*regs);
1862
1863 gen8_update_reg_state_unlocked(ctx, regs, oa_config);
1864
1865 i915_gem_object_unpin_map(ce->state->obj);
1866 }
1867
1868 out:
1869 return ret;
1870}
1871
1872static int gen8_enable_metric_set(struct drm_i915_private *dev_priv,
1873 const struct i915_oa_config *oa_config)
1874{
1875 int ret;
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900 if (IS_GEN(dev_priv, 9, 11)) {
1901 I915_WRITE(GEN8_OA_DEBUG,
1902 _MASKED_BIT_ENABLE(GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS |
1903 GEN9_OA_DEBUG_INCLUDE_CLK_RATIO));
1904 }
1905
1906
1907
1908
1909
1910
1911 ret = gen8_configure_all_contexts(dev_priv, oa_config);
1912 if (ret)
1913 return ret;
1914
1915 config_oa_regs(dev_priv, oa_config->mux_regs, oa_config->mux_regs_len);
1916
1917 config_oa_regs(dev_priv, oa_config->b_counter_regs,
1918 oa_config->b_counter_regs_len);
1919
1920 return 0;
1921}
1922
1923static void gen8_disable_metric_set(struct drm_i915_private *dev_priv)
1924{
1925
1926 gen8_configure_all_contexts(dev_priv, NULL);
1927
1928 I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) &
1929 ~GT_NOA_ENABLE));
1930}
1931
1932static void gen10_disable_metric_set(struct drm_i915_private *dev_priv)
1933{
1934
1935 gen8_configure_all_contexts(dev_priv, NULL);
1936
1937
1938 I915_WRITE(RPM_CONFIG1,
1939 I915_READ(RPM_CONFIG1) & ~GEN10_GT_NOA_ENABLE);
1940}
1941
1942static void gen7_oa_enable(struct drm_i915_private *dev_priv)
1943{
1944 struct i915_gem_context *ctx =
1945 dev_priv->perf.oa.exclusive_stream->ctx;
1946 u32 ctx_id = dev_priv->perf.oa.specific_ctx_id;
1947 bool periodic = dev_priv->perf.oa.periodic;
1948 u32 period_exponent = dev_priv->perf.oa.period_exponent;
1949 u32 report_format = dev_priv->perf.oa.oa_buffer.format;
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960 gen7_init_oa_buffer(dev_priv);
1961
1962 I915_WRITE(GEN7_OACONTROL,
1963 (ctx_id & GEN7_OACONTROL_CTX_MASK) |
1964 (period_exponent <<
1965 GEN7_OACONTROL_TIMER_PERIOD_SHIFT) |
1966 (periodic ? GEN7_OACONTROL_TIMER_ENABLE : 0) |
1967 (report_format << GEN7_OACONTROL_FORMAT_SHIFT) |
1968 (ctx ? GEN7_OACONTROL_PER_CTX_ENABLE : 0) |
1969 GEN7_OACONTROL_ENABLE);
1970}
1971
1972static void gen8_oa_enable(struct drm_i915_private *dev_priv)
1973{
1974 u32 report_format = dev_priv->perf.oa.oa_buffer.format;
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985 gen8_init_oa_buffer(dev_priv);
1986
1987
1988
1989
1990
1991
1992 I915_WRITE(GEN8_OACONTROL, (report_format <<
1993 GEN8_OA_REPORT_FORMAT_SHIFT) |
1994 GEN8_OA_COUNTER_ENABLE);
1995}
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006static void i915_oa_stream_enable(struct i915_perf_stream *stream)
2007{
2008 struct drm_i915_private *dev_priv = stream->dev_priv;
2009
2010 dev_priv->perf.oa.ops.oa_enable(dev_priv);
2011
2012 if (dev_priv->perf.oa.periodic)
2013 hrtimer_start(&dev_priv->perf.oa.poll_check_timer,
2014 ns_to_ktime(POLL_PERIOD),
2015 HRTIMER_MODE_REL_PINNED);
2016}
2017
2018static void gen7_oa_disable(struct drm_i915_private *dev_priv)
2019{
2020 I915_WRITE(GEN7_OACONTROL, 0);
2021 if (intel_wait_for_register(dev_priv,
2022 GEN7_OACONTROL, GEN7_OACONTROL_ENABLE, 0,
2023 50))
2024 DRM_ERROR("wait for OA to be disabled timed out\n");
2025}
2026
2027static void gen8_oa_disable(struct drm_i915_private *dev_priv)
2028{
2029 I915_WRITE(GEN8_OACONTROL, 0);
2030 if (intel_wait_for_register(dev_priv,
2031 GEN8_OACONTROL, GEN8_OA_COUNTER_ENABLE, 0,
2032 50))
2033 DRM_ERROR("wait for OA to be disabled timed out\n");
2034}
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044static void i915_oa_stream_disable(struct i915_perf_stream *stream)
2045{
2046 struct drm_i915_private *dev_priv = stream->dev_priv;
2047
2048 dev_priv->perf.oa.ops.oa_disable(dev_priv);
2049
2050 if (dev_priv->perf.oa.periodic)
2051 hrtimer_cancel(&dev_priv->perf.oa.poll_check_timer);
2052}
2053
2054static const struct i915_perf_stream_ops i915_oa_stream_ops = {
2055 .destroy = i915_oa_stream_destroy,
2056 .enable = i915_oa_stream_enable,
2057 .disable = i915_oa_stream_disable,
2058 .wait_unlocked = i915_oa_wait_unlocked,
2059 .poll_wait = i915_oa_poll_wait,
2060 .read = i915_oa_read,
2061};
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081static int i915_oa_stream_init(struct i915_perf_stream *stream,
2082 struct drm_i915_perf_open_param *param,
2083 struct perf_open_properties *props)
2084{
2085 struct drm_i915_private *dev_priv = stream->dev_priv;
2086 int format_size;
2087 int ret;
2088
2089
2090
2091
2092
2093 if (!dev_priv->perf.metrics_kobj) {
2094 DRM_DEBUG("OA metrics weren't advertised via sysfs\n");
2095 return -EINVAL;
2096 }
2097
2098 if (!(props->sample_flags & SAMPLE_OA_REPORT)) {
2099 DRM_DEBUG("Only OA report sampling supported\n");
2100 return -EINVAL;
2101 }
2102
2103 if (!dev_priv->perf.oa.ops.init_oa_buffer) {
2104 DRM_DEBUG("OA unit not supported\n");
2105 return -ENODEV;
2106 }
2107
2108
2109
2110
2111
2112 if (dev_priv->perf.oa.exclusive_stream) {
2113 DRM_DEBUG("OA unit already in use\n");
2114 return -EBUSY;
2115 }
2116
2117 if (!props->oa_format) {
2118 DRM_DEBUG("OA report format not specified\n");
2119 return -EINVAL;
2120 }
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133 ratelimit_state_init(&dev_priv->perf.oa.spurious_report_rs,
2134 5 * HZ, 10);
2135
2136
2137
2138
2139 ratelimit_set_flags(&dev_priv->perf.oa.spurious_report_rs,
2140 RATELIMIT_MSG_ON_RELEASE);
2141
2142 stream->sample_size = sizeof(struct drm_i915_perf_record_header);
2143
2144 format_size = dev_priv->perf.oa.oa_formats[props->oa_format].size;
2145
2146 stream->sample_flags |= SAMPLE_OA_REPORT;
2147 stream->sample_size += format_size;
2148
2149 dev_priv->perf.oa.oa_buffer.format_size = format_size;
2150 if (WARN_ON(dev_priv->perf.oa.oa_buffer.format_size == 0))
2151 return -EINVAL;
2152
2153 dev_priv->perf.oa.oa_buffer.format =
2154 dev_priv->perf.oa.oa_formats[props->oa_format].format;
2155
2156 dev_priv->perf.oa.periodic = props->oa_periodic;
2157 if (dev_priv->perf.oa.periodic)
2158 dev_priv->perf.oa.period_exponent = props->oa_period_exponent;
2159
2160 if (stream->ctx) {
2161 ret = oa_get_render_ctx_id(stream);
2162 if (ret) {
2163 DRM_DEBUG("Invalid context id to filter with\n");
2164 return ret;
2165 }
2166 }
2167
2168 ret = get_oa_config(dev_priv, props->metrics_set, &stream->oa_config);
2169 if (ret) {
2170 DRM_DEBUG("Invalid OA config id=%i\n", props->metrics_set);
2171 goto err_config;
2172 }
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186 intel_runtime_pm_get(dev_priv);
2187 intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
2188
2189 ret = alloc_oa_buffer(dev_priv);
2190 if (ret)
2191 goto err_oa_buf_alloc;
2192
2193 ret = i915_mutex_lock_interruptible(&dev_priv->drm);
2194 if (ret)
2195 goto err_lock;
2196
2197 ret = dev_priv->perf.oa.ops.enable_metric_set(dev_priv,
2198 stream->oa_config);
2199 if (ret) {
2200 DRM_DEBUG("Unable to enable metric set\n");
2201 goto err_enable;
2202 }
2203
2204 stream->ops = &i915_oa_stream_ops;
2205
2206 dev_priv->perf.oa.exclusive_stream = stream;
2207
2208 mutex_unlock(&dev_priv->drm.struct_mutex);
2209
2210 return 0;
2211
2212err_enable:
2213 dev_priv->perf.oa.ops.disable_metric_set(dev_priv);
2214 mutex_unlock(&dev_priv->drm.struct_mutex);
2215
2216err_lock:
2217 free_oa_buffer(dev_priv);
2218
2219err_oa_buf_alloc:
2220 put_oa_config(dev_priv, stream->oa_config);
2221
2222 intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
2223 intel_runtime_pm_put(dev_priv);
2224
2225err_config:
2226 if (stream->ctx)
2227 oa_put_render_ctx_id(stream);
2228
2229 return ret;
2230}
2231
2232void i915_oa_init_reg_state(struct intel_engine_cs *engine,
2233 struct i915_gem_context *ctx,
2234 u32 *reg_state)
2235{
2236 struct i915_perf_stream *stream;
2237
2238 if (engine->id != RCS)
2239 return;
2240
2241 stream = engine->i915->perf.oa.exclusive_stream;
2242 if (stream)
2243 gen8_update_reg_state_unlocked(ctx, reg_state, stream->oa_config);
2244}
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271static ssize_t i915_perf_read_locked(struct i915_perf_stream *stream,
2272 struct file *file,
2273 char __user *buf,
2274 size_t count,
2275 loff_t *ppos)
2276{
2277
2278
2279
2280
2281
2282
2283 size_t offset = 0;
2284 int ret = stream->ops->read(stream, buf, count, &offset);
2285
2286 return offset ?: (ret ?: -EAGAIN);
2287}
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307static ssize_t i915_perf_read(struct file *file,
2308 char __user *buf,
2309 size_t count,
2310 loff_t *ppos)
2311{
2312 struct i915_perf_stream *stream = file->private_data;
2313 struct drm_i915_private *dev_priv = stream->dev_priv;
2314 ssize_t ret;
2315
2316
2317
2318
2319
2320 if (!stream->enabled)
2321 return -EIO;
2322
2323 if (!(file->f_flags & O_NONBLOCK)) {
2324
2325
2326
2327
2328
2329
2330
2331 do {
2332 ret = stream->ops->wait_unlocked(stream);
2333 if (ret)
2334 return ret;
2335
2336 mutex_lock(&dev_priv->perf.lock);
2337 ret = i915_perf_read_locked(stream, file,
2338 buf, count, ppos);
2339 mutex_unlock(&dev_priv->perf.lock);
2340 } while (ret == -EAGAIN);
2341 } else {
2342 mutex_lock(&dev_priv->perf.lock);
2343 ret = i915_perf_read_locked(stream, file, buf, count, ppos);
2344 mutex_unlock(&dev_priv->perf.lock);
2345 }
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355 if (ret >= 0 || ret == -EAGAIN) {
2356
2357
2358
2359 dev_priv->perf.oa.pollin = false;
2360 }
2361
2362 return ret;
2363}
2364
2365static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer)
2366{
2367 struct drm_i915_private *dev_priv =
2368 container_of(hrtimer, typeof(*dev_priv),
2369 perf.oa.poll_check_timer);
2370
2371 if (oa_buffer_check_unlocked(dev_priv)) {
2372 dev_priv->perf.oa.pollin = true;
2373 wake_up(&dev_priv->perf.oa.poll_wq);
2374 }
2375
2376 hrtimer_forward_now(hrtimer, ns_to_ktime(POLL_PERIOD));
2377
2378 return HRTIMER_RESTART;
2379}
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397static __poll_t i915_perf_poll_locked(struct drm_i915_private *dev_priv,
2398 struct i915_perf_stream *stream,
2399 struct file *file,
2400 poll_table *wait)
2401{
2402 __poll_t events = 0;
2403
2404 stream->ops->poll_wait(stream, file, wait);
2405
2406
2407
2408
2409
2410
2411
2412 if (dev_priv->perf.oa.pollin)
2413 events |= EPOLLIN;
2414
2415 return events;
2416}
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431static __poll_t i915_perf_poll(struct file *file, poll_table *wait)
2432{
2433 struct i915_perf_stream *stream = file->private_data;
2434 struct drm_i915_private *dev_priv = stream->dev_priv;
2435 __poll_t ret;
2436
2437 mutex_lock(&dev_priv->perf.lock);
2438 ret = i915_perf_poll_locked(dev_priv, stream, file, wait);
2439 mutex_unlock(&dev_priv->perf.lock);
2440
2441 return ret;
2442}
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454static void i915_perf_enable_locked(struct i915_perf_stream *stream)
2455{
2456 if (stream->enabled)
2457 return;
2458
2459
2460 stream->enabled = true;
2461
2462 if (stream->ops->enable)
2463 stream->ops->enable(stream);
2464}
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480static void i915_perf_disable_locked(struct i915_perf_stream *stream)
2481{
2482 if (!stream->enabled)
2483 return;
2484
2485
2486 stream->enabled = false;
2487
2488 if (stream->ops->disable)
2489 stream->ops->disable(stream);
2490}
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504static long i915_perf_ioctl_locked(struct i915_perf_stream *stream,
2505 unsigned int cmd,
2506 unsigned long arg)
2507{
2508 switch (cmd) {
2509 case I915_PERF_IOCTL_ENABLE:
2510 i915_perf_enable_locked(stream);
2511 return 0;
2512 case I915_PERF_IOCTL_DISABLE:
2513 i915_perf_disable_locked(stream);
2514 return 0;
2515 }
2516
2517 return -EINVAL;
2518}
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531static long i915_perf_ioctl(struct file *file,
2532 unsigned int cmd,
2533 unsigned long arg)
2534{
2535 struct i915_perf_stream *stream = file->private_data;
2536 struct drm_i915_private *dev_priv = stream->dev_priv;
2537 long ret;
2538
2539 mutex_lock(&dev_priv->perf.lock);
2540 ret = i915_perf_ioctl_locked(stream, cmd, arg);
2541 mutex_unlock(&dev_priv->perf.lock);
2542
2543 return ret;
2544}
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556static void i915_perf_destroy_locked(struct i915_perf_stream *stream)
2557{
2558 if (stream->enabled)
2559 i915_perf_disable_locked(stream);
2560
2561 if (stream->ops->destroy)
2562 stream->ops->destroy(stream);
2563
2564 list_del(&stream->link);
2565
2566 if (stream->ctx)
2567 i915_gem_context_put(stream->ctx);
2568
2569 kfree(stream);
2570}
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583static int i915_perf_release(struct inode *inode, struct file *file)
2584{
2585 struct i915_perf_stream *stream = file->private_data;
2586 struct drm_i915_private *dev_priv = stream->dev_priv;
2587
2588 mutex_lock(&dev_priv->perf.lock);
2589 i915_perf_destroy_locked(stream);
2590 mutex_unlock(&dev_priv->perf.lock);
2591
2592 return 0;
2593}
2594
2595
2596static const struct file_operations fops = {
2597 .owner = THIS_MODULE,
2598 .llseek = no_llseek,
2599 .release = i915_perf_release,
2600 .poll = i915_perf_poll,
2601 .read = i915_perf_read,
2602 .unlocked_ioctl = i915_perf_ioctl,
2603
2604
2605
2606 .compat_ioctl = i915_perf_ioctl,
2607};
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634static int
2635i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv,
2636 struct drm_i915_perf_open_param *param,
2637 struct perf_open_properties *props,
2638 struct drm_file *file)
2639{
2640 struct i915_gem_context *specific_ctx = NULL;
2641 struct i915_perf_stream *stream = NULL;
2642 unsigned long f_flags = 0;
2643 bool privileged_op = true;
2644 int stream_fd;
2645 int ret;
2646
2647 if (props->single_context) {
2648 u32 ctx_handle = props->ctx_handle;
2649 struct drm_i915_file_private *file_priv = file->driver_priv;
2650
2651 specific_ctx = i915_gem_context_lookup(file_priv, ctx_handle);
2652 if (!specific_ctx) {
2653 DRM_DEBUG("Failed to look up context with ID %u for opening perf stream\n",
2654 ctx_handle);
2655 ret = -ENOENT;
2656 goto err;
2657 }
2658 }
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674 if (IS_HASWELL(dev_priv) && specific_ctx)
2675 privileged_op = false;
2676
2677
2678
2679
2680
2681
2682 if (privileged_op &&
2683 i915_perf_stream_paranoid && !capable(CAP_SYS_ADMIN)) {
2684 DRM_DEBUG("Insufficient privileges to open system-wide i915 perf stream\n");
2685 ret = -EACCES;
2686 goto err_ctx;
2687 }
2688
2689 stream = kzalloc(sizeof(*stream), GFP_KERNEL);
2690 if (!stream) {
2691 ret = -ENOMEM;
2692 goto err_ctx;
2693 }
2694
2695 stream->dev_priv = dev_priv;
2696 stream->ctx = specific_ctx;
2697
2698 ret = i915_oa_stream_init(stream, param, props);
2699 if (ret)
2700 goto err_alloc;
2701
2702
2703
2704
2705
2706 if (WARN_ON(stream->sample_flags != props->sample_flags)) {
2707 ret = -ENODEV;
2708 goto err_flags;
2709 }
2710
2711 list_add(&stream->link, &dev_priv->perf.streams);
2712
2713 if (param->flags & I915_PERF_FLAG_FD_CLOEXEC)
2714 f_flags |= O_CLOEXEC;
2715 if (param->flags & I915_PERF_FLAG_FD_NONBLOCK)
2716 f_flags |= O_NONBLOCK;
2717
2718 stream_fd = anon_inode_getfd("[i915_perf]", &fops, stream, f_flags);
2719 if (stream_fd < 0) {
2720 ret = stream_fd;
2721 goto err_open;
2722 }
2723
2724 if (!(param->flags & I915_PERF_FLAG_DISABLED))
2725 i915_perf_enable_locked(stream);
2726
2727 return stream_fd;
2728
2729err_open:
2730 list_del(&stream->link);
2731err_flags:
2732 if (stream->ops->destroy)
2733 stream->ops->destroy(stream);
2734err_alloc:
2735 kfree(stream);
2736err_ctx:
2737 if (specific_ctx)
2738 i915_gem_context_put(specific_ctx);
2739err:
2740 return ret;
2741}
2742
2743static u64 oa_exponent_to_ns(struct drm_i915_private *dev_priv, int exponent)
2744{
2745 return div64_u64(1000000000ULL * (2ULL << exponent),
2746 1000ULL * INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz);
2747}
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764static int read_properties_unlocked(struct drm_i915_private *dev_priv,
2765 u64 __user *uprops,
2766 u32 n_props,
2767 struct perf_open_properties *props)
2768{
2769 u64 __user *uprop = uprops;
2770 u32 i;
2771
2772 memset(props, 0, sizeof(struct perf_open_properties));
2773
2774 if (!n_props) {
2775 DRM_DEBUG("No i915 perf properties given\n");
2776 return -EINVAL;
2777 }
2778
2779
2780
2781
2782
2783
2784
2785 if (n_props >= DRM_I915_PERF_PROP_MAX) {
2786 DRM_DEBUG("More i915 perf properties specified than exist\n");
2787 return -EINVAL;
2788 }
2789
2790 for (i = 0; i < n_props; i++) {
2791 u64 oa_period, oa_freq_hz;
2792 u64 id, value;
2793 int ret;
2794
2795 ret = get_user(id, uprop);
2796 if (ret)
2797 return ret;
2798
2799 ret = get_user(value, uprop + 1);
2800 if (ret)
2801 return ret;
2802
2803 if (id == 0 || id >= DRM_I915_PERF_PROP_MAX) {
2804 DRM_DEBUG("Unknown i915 perf property ID\n");
2805 return -EINVAL;
2806 }
2807
2808 switch ((enum drm_i915_perf_property_id)id) {
2809 case DRM_I915_PERF_PROP_CTX_HANDLE:
2810 props->single_context = 1;
2811 props->ctx_handle = value;
2812 break;
2813 case DRM_I915_PERF_PROP_SAMPLE_OA:
2814 if (value)
2815 props->sample_flags |= SAMPLE_OA_REPORT;
2816 break;
2817 case DRM_I915_PERF_PROP_OA_METRICS_SET:
2818 if (value == 0) {
2819 DRM_DEBUG("Unknown OA metric set ID\n");
2820 return -EINVAL;
2821 }
2822 props->metrics_set = value;
2823 break;
2824 case DRM_I915_PERF_PROP_OA_FORMAT:
2825 if (value == 0 || value >= I915_OA_FORMAT_MAX) {
2826 DRM_DEBUG("Out-of-range OA report format %llu\n",
2827 value);
2828 return -EINVAL;
2829 }
2830 if (!dev_priv->perf.oa.oa_formats[value].size) {
2831 DRM_DEBUG("Unsupported OA report format %llu\n",
2832 value);
2833 return -EINVAL;
2834 }
2835 props->oa_format = value;
2836 break;
2837 case DRM_I915_PERF_PROP_OA_EXPONENT:
2838 if (value > OA_EXPONENT_MAX) {
2839 DRM_DEBUG("OA timer exponent too high (> %u)\n",
2840 OA_EXPONENT_MAX);
2841 return -EINVAL;
2842 }
2843
2844
2845
2846
2847
2848
2849
2850 BUILD_BUG_ON(sizeof(oa_period) != 8);
2851 oa_period = oa_exponent_to_ns(dev_priv, value);
2852
2853
2854
2855
2856
2857
2858
2859 if (oa_period <= NSEC_PER_SEC) {
2860 u64 tmp = NSEC_PER_SEC;
2861 do_div(tmp, oa_period);
2862 oa_freq_hz = tmp;
2863 } else
2864 oa_freq_hz = 0;
2865
2866 if (oa_freq_hz > i915_oa_max_sample_rate &&
2867 !capable(CAP_SYS_ADMIN)) {
2868 DRM_DEBUG("OA exponent would exceed the max sampling frequency (sysctl dev.i915.oa_max_sample_rate) %uHz without root privileges\n",
2869 i915_oa_max_sample_rate);
2870 return -EACCES;
2871 }
2872
2873 props->oa_periodic = true;
2874 props->oa_period_exponent = value;
2875 break;
2876 case DRM_I915_PERF_PROP_MAX:
2877 MISSING_CASE(id);
2878 return -EINVAL;
2879 }
2880
2881 uprop += 2;
2882 }
2883
2884 return 0;
2885}
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911int i915_perf_open_ioctl(struct drm_device *dev, void *data,
2912 struct drm_file *file)
2913{
2914 struct drm_i915_private *dev_priv = dev->dev_private;
2915 struct drm_i915_perf_open_param *param = data;
2916 struct perf_open_properties props;
2917 u32 known_open_flags;
2918 int ret;
2919
2920 if (!dev_priv->perf.initialized) {
2921 DRM_DEBUG("i915 perf interface not available for this system\n");
2922 return -ENOTSUPP;
2923 }
2924
2925 known_open_flags = I915_PERF_FLAG_FD_CLOEXEC |
2926 I915_PERF_FLAG_FD_NONBLOCK |
2927 I915_PERF_FLAG_DISABLED;
2928 if (param->flags & ~known_open_flags) {
2929 DRM_DEBUG("Unknown drm_i915_perf_open_param flag\n");
2930 return -EINVAL;
2931 }
2932
2933 ret = read_properties_unlocked(dev_priv,
2934 u64_to_user_ptr(param->properties_ptr),
2935 param->num_properties,
2936 &props);
2937 if (ret)
2938 return ret;
2939
2940 mutex_lock(&dev_priv->perf.lock);
2941 ret = i915_perf_open_ioctl_locked(dev_priv, param, &props, file);
2942 mutex_unlock(&dev_priv->perf.lock);
2943
2944 return ret;
2945}
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955void i915_perf_register(struct drm_i915_private *dev_priv)
2956{
2957 int ret;
2958
2959 if (!dev_priv->perf.initialized)
2960 return;
2961
2962
2963
2964
2965
2966 mutex_lock(&dev_priv->perf.lock);
2967
2968 dev_priv->perf.metrics_kobj =
2969 kobject_create_and_add("metrics",
2970 &dev_priv->drm.primary->kdev->kobj);
2971 if (!dev_priv->perf.metrics_kobj)
2972 goto exit;
2973
2974 sysfs_attr_init(&dev_priv->perf.oa.test_config.sysfs_metric_id.attr);
2975
2976 if (IS_HASWELL(dev_priv)) {
2977 i915_perf_load_test_config_hsw(dev_priv);
2978 } else if (IS_BROADWELL(dev_priv)) {
2979 i915_perf_load_test_config_bdw(dev_priv);
2980 } else if (IS_CHERRYVIEW(dev_priv)) {
2981 i915_perf_load_test_config_chv(dev_priv);
2982 } else if (IS_SKYLAKE(dev_priv)) {
2983 if (IS_SKL_GT2(dev_priv))
2984 i915_perf_load_test_config_sklgt2(dev_priv);
2985 else if (IS_SKL_GT3(dev_priv))
2986 i915_perf_load_test_config_sklgt3(dev_priv);
2987 else if (IS_SKL_GT4(dev_priv))
2988 i915_perf_load_test_config_sklgt4(dev_priv);
2989 } else if (IS_BROXTON(dev_priv)) {
2990 i915_perf_load_test_config_bxt(dev_priv);
2991 } else if (IS_KABYLAKE(dev_priv)) {
2992 if (IS_KBL_GT2(dev_priv))
2993 i915_perf_load_test_config_kblgt2(dev_priv);
2994 else if (IS_KBL_GT3(dev_priv))
2995 i915_perf_load_test_config_kblgt3(dev_priv);
2996 } else if (IS_GEMINILAKE(dev_priv)) {
2997 i915_perf_load_test_config_glk(dev_priv);
2998 } else if (IS_COFFEELAKE(dev_priv)) {
2999 if (IS_CFL_GT2(dev_priv))
3000 i915_perf_load_test_config_cflgt2(dev_priv);
3001 if (IS_CFL_GT3(dev_priv))
3002 i915_perf_load_test_config_cflgt3(dev_priv);
3003 } else if (IS_CANNONLAKE(dev_priv)) {
3004 i915_perf_load_test_config_cnl(dev_priv);
3005 } else if (IS_ICELAKE(dev_priv)) {
3006 i915_perf_load_test_config_icl(dev_priv);
3007 }
3008
3009 if (dev_priv->perf.oa.test_config.id == 0)
3010 goto sysfs_error;
3011
3012 ret = sysfs_create_group(dev_priv->perf.metrics_kobj,
3013 &dev_priv->perf.oa.test_config.sysfs_metric);
3014 if (ret)
3015 goto sysfs_error;
3016
3017 atomic_set(&dev_priv->perf.oa.test_config.ref_count, 1);
3018
3019 goto exit;
3020
3021sysfs_error:
3022 kobject_put(dev_priv->perf.metrics_kobj);
3023 dev_priv->perf.metrics_kobj = NULL;
3024
3025exit:
3026 mutex_unlock(&dev_priv->perf.lock);
3027}
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038void i915_perf_unregister(struct drm_i915_private *dev_priv)
3039{
3040 if (!dev_priv->perf.metrics_kobj)
3041 return;
3042
3043 sysfs_remove_group(dev_priv->perf.metrics_kobj,
3044 &dev_priv->perf.oa.test_config.sysfs_metric);
3045
3046 kobject_put(dev_priv->perf.metrics_kobj);
3047 dev_priv->perf.metrics_kobj = NULL;
3048}
3049
3050static bool gen8_is_valid_flex_addr(struct drm_i915_private *dev_priv, u32 addr)
3051{
3052 static const i915_reg_t flex_eu_regs[] = {
3053 EU_PERF_CNTL0,
3054 EU_PERF_CNTL1,
3055 EU_PERF_CNTL2,
3056 EU_PERF_CNTL3,
3057 EU_PERF_CNTL4,
3058 EU_PERF_CNTL5,
3059 EU_PERF_CNTL6,
3060 };
3061 int i;
3062
3063 for (i = 0; i < ARRAY_SIZE(flex_eu_regs); i++) {
3064 if (i915_mmio_reg_offset(flex_eu_regs[i]) == addr)
3065 return true;
3066 }
3067 return false;
3068}
3069
3070static bool gen7_is_valid_b_counter_addr(struct drm_i915_private *dev_priv, u32 addr)
3071{
3072 return (addr >= i915_mmio_reg_offset(OASTARTTRIG1) &&
3073 addr <= i915_mmio_reg_offset(OASTARTTRIG8)) ||
3074 (addr >= i915_mmio_reg_offset(OAREPORTTRIG1) &&
3075 addr <= i915_mmio_reg_offset(OAREPORTTRIG8)) ||
3076 (addr >= i915_mmio_reg_offset(OACEC0_0) &&
3077 addr <= i915_mmio_reg_offset(OACEC7_1));
3078}
3079
3080static bool gen7_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
3081{
3082 return addr == i915_mmio_reg_offset(HALF_SLICE_CHICKEN2) ||
3083 (addr >= i915_mmio_reg_offset(MICRO_BP0_0) &&
3084 addr <= i915_mmio_reg_offset(NOA_WRITE)) ||
3085 (addr >= i915_mmio_reg_offset(OA_PERFCNT1_LO) &&
3086 addr <= i915_mmio_reg_offset(OA_PERFCNT2_HI)) ||
3087 (addr >= i915_mmio_reg_offset(OA_PERFMATRIX_LO) &&
3088 addr <= i915_mmio_reg_offset(OA_PERFMATRIX_HI));
3089}
3090
3091static bool gen8_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
3092{
3093 return gen7_is_valid_mux_addr(dev_priv, addr) ||
3094 addr == i915_mmio_reg_offset(WAIT_FOR_RC6_EXIT) ||
3095 (addr >= i915_mmio_reg_offset(RPM_CONFIG0) &&
3096 addr <= i915_mmio_reg_offset(NOA_CONFIG(8)));
3097}
3098
3099static bool gen10_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
3100{
3101 return gen8_is_valid_mux_addr(dev_priv, addr) ||
3102 (addr >= i915_mmio_reg_offset(OA_PERFCNT3_LO) &&
3103 addr <= i915_mmio_reg_offset(OA_PERFCNT4_HI));
3104}
3105
3106static bool hsw_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
3107{
3108 return gen7_is_valid_mux_addr(dev_priv, addr) ||
3109 (addr >= 0x25100 && addr <= 0x2FF90) ||
3110 (addr >= i915_mmio_reg_offset(HSW_MBVID2_NOA0) &&
3111 addr <= i915_mmio_reg_offset(HSW_MBVID2_NOA9)) ||
3112 addr == i915_mmio_reg_offset(HSW_MBVID2_MISR0);
3113}
3114
3115static bool chv_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr)
3116{
3117 return gen7_is_valid_mux_addr(dev_priv, addr) ||
3118 (addr >= 0x182300 && addr <= 0x1823A4);
3119}
3120
3121static uint32_t mask_reg_value(u32 reg, u32 val)
3122{
3123
3124
3125
3126
3127 if (i915_mmio_reg_offset(HALF_SLICE_CHICKEN2) == reg)
3128 val = val & ~_MASKED_BIT_ENABLE(GEN8_ST_PO_DISABLE);
3129
3130
3131
3132
3133
3134 if (i915_mmio_reg_offset(WAIT_FOR_RC6_EXIT) == reg)
3135 val = val & ~_MASKED_BIT_ENABLE(HSW_WAIT_FOR_RC6_EXIT_ENABLE);
3136
3137 return val;
3138}
3139
3140static struct i915_oa_reg *alloc_oa_regs(struct drm_i915_private *dev_priv,
3141 bool (*is_valid)(struct drm_i915_private *dev_priv, u32 addr),
3142 u32 __user *regs,
3143 u32 n_regs)
3144{
3145 struct i915_oa_reg *oa_regs;
3146 int err;
3147 u32 i;
3148
3149 if (!n_regs)
3150 return NULL;
3151
3152 if (!access_ok(VERIFY_READ, regs, n_regs * sizeof(u32) * 2))
3153 return ERR_PTR(-EFAULT);
3154
3155
3156 GEM_BUG_ON(!is_valid);
3157 if (!is_valid)
3158 return ERR_PTR(-EINVAL);
3159
3160 oa_regs = kmalloc_array(n_regs, sizeof(*oa_regs), GFP_KERNEL);
3161 if (!oa_regs)
3162 return ERR_PTR(-ENOMEM);
3163
3164 for (i = 0; i < n_regs; i++) {
3165 u32 addr, value;
3166
3167 err = get_user(addr, regs);
3168 if (err)
3169 goto addr_err;
3170
3171 if (!is_valid(dev_priv, addr)) {
3172 DRM_DEBUG("Invalid oa_reg address: %X\n", addr);
3173 err = -EINVAL;
3174 goto addr_err;
3175 }
3176
3177 err = get_user(value, regs + 1);
3178 if (err)
3179 goto addr_err;
3180
3181 oa_regs[i].addr = _MMIO(addr);
3182 oa_regs[i].value = mask_reg_value(addr, value);
3183
3184 regs += 2;
3185 }
3186
3187 return oa_regs;
3188
3189addr_err:
3190 kfree(oa_regs);
3191 return ERR_PTR(err);
3192}
3193
3194static ssize_t show_dynamic_id(struct device *dev,
3195 struct device_attribute *attr,
3196 char *buf)
3197{
3198 struct i915_oa_config *oa_config =
3199 container_of(attr, typeof(*oa_config), sysfs_metric_id);
3200
3201 return sprintf(buf, "%d\n", oa_config->id);
3202}
3203
3204static int create_dynamic_oa_sysfs_entry(struct drm_i915_private *dev_priv,
3205 struct i915_oa_config *oa_config)
3206{
3207 sysfs_attr_init(&oa_config->sysfs_metric_id.attr);
3208 oa_config->sysfs_metric_id.attr.name = "id";
3209 oa_config->sysfs_metric_id.attr.mode = S_IRUGO;
3210 oa_config->sysfs_metric_id.show = show_dynamic_id;
3211 oa_config->sysfs_metric_id.store = NULL;
3212
3213 oa_config->attrs[0] = &oa_config->sysfs_metric_id.attr;
3214 oa_config->attrs[1] = NULL;
3215
3216 oa_config->sysfs_metric.name = oa_config->uuid;
3217 oa_config->sysfs_metric.attrs = oa_config->attrs;
3218
3219 return sysfs_create_group(dev_priv->perf.metrics_kobj,
3220 &oa_config->sysfs_metric);
3221}
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
3237 struct drm_file *file)
3238{
3239 struct drm_i915_private *dev_priv = dev->dev_private;
3240 struct drm_i915_perf_oa_config *args = data;
3241 struct i915_oa_config *oa_config, *tmp;
3242 int err, id;
3243
3244 if (!dev_priv->perf.initialized) {
3245 DRM_DEBUG("i915 perf interface not available for this system\n");
3246 return -ENOTSUPP;
3247 }
3248
3249 if (!dev_priv->perf.metrics_kobj) {
3250 DRM_DEBUG("OA metrics weren't advertised via sysfs\n");
3251 return -EINVAL;
3252 }
3253
3254 if (i915_perf_stream_paranoid && !capable(CAP_SYS_ADMIN)) {
3255 DRM_DEBUG("Insufficient privileges to add i915 OA config\n");
3256 return -EACCES;
3257 }
3258
3259 if ((!args->mux_regs_ptr || !args->n_mux_regs) &&
3260 (!args->boolean_regs_ptr || !args->n_boolean_regs) &&
3261 (!args->flex_regs_ptr || !args->n_flex_regs)) {
3262 DRM_DEBUG("No OA registers given\n");
3263 return -EINVAL;
3264 }
3265
3266 oa_config = kzalloc(sizeof(*oa_config), GFP_KERNEL);
3267 if (!oa_config) {
3268 DRM_DEBUG("Failed to allocate memory for the OA config\n");
3269 return -ENOMEM;
3270 }
3271
3272 atomic_set(&oa_config->ref_count, 1);
3273
3274 if (!uuid_is_valid(args->uuid)) {
3275 DRM_DEBUG("Invalid uuid format for OA config\n");
3276 err = -EINVAL;
3277 goto reg_err;
3278 }
3279
3280
3281
3282
3283 memcpy(oa_config->uuid, args->uuid, sizeof(args->uuid));
3284
3285 oa_config->mux_regs_len = args->n_mux_regs;
3286 oa_config->mux_regs =
3287 alloc_oa_regs(dev_priv,
3288 dev_priv->perf.oa.ops.is_valid_mux_reg,
3289 u64_to_user_ptr(args->mux_regs_ptr),
3290 args->n_mux_regs);
3291
3292 if (IS_ERR(oa_config->mux_regs)) {
3293 DRM_DEBUG("Failed to create OA config for mux_regs\n");
3294 err = PTR_ERR(oa_config->mux_regs);
3295 goto reg_err;
3296 }
3297
3298 oa_config->b_counter_regs_len = args->n_boolean_regs;
3299 oa_config->b_counter_regs =
3300 alloc_oa_regs(dev_priv,
3301 dev_priv->perf.oa.ops.is_valid_b_counter_reg,
3302 u64_to_user_ptr(args->boolean_regs_ptr),
3303 args->n_boolean_regs);
3304
3305 if (IS_ERR(oa_config->b_counter_regs)) {
3306 DRM_DEBUG("Failed to create OA config for b_counter_regs\n");
3307 err = PTR_ERR(oa_config->b_counter_regs);
3308 goto reg_err;
3309 }
3310
3311 if (INTEL_GEN(dev_priv) < 8) {
3312 if (args->n_flex_regs != 0) {
3313 err = -EINVAL;
3314 goto reg_err;
3315 }
3316 } else {
3317 oa_config->flex_regs_len = args->n_flex_regs;
3318 oa_config->flex_regs =
3319 alloc_oa_regs(dev_priv,
3320 dev_priv->perf.oa.ops.is_valid_flex_reg,
3321 u64_to_user_ptr(args->flex_regs_ptr),
3322 args->n_flex_regs);
3323
3324 if (IS_ERR(oa_config->flex_regs)) {
3325 DRM_DEBUG("Failed to create OA config for flex_regs\n");
3326 err = PTR_ERR(oa_config->flex_regs);
3327 goto reg_err;
3328 }
3329 }
3330
3331 err = mutex_lock_interruptible(&dev_priv->perf.metrics_lock);
3332 if (err)
3333 goto reg_err;
3334
3335
3336
3337
3338 idr_for_each_entry(&dev_priv->perf.metrics_idr, tmp, id) {
3339 if (!strcmp(tmp->uuid, oa_config->uuid)) {
3340 DRM_DEBUG("OA config already exists with this uuid\n");
3341 err = -EADDRINUSE;
3342 goto sysfs_err;
3343 }
3344 }
3345
3346 err = create_dynamic_oa_sysfs_entry(dev_priv, oa_config);
3347 if (err) {
3348 DRM_DEBUG("Failed to create sysfs entry for OA config\n");
3349 goto sysfs_err;
3350 }
3351
3352
3353 oa_config->id = idr_alloc(&dev_priv->perf.metrics_idr,
3354 oa_config, 2,
3355 0, GFP_KERNEL);
3356 if (oa_config->id < 0) {
3357 DRM_DEBUG("Failed to create sysfs entry for OA config\n");
3358 err = oa_config->id;
3359 goto sysfs_err;
3360 }
3361
3362 mutex_unlock(&dev_priv->perf.metrics_lock);
3363
3364 DRM_DEBUG("Added config %s id=%i\n", oa_config->uuid, oa_config->id);
3365
3366 return oa_config->id;
3367
3368sysfs_err:
3369 mutex_unlock(&dev_priv->perf.metrics_lock);
3370reg_err:
3371 put_oa_config(dev_priv, oa_config);
3372 DRM_DEBUG("Failed to add new OA config\n");
3373 return err;
3374}
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
3388 struct drm_file *file)
3389{
3390 struct drm_i915_private *dev_priv = dev->dev_private;
3391 u64 *arg = data;
3392 struct i915_oa_config *oa_config;
3393 int ret;
3394
3395 if (!dev_priv->perf.initialized) {
3396 DRM_DEBUG("i915 perf interface not available for this system\n");
3397 return -ENOTSUPP;
3398 }
3399
3400 if (i915_perf_stream_paranoid && !capable(CAP_SYS_ADMIN)) {
3401 DRM_DEBUG("Insufficient privileges to remove i915 OA config\n");
3402 return -EACCES;
3403 }
3404
3405 ret = mutex_lock_interruptible(&dev_priv->perf.metrics_lock);
3406 if (ret)
3407 goto lock_err;
3408
3409 oa_config = idr_find(&dev_priv->perf.metrics_idr, *arg);
3410 if (!oa_config) {
3411 DRM_DEBUG("Failed to remove unknown OA config\n");
3412 ret = -ENOENT;
3413 goto config_err;
3414 }
3415
3416 GEM_BUG_ON(*arg != oa_config->id);
3417
3418 sysfs_remove_group(dev_priv->perf.metrics_kobj,
3419 &oa_config->sysfs_metric);
3420
3421 idr_remove(&dev_priv->perf.metrics_idr, *arg);
3422
3423 DRM_DEBUG("Removed config %s id=%i\n", oa_config->uuid, oa_config->id);
3424
3425 put_oa_config(dev_priv, oa_config);
3426
3427config_err:
3428 mutex_unlock(&dev_priv->perf.metrics_lock);
3429lock_err:
3430 return ret;
3431}
3432
3433static struct ctl_table oa_table[] = {
3434 {
3435 .procname = "perf_stream_paranoid",
3436 .data = &i915_perf_stream_paranoid,
3437 .maxlen = sizeof(i915_perf_stream_paranoid),
3438 .mode = 0644,
3439 .proc_handler = proc_dointvec_minmax,
3440 .extra1 = &zero,
3441 .extra2 = &one,
3442 },
3443 {
3444 .procname = "oa_max_sample_rate",
3445 .data = &i915_oa_max_sample_rate,
3446 .maxlen = sizeof(i915_oa_max_sample_rate),
3447 .mode = 0644,
3448 .proc_handler = proc_dointvec_minmax,
3449 .extra1 = &zero,
3450 .extra2 = &oa_sample_rate_hard_limit,
3451 },
3452 {}
3453};
3454
3455static struct ctl_table i915_root[] = {
3456 {
3457 .procname = "i915",
3458 .maxlen = 0,
3459 .mode = 0555,
3460 .child = oa_table,
3461 },
3462 {}
3463};
3464
3465static struct ctl_table dev_root[] = {
3466 {
3467 .procname = "dev",
3468 .maxlen = 0,
3469 .mode = 0555,
3470 .child = i915_root,
3471 },
3472 {}
3473};
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484void i915_perf_init(struct drm_i915_private *dev_priv)
3485{
3486 if (IS_HASWELL(dev_priv)) {
3487 dev_priv->perf.oa.ops.is_valid_b_counter_reg =
3488 gen7_is_valid_b_counter_addr;
3489 dev_priv->perf.oa.ops.is_valid_mux_reg =
3490 hsw_is_valid_mux_addr;
3491 dev_priv->perf.oa.ops.is_valid_flex_reg = NULL;
3492 dev_priv->perf.oa.ops.init_oa_buffer = gen7_init_oa_buffer;
3493 dev_priv->perf.oa.ops.enable_metric_set = hsw_enable_metric_set;
3494 dev_priv->perf.oa.ops.disable_metric_set = hsw_disable_metric_set;
3495 dev_priv->perf.oa.ops.oa_enable = gen7_oa_enable;
3496 dev_priv->perf.oa.ops.oa_disable = gen7_oa_disable;
3497 dev_priv->perf.oa.ops.read = gen7_oa_read;
3498 dev_priv->perf.oa.ops.oa_hw_tail_read =
3499 gen7_oa_hw_tail_read;
3500
3501 dev_priv->perf.oa.oa_formats = hsw_oa_formats;
3502 } else if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) {
3503
3504
3505
3506
3507
3508
3509 dev_priv->perf.oa.oa_formats = gen8_plus_oa_formats;
3510
3511 dev_priv->perf.oa.ops.init_oa_buffer = gen8_init_oa_buffer;
3512 dev_priv->perf.oa.ops.oa_enable = gen8_oa_enable;
3513 dev_priv->perf.oa.ops.oa_disable = gen8_oa_disable;
3514 dev_priv->perf.oa.ops.read = gen8_oa_read;
3515 dev_priv->perf.oa.ops.oa_hw_tail_read = gen8_oa_hw_tail_read;
3516
3517 if (IS_GEN8(dev_priv) || IS_GEN9(dev_priv)) {
3518 dev_priv->perf.oa.ops.is_valid_b_counter_reg =
3519 gen7_is_valid_b_counter_addr;
3520 dev_priv->perf.oa.ops.is_valid_mux_reg =
3521 gen8_is_valid_mux_addr;
3522 dev_priv->perf.oa.ops.is_valid_flex_reg =
3523 gen8_is_valid_flex_addr;
3524
3525 if (IS_CHERRYVIEW(dev_priv)) {
3526 dev_priv->perf.oa.ops.is_valid_mux_reg =
3527 chv_is_valid_mux_addr;
3528 }
3529
3530 dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set;
3531 dev_priv->perf.oa.ops.disable_metric_set = gen8_disable_metric_set;
3532
3533 if (IS_GEN8(dev_priv)) {
3534 dev_priv->perf.oa.ctx_oactxctrl_offset = 0x120;
3535 dev_priv->perf.oa.ctx_flexeu0_offset = 0x2ce;
3536
3537 dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<25);
3538 } else {
3539 dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128;
3540 dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de;
3541
3542 dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16);
3543 }
3544 } else if (IS_GEN(dev_priv, 10, 11)) {
3545 dev_priv->perf.oa.ops.is_valid_b_counter_reg =
3546 gen7_is_valid_b_counter_addr;
3547 dev_priv->perf.oa.ops.is_valid_mux_reg =
3548 gen10_is_valid_mux_addr;
3549 dev_priv->perf.oa.ops.is_valid_flex_reg =
3550 gen8_is_valid_flex_addr;
3551
3552 dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set;
3553 dev_priv->perf.oa.ops.disable_metric_set = gen10_disable_metric_set;
3554
3555 dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128;
3556 dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de;
3557
3558 dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16);
3559 }
3560 }
3561
3562 if (dev_priv->perf.oa.ops.enable_metric_set) {
3563 hrtimer_init(&dev_priv->perf.oa.poll_check_timer,
3564 CLOCK_MONOTONIC, HRTIMER_MODE_REL);
3565 dev_priv->perf.oa.poll_check_timer.function = oa_poll_check_timer_cb;
3566 init_waitqueue_head(&dev_priv->perf.oa.poll_wq);
3567
3568 INIT_LIST_HEAD(&dev_priv->perf.streams);
3569 mutex_init(&dev_priv->perf.lock);
3570 spin_lock_init(&dev_priv->perf.oa.oa_buffer.ptr_lock);
3571
3572 oa_sample_rate_hard_limit = 1000 *
3573 (INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz / 2);
3574 dev_priv->perf.sysctl_header = register_sysctl_table(dev_root);
3575
3576 mutex_init(&dev_priv->perf.metrics_lock);
3577 idr_init(&dev_priv->perf.metrics_idr);
3578
3579 dev_priv->perf.initialized = true;
3580 }
3581}
3582
3583static int destroy_config(int id, void *p, void *data)
3584{
3585 struct drm_i915_private *dev_priv = data;
3586 struct i915_oa_config *oa_config = p;
3587
3588 put_oa_config(dev_priv, oa_config);
3589
3590 return 0;
3591}
3592
3593
3594
3595
3596
3597void i915_perf_fini(struct drm_i915_private *dev_priv)
3598{
3599 if (!dev_priv->perf.initialized)
3600 return;
3601
3602 idr_for_each(&dev_priv->perf.metrics_idr, destroy_config, dev_priv);
3603 idr_destroy(&dev_priv->perf.metrics_idr);
3604
3605 unregister_sysctl_table(dev_priv->perf.sysctl_header);
3606
3607 memset(&dev_priv->perf.oa.ops, 0, sizeof(dev_priv->perf.oa.ops));
3608
3609 dev_priv->perf.initialized = false;
3610}
3611