xref: /linux/drivers/gpu/drm/msm/msm_perfcntr.c (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4  */
5 
6 #include "drm/drm_file.h"
7 #include "drm/msm_drm.h"
8 
9 #include "linux/anon_inodes.h"
10 #include "linux/gfp_types.h"
11 #include "linux/poll.h"
12 #include "linux/slab.h"
13 
14 #include "msm_drv.h"
15 #include "msm_gpu.h"
16 #include "msm_perfcntr.h"
17 
18 #include "adreno/adreno_gpu.h"
19 
20 /* space used: */
21 #define fifo_count(stream) \
22 	(CIRC_CNT((stream)->fifo.head, (stream)->fifo.tail, (stream)->fifo_size))
23 #define fifo_count_to_end(stream) \
24 	(CIRC_CNT_TO_END(smp_load_acquire(&(stream)->fifo.head), (stream)->fifo.tail, (stream)->fifo_size))
25 /* space available: */
26 #define fifo_space(stream) \
27 	(CIRC_SPACE((stream)->fifo.head, (stream)->fifo.tail, (stream)->fifo_size))
28 
29 static int
30 msm_perfcntr_resume_locked(struct msm_perfcntr_stream *stream)
31 {
32 	if (!stream)
33 		return 0;
34 
35 	/* Reprogram SEL regs on highest priority rb: */
36 	struct msm_ringbuffer *ring = stream->gpu->rb[0];
37 
38 	queue_work(ring->sched.submit_wq, &stream->sel_work);
39 
40 	hrtimer_start(&stream->sample_timer,
41 		      ns_to_ktime(stream->sample_period_ns),
42 		      HRTIMER_MODE_REL_PINNED);
43 
44 	return 0;
45 }
46 
47 int
48 msm_perfcntr_resume(struct msm_gpu *gpu)
49 {
50 	if (!gpu->perfcntrs)
51 		return 0;
52 	guard(mutex)(&gpu->perfcntr_lock);
53 	return msm_perfcntr_resume_locked(gpu->perfcntrs->stream);
54 }
55 
56 static void
57 msm_perfcntr_suspend_locked(struct msm_perfcntr_stream *stream)
58 {
59 	if (!stream)
60 		return;
61 
62 	hrtimer_cancel(&stream->sample_timer);
63 	kthread_cancel_work_sync(&stream->sample_work);
64 
65 	/*
66 	 * We can't use cancel_work_sync() here, since sel_work acquires
67 	 * gpu->lock which (a) in suspend path can already be held, or
68 	 * (b) in release path would invert the order of gpu->lock and
69 	 * gpu->perfcntr_lock.  Either would cause deadlock.
70 	 */
71 	cancel_work(&stream->sel_work);
72 
73 	stream->sel_fence = ++stream->gpu->perfcntrs->sel_seqno;
74 	stream->seqno = 0;
75 }
76 
77 void
78 msm_perfcntr_suspend(struct msm_gpu *gpu)
79 {
80 	if (!gpu->perfcntrs)
81 		return;
82 	guard(mutex)(&gpu->perfcntr_lock);
83 	msm_perfcntr_suspend_locked(gpu->perfcntrs->stream);
84 }
85 
86 static int
87 msm_perfcntrs_stream_release(struct inode *inode, struct file *file)
88 {
89 	struct msm_perfcntr_stream *stream = file->private_data;
90 	struct msm_gpu *gpu = stream->gpu;
91 
92 	scoped_guard (mutex, &gpu->perfcntr_lock) {
93 		struct msm_perfcntr_state *perfcntrs = gpu->perfcntrs;
94 
95 		msm_perfcntr_suspend_locked(stream);
96 		perfcntrs->stream = NULL;
97 
98 		/* release previously allocated counters: */
99 		for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++)
100 			perfcntrs->groups[i]->allocated_counters = 0;
101 	}
102 
103 	/*
104 	 * In the suspend path we use async cancel_work(), to avoid blocking
105 	 * on sel_work, which acquires gpu->lock (which could deadlock since
106 	 * other paths acquire gpu->lock before perfcntr_lock) or already
107 	 * hold gpu->lock.
108 	 *
109 	 * But since we are freeing the stream, after dropping perfcntr_lock
110 	 * we need to block until sel_work is done:
111 	 */
112 	cancel_work_sync(&stream->sel_work);
113 
114 	kfree(stream->group_idx);
115 	kfree(stream->fifo.buf);
116 	kfree(stream);
117 
118 	return 0;
119 }
120 
121 static __poll_t
122 msm_perfcntrs_stream_poll(struct file *file, poll_table *wait)
123 {
124 	struct msm_perfcntr_stream *stream = file->private_data;
125 	__poll_t events = 0;
126 
127 	poll_wait(file, &stream->poll_wq, wait);
128 
129 	/* Are there samples to read? */
130 	if (fifo_count(stream) > 0)
131 		events |= EPOLLIN;
132 
133 	return events;
134 }
135 
136 static ssize_t
137 msm_perfcntrs_stream_read(struct file *file, char __user *buf,
138 			  size_t count, loff_t *ppos)
139 {
140 	struct msm_perfcntr_stream *stream = file->private_data;
141 	int ret;
142 
143 	if (!(file->f_flags & O_NONBLOCK)) {
144 		ret = wait_event_interruptible(stream->poll_wq,
145 					       fifo_count(stream) > 0);
146 		if (ret)
147 			return ret;
148 	}
149 
150 	guard(mutex)(&stream->read_lock);
151 
152 	struct circ_buf *fifo = &stream->fifo;
153 	const char *fptr = &fifo->buf[fifo->tail];
154 
155 	count = min_t(size_t, count, fifo_count_to_end(stream));
156 	if (!count)
157 		return -EAGAIN;
158 	if (copy_to_user(buf, fptr, count))
159 		return -EFAULT;
160 
161 	smp_store_release(&fifo->tail, (fifo->tail + count) & (stream->fifo_size - 1));
162 	*ppos += count;
163 
164 	return count;
165 }
166 
167 static const struct file_operations stream_fops = {
168 	.owner		= THIS_MODULE,
169 	.release	= msm_perfcntrs_stream_release,
170 	.poll		= msm_perfcntrs_stream_poll,
171 	.read		= msm_perfcntrs_stream_read,
172 };
173 
174 static void
175 sel_worker(struct work_struct *w)
176 {
177 	struct msm_perfcntr_stream *stream =
178 		container_of(w, typeof(*stream), sel_work);
179 	struct msm_gpu *gpu = stream->gpu;
180 	/* Reprogram SEL regs on highest priority rb: */
181 	struct msm_ringbuffer *ring = stream->gpu->rb[0];
182 
183 	/*
184 	 * If in the process of resuming, wait for that.  Otherwise sel_worker
185 	 * which is enqueued in the resume path can be scheduled before the
186 	 * resume completes.
187 	 */
188 	pm_runtime_barrier(&gpu->pdev->dev);
189 
190 	/*
191 	 * sel_work could end up scheduled before suspend, but running
192 	 * after.  See msm_perfcntr_suspend_locked()
193 	 *
194 	 * So if we end up running sel_work after the GPU is already
195 	 * suspended, just bail.  It will be scheduled again after
196 	 * the GPU is resumed.
197 	 */
198 	if (!pm_runtime_get_if_active(&gpu->pdev->dev))
199 		return;
200 
201 	scoped_guard (mutex, &gpu->lock) {
202 		guard(mutex)(&gpu->perfcntr_lock);
203 
204 		if (stream == gpu->perfcntrs->stream) {
205 			msm_gpu_hw_init(gpu);
206 			gpu->funcs->perfcntr_configure(gpu, ring, stream);
207 		}
208 	}
209 
210 	pm_runtime_put_autosuspend(&gpu->pdev->dev);
211 }
212 
213 static void
214 sample_write(struct msm_perfcntr_stream *stream, int *head, const void *buf, size_t sz)
215 {
216 	/*
217 	 * FIFO size is power-of-two, and guaranteed to have enough space to
218 	 * fit what we are writing.  So we should not hit the wrap-around
219 	 * point writing things that are power-of-two sized
220 	 */
221 	WARN_ON(CIRC_SPACE_TO_END(*head, stream->fifo.tail, stream->fifo_size) < sz);
222 
223 	memcpy(&stream->fifo.buf[*head], buf, sz);
224 
225 	/* Advance head, wrapping around if necessary: */
226 	*head = (*head + sz) & (stream->fifo_size - 1);
227 }
228 
229 static void
230 sample_write_u32(struct msm_perfcntr_stream *stream, int *head, uint32_t val)
231 {
232 	sample_write(stream, head, &val, sizeof(val));
233 }
234 
235 static void
236 sample_write_u64(struct msm_perfcntr_stream *stream, int *head, uint64_t val)
237 {
238 	sample_write(stream, head, &val, sizeof(val));
239 }
240 
241 static void
242 sample_worker(struct kthread_work *work)
243 {
244 	struct msm_perfcntr_stream *stream =
245 		container_of(work, typeof(*stream), sample_work);
246 	struct msm_gpu *gpu = stream->gpu;
247 	struct msm_rbmemptrs *memptrs = gpu->rb[0]->memptrs;
248 
249 	if (memptrs->perfcntr_fence != stream->sel_fence)
250 		return;
251 
252 	/*
253 	 * Ensure we have enough space to capture a sample period's
254 	 * worth of data:
255 	 */
256 	if (stream->period_size > fifo_space(stream)) {
257 		stream->seqno = 0;
258 		return;
259 	}
260 
261 	/* Inhibit IFPC while accessing registers: */
262 	if (gpu->funcs->sysprof_setup)
263 		gpu->funcs->sysprof_setup(gpu, true);
264 
265 	if (gpu->funcs->perfcntr_flush)
266 		gpu->funcs->perfcntr_flush(gpu);
267 
268 	/* Keep local copy of head to avoid updating fifo until the end: */
269 	int head = stream->fifo.head;
270 
271 	/*
272 	 * We expect the GPU to be powered at this point, as the timer
273 	 * and kthread work are canceled/flushed in the suspend path:
274 	 */
275 	sample_write_u64(stream, &head,
276 			 to_adreno_gpu(gpu)->funcs->get_timestamp(gpu));
277 	sample_write_u32(stream, &head, stream->seqno++);
278 	sample_write_u32(stream, &head, 0);
279 
280 	for (unsigned i = 0; i < stream->nr_groups; i++) {
281 		unsigned group_idx = msm_perfcntr_group_idx(stream, i);
282 		unsigned base = msm_perfcntr_counter_base(stream, group_idx);
283 
284 		const struct msm_perfcntr_group *group =
285 			&gpu->perfcntr_groups[group_idx];
286 
287 		struct msm_perfcntr_group_state *group_state =
288 			gpu->perfcntrs->groups[group_idx];
289 
290 		unsigned nr = group_state->allocated_counters;
291 		for (unsigned j = 0; j < nr; j++) {
292 			const struct msm_perfcntr_counter *counter =
293 				&group->counters[j + base];
294 			uint64_t val = gpu_read64(gpu, counter->counter_reg_lo);
295 			sample_write_u64(stream, &head, val);
296 		}
297 	}
298 
299 	/* Re-enable IFPC: */
300 	if (gpu->funcs->sysprof_setup)
301 		gpu->funcs->sysprof_setup(gpu, false);
302 
303 	smp_store_release(&stream->fifo.head, head);
304 	wake_up_all(&stream->poll_wq);
305 }
306 
307 static enum hrtimer_restart
308 sample_timer(struct hrtimer *hrtimer)
309 {
310 	struct msm_perfcntr_stream *stream =
311 		container_of(hrtimer, typeof(*stream), sample_timer);
312 
313 	kthread_queue_work(stream->gpu->worker, &stream->sample_work);
314 
315 	hrtimer_forward_now(hrtimer, ns_to_ktime(stream->sample_period_ns));
316 
317 	return HRTIMER_RESTART;
318 }
319 
320 static int
321 get_group_idx(struct msm_gpu *gpu, const char *name, size_t len)
322 {
323 	for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++) {
324 		const struct msm_perfcntr_group *group =
325 			&gpu->perfcntr_groups[i];
326 		if (!strncmp(group->name, name, len))
327 			return i;
328 	}
329 
330 	return -1;
331 }
332 
333 static int
334 get_available_counters(struct msm_gpu *gpu, int group_idx, uint32_t flags)
335 {
336 	struct msm_perfcntr_state *perfcntrs = gpu->perfcntrs;
337 
338 	/*
339 	 * For local counter reservation, anything that is not used by
340 	 * global perfcntr stream is available:
341 	 */
342 	if (!(flags & MSM_PERFCNTR_STREAM)) {
343 		return gpu->perfcntr_groups[group_idx].num_counters -
344 			perfcntrs->groups[group_idx]->allocated_counters;
345 	}
346 
347 	/*
348 	 * For global counter collection, anything that is not reserved by
349 	 * one or more contexts is available:
350 	 */
351 	guard(mutex)(&gpu->dev->filelist_mutex);
352 
353 	unsigned reserved_counters = 0;
354 	struct drm_file *file;
355 
356 	list_for_each_entry (file, &gpu->dev->filelist, lhead) {
357 		struct msm_context *ctx = file->driver_priv;
358 
359 		if (!ctx || !ctx->perfctx)
360 			continue;
361 
362 		unsigned n = ctx->perfctx->reserved_counters[group_idx];
363 		reserved_counters = max(reserved_counters, n);
364 	}
365 
366 	return gpu->perfcntr_groups[group_idx].num_counters - reserved_counters;
367 }
368 
369 int
370 msm_ioctl_perfcntr_config(struct drm_device *dev, void *data, struct drm_file *file)
371 {
372 	struct msm_drm_private *priv = dev->dev_private;
373 	const struct drm_msm_perfcntr_config *args = data;
374 	struct msm_context *ctx = file->driver_priv;
375 	struct msm_gpu *gpu = priv->gpu;
376 	int stream_fd = 0;
377 
378 	if (!gpu || !gpu->num_perfcntr_groups)
379 		return -ENXIO;
380 
381 	struct msm_perfcntr_state *perfcntrs = gpu->perfcntrs;
382 
383 	/*
384 	 * Validate args that don't require locks/power first:
385 	 */
386 
387 	if (args->flags & ~MSM_PERFCNTR_FLAGS)
388 		return UERR(EINVAL, dev, "invalid flags");
389 
390 	if (args->nr_groups && !args->group_stride)
391 		return UERR(EINVAL, dev, "invalid group_stride");
392 
393 	if (args->nr_groups > gpu->num_perfcntr_groups)
394 		return UERR(EINVAL, dev, "too many groups");
395 
396 	if (args->nr_groups && !args->groups)
397 		return UERR(EINVAL, dev, "no groups");
398 
399 	if (args->flags & MSM_PERFCNTR_STREAM) {
400 		if (!perfmon_capable())
401 			return UERR(EPERM, dev, "invalid permissions");
402 		if (!args->nr_groups)
403 			return UERR(EINVAL, dev, "invalid nr_groups");
404 		if (!args->period)
405 			return UERR(EINVAL, dev, "invalid sampling period");
406 		if (args->bufsz_shift > const_ilog2(SZ_128M))
407 			return UERR(EINVAL, dev, "buffer size too big (>128M)");
408 	} else {
409 		if (args->period)
410 			return UERR(EINVAL, dev, "sampling period not allowed");
411 		if (args->bufsz_shift)
412 			return UERR(EINVAL, dev, "sample buf size not allowed");
413 	}
414 
415 	/*
416 	 * To avoid iterating over the groups multiple times, allocate and setup
417 	 * both a ctx and global stream object.  Only one of the two will be
418 	 * kept in the end.
419 	 */
420 
421 	struct msm_perfcntr_context_state *perfctx __free(kfree) = kzalloc(
422 		struct_size(perfctx, reserved_counters, gpu->num_perfcntr_groups),
423 		GFP_KERNEL);
424 	if (!perfctx)
425 		return -ENOMEM;
426 
427 	struct msm_perfcntr_stream *stream __free(kfree) = kzalloc_obj(*stream);
428 	if (!stream)
429 		return -ENOMEM;
430 
431 	uint8_t *nr_counters __free(kfree) = kzalloc_objs(uint8_t, gpu->num_perfcntr_groups);
432 	if (!nr_counters)
433 		return -ENOMEM;
434 
435 	uint32_t *group_idx __free(kfree) = kzalloc_objs(uint32_t, args->nr_groups);
436 	if (!group_idx)
437 		return -ENOMEM;
438 
439 	stream->gpu = gpu;
440 	stream->sample_period_ns = args->period;
441 	stream->nr_groups = args->nr_groups;
442 	stream->fifo_size = 1ull << args->bufsz_shift;
443 
444 	mutex_init(&stream->read_lock);
445 
446 	guard(mutex)(&gpu->perfcntr_lock);
447 
448 	if (args->flags & MSM_PERFCNTR_STREAM) {
449 		if (perfcntrs->stream)
450 			return UERR(EBUSY, dev, "perfcntr stream already open");
451 	}
452 
453 	size_t bufsz = 16;  /* header size includes seqno and 64b timestamp: */
454 	int ret = 0;
455 
456 	for (unsigned i = 0; i < args->nr_groups; i++) {
457 		struct drm_msm_perfcntr_group g = {0};
458 		size_t sz = min_t(size_t, args->group_stride, sizeof(g));
459 		void __user *userptr =
460 			u64_to_user_ptr(args->groups + (i * args->group_stride));
461 
462 		if (copy_from_user(&g, userptr, sz))
463 			return -EFAULT;
464 
465 		if (g.pad)
466 			return UERR(EINVAL, dev, "groups[%d]: invalid pad", i);
467 
468 		int idx = get_group_idx(gpu, g.group_name, sizeof(g.group_name));
469 
470 		if (idx < 0)
471 			return UERR(EINVAL, dev, "groups[%d]: unknown group", i);
472 
473 		if (nr_counters[idx])
474 			return UERR(EINVAL, dev, "groups[%d]: duplicate group", i);
475 
476 		if (g.nr_countables > gpu->perfcntr_groups[idx].num_counters)
477 			return UERR(EINVAL, dev, "groups[%d]: too many counters", i);
478 
479 		if (args->flags & MSM_PERFCNTR_STREAM) {
480 			if (g.nr_countables && !g.countables)
481 				return UERR(EINVAL, dev, "groups[%d]: no countables", i);
482 		} else {
483 			if (g.countables)
484 				return UERR(EINVAL, dev, "groups[%d]: countables should be NULL", i);
485 		}
486 
487 		int avail_counters = get_available_counters(gpu, idx, args->flags);
488 		if (g.nr_countables > avail_counters) {
489 			/*
490 			 * Defer error return until we process all groups, in
491 			 * case there are other E2BIG groups:
492 			 */
493 			ret = UERR(E2BIG, dev, "groups[%d]: too few counters available", i);
494 
495 			if (args->flags & MSM_PERFCNTR_UPDATE) {
496 				/* Let userspace know how many counters are actually avail: */
497 				g.nr_countables = avail_counters;
498 				if (copy_to_user(userptr, &g, sz))
499 					return -EFAULT;
500 			}
501 		}
502 
503 		group_idx[i] = idx;
504 		perfctx->reserved_counters[idx] = g.nr_countables;
505 
506 		/* +1 to catch duplicate zero sized groups: */
507 		nr_counters[idx] = g.nr_countables + 1;
508 
509 		if (args->flags & MSM_PERFCNTR_STREAM) {
510 			size_t sz = sizeof(uint32_t) * g.nr_countables;
511 			void __user *userptr = u64_to_user_ptr(g.countables);
512 
513 			if (copy_from_user(perfcntrs->groups[idx]->countables, userptr, sz))
514 				return -EFAULT;
515 
516 			/* Samples are 64b per countable: */
517 			bufsz += 2 * sz;
518 		}
519 	}
520 
521 	if (ret)
522 		return ret;
523 
524 	if (args->flags & MSM_PERFCNTR_STREAM) {
525 		/*
526 		 * Validate requested buffer size is large enough for at least
527 		 * a single sample period.
528 		 *
529 		 * Note the circ_buf implementation needs to be 1 byte larger
530 		 * than max it can hold (see CIRC_SPACE()).
531 		 */
532 		if (stream->fifo_size <= bufsz)
533 			return UERR(EINVAL, dev, "required buffer size: %zu", bufsz);
534 
535 		/* There aren't enough counters to hit this limit: */
536 		WARN_ON(bufsz > SZ_128M);
537 
538 		stream->period_size = bufsz;
539 
540 		void *buf __free(kfree) = kmalloc(stream->fifo_size, GFP_KERNEL);
541 		if (!buf)
542 			return -ENOMEM;
543 
544 		FD_PREPARE(fdf, O_CLOEXEC,
545 			   anon_inode_getfile("[msm_perfcntrs]", &stream_fops, stream, 0));
546 		if (fdf.err)
547 			return fdf.err;
548 
549 		INIT_WORK(&stream->sel_work, sel_worker);
550 		kthread_init_work(&stream->sample_work, sample_worker);
551 		init_waitqueue_head(&stream->poll_wq);
552 		hrtimer_setup(&stream->sample_timer, sample_timer,
553 			      CLOCK_MONOTONIC, HRTIMER_MODE_REL);
554 
555 		stream->sel_fence = ++perfcntrs->sel_seqno;
556 		stream->group_idx = no_free_ptr(group_idx);
557 		stream->fifo.buf = no_free_ptr(buf);
558 
559 		/* commit the allocated counters, subtracting off original +1: */
560 		for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++)
561 			perfcntrs->groups[i]->allocated_counters = nr_counters[i] - 1;
562 
563 		perfcntrs->stream = no_free_ptr(stream);
564 
565 		msm_perfcntr_resume_locked(perfcntrs->stream);
566 
567 		stream_fd = fd_publish(fdf);
568 	} else {
569 		kfree(ctx->perfctx);
570 		ctx->perfctx = no_free_ptr(perfctx);
571 	}
572 
573 	return stream_fd;
574 }
575 
576 /**
577  * msm_perfcntr_group_idx - map idx of perfcntr group to group_idx
578  * @stream: The global perfcntr stream
579  * @n: The requested group_idx
580  *
581  * The PERFCNTR_CONFIG ioctl requested N counters/countables per perfcntr
582  * group, but the order of groups is not required to match the order they
583  * are defined in the perfcntr tables (which is not stable/UABI, only the
584  * group names are UABI).
585  *
586  * But the order samples are returned in the stream should match the
587  * order they are requested in the PERFCNTR_CONFIG ioctl.  This helper
588  * handles the order remapping.
589  *
590  * Returns an index into gpu->perfcntr_groups[] and perfcntrs->groups[].
591  */
592 uint32_t
593 msm_perfcntr_group_idx(const struct msm_perfcntr_stream *stream, uint32_t n)
594 {
595 	WARN_ON_ONCE(n >= stream->nr_groups);
596 	return stream->group_idx[n];
597 }
598 
599 /**
600  * msm_perfcntr_counter_base - get idx of the first counter in group
601  * @stream: The global perfcntr stream
602  * @group_idx: the index of the counter group
603  *
604  * For global counter collection, counters are allocated from the end
605  * (last counter) while UMD allocates them from the start (0..N-1).
606  * Since UMD always allocated them from the start this also minimizes
607  * the chance of conflict when using old UMD which predates
608  * PERFCNTR_CONFIG ioctl.
609  *
610  * Returns the index of first counter to use.  An index into
611  * msm_perfcntr_group::counters[].
612  */
613 uint32_t
614 msm_perfcntr_counter_base(const struct msm_perfcntr_stream *stream, uint32_t group_idx)
615 {
616 	struct msm_gpu *gpu = stream->gpu;
617 	struct msm_perfcntr_state *perfcntrs = gpu->perfcntrs;
618 	unsigned num_counters = gpu->perfcntr_groups[group_idx].num_counters;
619 	unsigned allocated_counters = perfcntrs->groups[group_idx]->allocated_counters;
620 
621 	return num_counters - allocated_counters;
622 }
623 
624 static void
625 __msm_perfcntr_cleanup(struct msm_gpu *gpu, struct msm_perfcntr_state *perfcntrs)
626 {
627 	struct device *dev = &gpu->pdev->dev;
628 
629 	for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++)
630 		devm_kfree(dev, perfcntrs->groups[i]);
631 
632 	devm_kfree(dev, perfcntrs);
633 }
634 
635 void
636 msm_perfcntr_cleanup(struct msm_gpu *gpu)
637 {
638 	if (!gpu->perfcntrs)
639 		return;
640 
641 	__msm_perfcntr_cleanup(gpu, gpu->perfcntrs);
642 	gpu->perfcntrs = NULL;
643 }
644 
645 struct msm_perfcntr_state *
646 msm_perfcntr_init(struct msm_gpu *gpu)
647 {
648 	struct msm_perfcntr_state *perfcntrs;
649 	struct device *dev = &gpu->pdev->dev;
650 	size_t sz;
651 
652 	sz = struct_size(perfcntrs, groups, gpu->num_perfcntr_groups);
653 	perfcntrs = devm_kzalloc(dev, sz, GFP_KERNEL);
654 	if (!perfcntrs)
655 		return ERR_PTR(-ENOMEM);
656 
657 	for (unsigned i = 0; i < gpu->num_perfcntr_groups; i++) {
658 		const struct msm_perfcntr_group *group =
659 			&gpu->perfcntr_groups[i];
660 
661 		sz = struct_size(perfcntrs->groups[i], countables, group->num_counters);
662 		perfcntrs->groups[i] = devm_kzalloc(dev, sz, GFP_KERNEL);
663 		if (!perfcntrs->groups[i]) {
664 			__msm_perfcntr_cleanup(gpu, perfcntrs);
665 			return ERR_PTR(-ENOMEM);
666 		}
667 	}
668 
669 	return perfcntrs;
670 }
671