Loading...
Note: File does not exist in v4.6.
1/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
2/* Copyright (c) 2023 Imagination Technologies Ltd. */
3
4#ifndef PVR_DEVICE_H
5#define PVR_DEVICE_H
6
7#include "pvr_ccb.h"
8#include "pvr_device_info.h"
9#include "pvr_fw.h"
10#include "pvr_params.h"
11#include "pvr_rogue_fwif_stream.h"
12#include "pvr_stream.h"
13
14#include <drm/drm_device.h>
15#include <drm/drm_file.h>
16#include <drm/drm_mm.h>
17
18#include <linux/bits.h>
19#include <linux/compiler_attributes.h>
20#include <linux/compiler_types.h>
21#include <linux/io.h>
22#include <linux/iopoll.h>
23#include <linux/kernel.h>
24#include <linux/math.h>
25#include <linux/mutex.h>
26#include <linux/timer.h>
27#include <linux/types.h>
28#include <linux/wait.h>
29#include <linux/workqueue.h>
30#include <linux/xarray.h>
31
32/* Forward declaration from <linux/clk.h>. */
33struct clk;
34
35/* Forward declaration from <linux/firmware.h>. */
36struct firmware;
37
38/**
39 * struct pvr_gpu_id - Hardware GPU ID information for a PowerVR device
40 * @b: Branch ID.
41 * @v: Version ID.
42 * @n: Number of scalable units.
43 * @c: Config ID.
44 */
45struct pvr_gpu_id {
46 u16 b, v, n, c;
47};
48
49/**
50 * struct pvr_fw_version - Firmware version information
51 * @major: Major version number.
52 * @minor: Minor version number.
53 */
54struct pvr_fw_version {
55 u16 major, minor;
56};
57
58/**
59 * struct pvr_device - powervr-specific wrapper for &struct drm_device
60 */
61struct pvr_device {
62 /**
63 * @base: The underlying &struct drm_device.
64 *
65 * Do not access this member directly, instead call
66 * from_pvr_device().
67 */
68 struct drm_device base;
69
70 /** @gpu_id: GPU ID detected at runtime. */
71 struct pvr_gpu_id gpu_id;
72
73 /**
74 * @features: Hardware feature information.
75 *
76 * Do not access this member directly, instead use PVR_HAS_FEATURE()
77 * or PVR_FEATURE_VALUE() macros.
78 */
79 struct pvr_device_features features;
80
81 /**
82 * @quirks: Hardware quirk information.
83 *
84 * Do not access this member directly, instead use PVR_HAS_QUIRK().
85 */
86 struct pvr_device_quirks quirks;
87
88 /**
89 * @enhancements: Hardware enhancement information.
90 *
91 * Do not access this member directly, instead use
92 * PVR_HAS_ENHANCEMENT().
93 */
94 struct pvr_device_enhancements enhancements;
95
96 /** @fw_version: Firmware version detected at runtime. */
97 struct pvr_fw_version fw_version;
98
99 /** @regs_resource: Resource representing device control registers. */
100 struct resource *regs_resource;
101
102 /**
103 * @regs: Device control registers.
104 *
105 * These are mapped into memory when the device is initialized; that
106 * location is where this pointer points.
107 */
108 void __iomem *regs;
109
110 /**
111 * @core_clk: General core clock.
112 *
113 * This is the primary clock used by the entire GPU core.
114 */
115 struct clk *core_clk;
116
117 /**
118 * @sys_clk: Optional system bus clock.
119 *
120 * This may be used on some platforms to provide an independent clock to the SoC Interface
121 * (SOCIF). If present, this needs to be enabled/disabled together with @core_clk.
122 */
123 struct clk *sys_clk;
124
125 /**
126 * @mem_clk: Optional memory clock.
127 *
128 * This may be used on some platforms to provide an independent clock to the Memory
129 * Interface (MEMIF). If present, this needs to be enabled/disabled together with @core_clk.
130 */
131 struct clk *mem_clk;
132
133 /** @irq: IRQ number. */
134 int irq;
135
136 /** @fwccb: Firmware CCB. */
137 struct pvr_ccb fwccb;
138
139 /**
140 * @kernel_vm_ctx: Virtual memory context used for kernel mappings.
141 *
142 * This is used for mappings in the firmware address region when a META firmware processor
143 * is in use.
144 *
145 * When a MIPS firmware processor is in use, this will be %NULL.
146 */
147 struct pvr_vm_context *kernel_vm_ctx;
148
149 /** @fw_dev: Firmware related data. */
150 struct pvr_fw_device fw_dev;
151
152 /**
153 * @params: Device-specific parameters.
154 *
155 * The values of these parameters are initialized from the
156 * defaults specified as module parameters. They may be
157 * modified at runtime via debugfs (if enabled).
158 */
159 struct pvr_device_params params;
160
161 /** @stream_musthave_quirks: Bit array of "must-have" quirks for stream commands. */
162 u32 stream_musthave_quirks[PVR_STREAM_TYPE_MAX][PVR_STREAM_EXTHDR_TYPE_MAX];
163
164 /**
165 * @mmu_flush_cache_flags: Records which MMU caches require flushing
166 * before submitting the next job.
167 */
168 atomic_t mmu_flush_cache_flags;
169
170 /**
171 * @ctx_ids: Array of contexts belonging to this device. Array members
172 * are of type "struct pvr_context *".
173 *
174 * This array is used to allocate IDs used by the firmware.
175 */
176 struct xarray ctx_ids;
177
178 /**
179 * @free_list_ids: Array of free lists belonging to this device. Array members
180 * are of type "struct pvr_free_list *".
181 *
182 * This array is used to allocate IDs used by the firmware.
183 */
184 struct xarray free_list_ids;
185
186 /**
187 * @job_ids: Array of jobs belonging to this device. Array members
188 * are of type "struct pvr_job *".
189 */
190 struct xarray job_ids;
191
192 /**
193 * @queues: Queue-related fields.
194 */
195 struct {
196 /** @queues.active: Active queue list. */
197 struct list_head active;
198
199 /** @queues.idle: Idle queue list. */
200 struct list_head idle;
201
202 /** @queues.lock: Lock protecting access to the active/idle
203 * lists. */
204 struct mutex lock;
205 } queues;
206
207 /**
208 * @watchdog: Watchdog for communications with firmware.
209 */
210 struct {
211 /** @watchdog.work: Work item for watchdog callback. */
212 struct delayed_work work;
213
214 /**
215 * @watchdog.old_kccb_cmds_executed: KCCB command execution
216 * count at last watchdog poll.
217 */
218 u32 old_kccb_cmds_executed;
219
220 /**
221 * @watchdog.kccb_stall_count: Number of watchdog polls
222 * KCCB has been stalled for.
223 */
224 u32 kccb_stall_count;
225 } watchdog;
226
227 /**
228 * @kccb: Circular buffer for communications with firmware.
229 */
230 struct {
231 /** @kccb.ccb: Kernel CCB. */
232 struct pvr_ccb ccb;
233
234 /** @kccb.rtn_q: Waitqueue for KCCB command return waiters. */
235 wait_queue_head_t rtn_q;
236
237 /** @kccb.rtn_obj: Object representing KCCB return slots. */
238 struct pvr_fw_object *rtn_obj;
239
240 /**
241 * @kccb.rtn: Pointer to CPU mapping of KCCB return slots.
242 * Must be accessed by READ_ONCE()/WRITE_ONCE().
243 */
244 u32 *rtn;
245
246 /** @kccb.slot_count: Total number of KCCB slots available. */
247 u32 slot_count;
248
249 /** @kccb.reserved_count: Number of KCCB slots reserved for
250 * future use. */
251 u32 reserved_count;
252
253 /**
254 * @kccb.waiters: List of KCCB slot waiters.
255 */
256 struct list_head waiters;
257
258 /** @kccb.fence_ctx: KCCB fence context. */
259 struct {
260 /** @kccb.fence_ctx.id: KCCB fence context ID
261 * allocated with dma_fence_context_alloc(). */
262 u64 id;
263
264 /** @kccb.fence_ctx.seqno: Sequence number incremented
265 * each time a fence is created. */
266 atomic_t seqno;
267
268 /**
269 * @kccb.fence_ctx.lock: Lock used to synchronize
270 * access to fences allocated by this context.
271 */
272 spinlock_t lock;
273 } fence_ctx;
274 } kccb;
275
276 /**
277 * @lost: %true if the device has been lost.
278 *
279 * This variable is set if the device has become irretrievably unavailable, e.g. if the
280 * firmware processor has stopped responding and can not be revived via a hard reset.
281 */
282 bool lost;
283
284 /**
285 * @reset_sem: Reset semaphore.
286 *
287 * GPU reset code will lock this for writing. Any code that submits commands to the firmware
288 * that isn't in an IRQ handler or on the scheduler workqueue must lock this for reading.
289 * Once this has been successfully locked, &pvr_dev->lost _must_ be checked, and -%EIO must
290 * be returned if it is set.
291 */
292 struct rw_semaphore reset_sem;
293
294 /** @sched_wq: Workqueue for schedulers. */
295 struct workqueue_struct *sched_wq;
296};
297
298/**
299 * struct pvr_file - powervr-specific data to be assigned to &struct
300 * drm_file.driver_priv
301 */
302struct pvr_file {
303 /**
304 * @file: A reference to the parent &struct drm_file.
305 *
306 * Do not access this member directly, instead call from_pvr_file().
307 */
308 struct drm_file *file;
309
310 /**
311 * @pvr_dev: A reference to the powervr-specific wrapper for the
312 * associated device. Saves on repeated calls to to_pvr_device().
313 */
314 struct pvr_device *pvr_dev;
315
316 /**
317 * @ctx_handles: Array of contexts belonging to this file. Array members
318 * are of type "struct pvr_context *".
319 *
320 * This array is used to allocate handles returned to userspace.
321 */
322 struct xarray ctx_handles;
323
324 /**
325 * @free_list_handles: Array of free lists belonging to this file. Array
326 * members are of type "struct pvr_free_list *".
327 *
328 * This array is used to allocate handles returned to userspace.
329 */
330 struct xarray free_list_handles;
331
332 /**
333 * @hwrt_handles: Array of HWRT datasets belonging to this file. Array
334 * members are of type "struct pvr_hwrt_dataset *".
335 *
336 * This array is used to allocate handles returned to userspace.
337 */
338 struct xarray hwrt_handles;
339
340 /**
341 * @vm_ctx_handles: Array of VM contexts belonging to this file. Array
342 * members are of type "struct pvr_vm_context *".
343 *
344 * This array is used to allocate handles returned to userspace.
345 */
346 struct xarray vm_ctx_handles;
347};
348
349/**
350 * PVR_HAS_FEATURE() - Tests whether a PowerVR device has a given feature
351 * @pvr_dev: [IN] Target PowerVR device.
352 * @feature: [IN] Hardware feature name.
353 *
354 * Feature names are derived from those found in &struct pvr_device_features by
355 * dropping the 'has_' prefix, which is applied by this macro.
356 *
357 * Return:
358 * * true if the named feature is present in the hardware
359 * * false if the named feature is not present in the hardware
360 */
361#define PVR_HAS_FEATURE(pvr_dev, feature) ((pvr_dev)->features.has_##feature)
362
363/**
364 * PVR_FEATURE_VALUE() - Gets a PowerVR device feature value
365 * @pvr_dev: [IN] Target PowerVR device.
366 * @feature: [IN] Feature name.
367 * @value_out: [OUT] Feature value.
368 *
369 * This macro will get a feature value for those features that have values.
370 * If the feature is not present, nothing will be stored to @value_out.
371 *
372 * Feature names are derived from those found in &struct pvr_device_features by
373 * dropping the 'has_' prefix.
374 *
375 * Return:
376 * * 0 on success, or
377 * * -%EINVAL if the named feature is not present in the hardware
378 */
379#define PVR_FEATURE_VALUE(pvr_dev, feature, value_out) \
380 ({ \
381 struct pvr_device *_pvr_dev = pvr_dev; \
382 int _ret = -EINVAL; \
383 if (_pvr_dev->features.has_##feature) { \
384 *(value_out) = _pvr_dev->features.feature; \
385 _ret = 0; \
386 } \
387 _ret; \
388 })
389
390/**
391 * PVR_HAS_QUIRK() - Tests whether a physical device has a given quirk
392 * @pvr_dev: [IN] Target PowerVR device.
393 * @quirk: [IN] Hardware quirk name.
394 *
395 * Quirk numbers are derived from those found in #pvr_device_quirks by
396 * dropping the 'has_brn' prefix, which is applied by this macro.
397 *
398 * Returns
399 * * true if the quirk is present in the hardware, or
400 * * false if the quirk is not present in the hardware.
401 */
402#define PVR_HAS_QUIRK(pvr_dev, quirk) ((pvr_dev)->quirks.has_brn##quirk)
403
404/**
405 * PVR_HAS_ENHANCEMENT() - Tests whether a physical device has a given
406 * enhancement
407 * @pvr_dev: [IN] Target PowerVR device.
408 * @enhancement: [IN] Hardware enhancement name.
409 *
410 * Enhancement numbers are derived from those found in #pvr_device_enhancements
411 * by dropping the 'has_ern' prefix, which is applied by this macro.
412 *
413 * Returns
414 * * true if the enhancement is present in the hardware, or
415 * * false if the enhancement is not present in the hardware.
416 */
417#define PVR_HAS_ENHANCEMENT(pvr_dev, enhancement) ((pvr_dev)->enhancements.has_ern##enhancement)
418
419#define from_pvr_device(pvr_dev) (&(pvr_dev)->base)
420
421#define to_pvr_device(drm_dev) container_of_const(drm_dev, struct pvr_device, base)
422
423#define from_pvr_file(pvr_file) ((pvr_file)->file)
424
425#define to_pvr_file(file) ((file)->driver_priv)
426
427/**
428 * PVR_PACKED_BVNC() - Packs B, V, N and C values into a 64-bit unsigned integer
429 * @b: Branch ID.
430 * @v: Version ID.
431 * @n: Number of scalable units.
432 * @c: Config ID.
433 *
434 * The packed layout is as follows:
435 *
436 * +--------+--------+--------+-------+
437 * | 63..48 | 47..32 | 31..16 | 15..0 |
438 * +========+========+========+=======+
439 * | B | V | N | C |
440 * +--------+--------+--------+-------+
441 *
442 * pvr_gpu_id_to_packed_bvnc() should be used instead of this macro when a
443 * &struct pvr_gpu_id is available in order to ensure proper type checking.
444 *
445 * Return: Packed BVNC.
446 */
447/* clang-format off */
448#define PVR_PACKED_BVNC(b, v, n, c) \
449 ((((u64)(b) & GENMASK_ULL(15, 0)) << 48) | \
450 (((u64)(v) & GENMASK_ULL(15, 0)) << 32) | \
451 (((u64)(n) & GENMASK_ULL(15, 0)) << 16) | \
452 (((u64)(c) & GENMASK_ULL(15, 0)) << 0))
453/* clang-format on */
454
455/**
456 * pvr_gpu_id_to_packed_bvnc() - Packs B, V, N and C values into a 64-bit
457 * unsigned integer
458 * @gpu_id: GPU ID.
459 *
460 * The packed layout is as follows:
461 *
462 * +--------+--------+--------+-------+
463 * | 63..48 | 47..32 | 31..16 | 15..0 |
464 * +========+========+========+=======+
465 * | B | V | N | C |
466 * +--------+--------+--------+-------+
467 *
468 * This should be used in preference to PVR_PACKED_BVNC() when a &struct
469 * pvr_gpu_id is available in order to ensure proper type checking.
470 *
471 * Return: Packed BVNC.
472 */
473static __always_inline u64
474pvr_gpu_id_to_packed_bvnc(struct pvr_gpu_id *gpu_id)
475{
476 return PVR_PACKED_BVNC(gpu_id->b, gpu_id->v, gpu_id->n, gpu_id->c);
477}
478
479static __always_inline void
480packed_bvnc_to_pvr_gpu_id(u64 bvnc, struct pvr_gpu_id *gpu_id)
481{
482 gpu_id->b = (bvnc & GENMASK_ULL(63, 48)) >> 48;
483 gpu_id->v = (bvnc & GENMASK_ULL(47, 32)) >> 32;
484 gpu_id->n = (bvnc & GENMASK_ULL(31, 16)) >> 16;
485 gpu_id->c = bvnc & GENMASK_ULL(15, 0);
486}
487
488int pvr_device_init(struct pvr_device *pvr_dev);
489void pvr_device_fini(struct pvr_device *pvr_dev);
490void pvr_device_reset(struct pvr_device *pvr_dev);
491
492bool
493pvr_device_has_uapi_quirk(struct pvr_device *pvr_dev, u32 quirk);
494bool
495pvr_device_has_uapi_enhancement(struct pvr_device *pvr_dev, u32 enhancement);
496bool
497pvr_device_has_feature(struct pvr_device *pvr_dev, u32 feature);
498
499/**
500 * PVR_CR_FIELD_GET() - Extract a single field from a PowerVR control register
501 * @val: Value of the target register.
502 * @field: Field specifier, as defined in "pvr_rogue_cr_defs.h".
503 *
504 * Return: The extracted field.
505 */
506#define PVR_CR_FIELD_GET(val, field) FIELD_GET(~ROGUE_CR_##field##_CLRMSK, val)
507
508/**
509 * pvr_cr_read32() - Read a 32-bit register from a PowerVR device
510 * @pvr_dev: Target PowerVR device.
511 * @reg: Target register.
512 *
513 * Return: The value of the requested register.
514 */
515static __always_inline u32
516pvr_cr_read32(struct pvr_device *pvr_dev, u32 reg)
517{
518 return ioread32(pvr_dev->regs + reg);
519}
520
521/**
522 * pvr_cr_read64() - Read a 64-bit register from a PowerVR device
523 * @pvr_dev: Target PowerVR device.
524 * @reg: Target register.
525 *
526 * Return: The value of the requested register.
527 */
528static __always_inline u64
529pvr_cr_read64(struct pvr_device *pvr_dev, u32 reg)
530{
531 return ioread64(pvr_dev->regs + reg);
532}
533
534/**
535 * pvr_cr_write32() - Write to a 32-bit register in a PowerVR device
536 * @pvr_dev: Target PowerVR device.
537 * @reg: Target register.
538 * @val: Value to write.
539 */
540static __always_inline void
541pvr_cr_write32(struct pvr_device *pvr_dev, u32 reg, u32 val)
542{
543 iowrite32(val, pvr_dev->regs + reg);
544}
545
546/**
547 * pvr_cr_write64() - Write to a 64-bit register in a PowerVR device
548 * @pvr_dev: Target PowerVR device.
549 * @reg: Target register.
550 * @val: Value to write.
551 */
552static __always_inline void
553pvr_cr_write64(struct pvr_device *pvr_dev, u32 reg, u64 val)
554{
555 iowrite64(val, pvr_dev->regs + reg);
556}
557
558/**
559 * pvr_cr_poll_reg32() - Wait for a 32-bit register to match a given value by
560 * polling
561 * @pvr_dev: Target PowerVR device.
562 * @reg_addr: Address of register.
563 * @reg_value: Expected register value (after masking).
564 * @reg_mask: Mask of bits valid for comparison with @reg_value.
565 * @timeout_usec: Timeout length, in us.
566 *
567 * Returns:
568 * * 0 on success, or
569 * * -%ETIMEDOUT on timeout.
570 */
571static __always_inline int
572pvr_cr_poll_reg32(struct pvr_device *pvr_dev, u32 reg_addr, u32 reg_value,
573 u32 reg_mask, u64 timeout_usec)
574{
575 u32 value;
576
577 return readl_poll_timeout(pvr_dev->regs + reg_addr, value,
578 (value & reg_mask) == reg_value, 0, timeout_usec);
579}
580
581/**
582 * pvr_cr_poll_reg64() - Wait for a 64-bit register to match a given value by
583 * polling
584 * @pvr_dev: Target PowerVR device.
585 * @reg_addr: Address of register.
586 * @reg_value: Expected register value (after masking).
587 * @reg_mask: Mask of bits valid for comparison with @reg_value.
588 * @timeout_usec: Timeout length, in us.
589 *
590 * Returns:
591 * * 0 on success, or
592 * * -%ETIMEDOUT on timeout.
593 */
594static __always_inline int
595pvr_cr_poll_reg64(struct pvr_device *pvr_dev, u32 reg_addr, u64 reg_value,
596 u64 reg_mask, u64 timeout_usec)
597{
598 u64 value;
599
600 return readq_poll_timeout(pvr_dev->regs + reg_addr, value,
601 (value & reg_mask) == reg_value, 0, timeout_usec);
602}
603
604/**
605 * pvr_round_up_to_cacheline_size() - Round up a provided size to be cacheline
606 * aligned
607 * @pvr_dev: Target PowerVR device.
608 * @size: Initial size, in bytes.
609 *
610 * Returns:
611 * * Size aligned to cacheline size.
612 */
613static __always_inline size_t
614pvr_round_up_to_cacheline_size(struct pvr_device *pvr_dev, size_t size)
615{
616 u16 slc_cacheline_size_bits = 0;
617 u16 slc_cacheline_size_bytes;
618
619 WARN_ON(!PVR_HAS_FEATURE(pvr_dev, slc_cache_line_size_bits));
620 PVR_FEATURE_VALUE(pvr_dev, slc_cache_line_size_bits,
621 &slc_cacheline_size_bits);
622 slc_cacheline_size_bytes = slc_cacheline_size_bits / 8;
623
624 return round_up(size, slc_cacheline_size_bytes);
625}
626
627/**
628 * DOC: IOCTL validation helpers
629 *
630 * To validate the constraints imposed on IOCTL argument structs, a collection
631 * of macros and helper functions exist in ``pvr_device.h``.
632 *
633 * Of the current helpers, it should only be necessary to call
634 * PVR_IOCTL_UNION_PADDING_CHECK() directly. This macro should be used once in
635 * every code path which extracts a union member from a struct passed from
636 * userspace.
637 */
638
639/**
640 * pvr_ioctl_union_padding_check() - Validate that the implicit padding between
641 * the end of a union member and the end of the union itself is zeroed.
642 * @instance: Pointer to the instance of the struct to validate.
643 * @union_offset: Offset into the type of @instance of the target union. Must
644 * be 64-bit aligned.
645 * @union_size: Size of the target union in the type of @instance. Must be
646 * 64-bit aligned.
647 * @member_size: Size of the target member in the target union specified by
648 * @union_offset and @union_size. It is assumed that the offset of the target
649 * member is zero relative to @union_offset. Must be 64-bit aligned.
650 *
651 * You probably want to use PVR_IOCTL_UNION_PADDING_CHECK() instead of calling
652 * this function directly, since that macro abstracts away much of the setup,
653 * and also provides some static validation. See its docs for details.
654 *
655 * Return:
656 * * %true if every byte between the end of the used member of the union and
657 * the end of that union is zeroed, or
658 * * %false otherwise.
659 */
660static __always_inline bool
661pvr_ioctl_union_padding_check(void *instance, size_t union_offset,
662 size_t union_size, size_t member_size)
663{
664 /*
665 * void pointer arithmetic is technically illegal - cast to a byte
666 * pointer so this addition works safely.
667 */
668 void *padding_start = ((u8 *)instance) + union_offset + member_size;
669 size_t padding_size = union_size - member_size;
670
671 return !memchr_inv(padding_start, 0, padding_size);
672}
673
674/**
675 * PVR_STATIC_ASSERT_64BIT_ALIGNED() - Inline assertion for 64-bit alignment.
676 * @static_expr_: Target expression to evaluate.
677 *
678 * If @static_expr_ does not evaluate to a constant integer which would be a
679 * 64-bit aligned address (i.e. a multiple of 8), compilation will fail.
680 *
681 * Return:
682 * The value of @static_expr_.
683 */
684#define PVR_STATIC_ASSERT_64BIT_ALIGNED(static_expr_) \
685 ({ \
686 static_assert(((static_expr_) & (sizeof(u64) - 1)) == 0); \
687 (static_expr_); \
688 })
689
690/**
691 * PVR_IOCTL_UNION_PADDING_CHECK() - Validate that the implicit padding between
692 * the end of a union member and the end of the union itself is zeroed.
693 * @struct_instance_: An expression which evaluates to a pointer to a UAPI data
694 * struct.
695 * @union_: The name of the union member of @struct_instance_ to check. If the
696 * union member is nested within the type of @struct_instance_, this may
697 * contain the member access operator (".").
698 * @member_: The name of the member of @union_ to assess.
699 *
700 * This is a wrapper around pvr_ioctl_union_padding_check() which performs
701 * alignment checks and simplifies things for the caller.
702 *
703 * Return:
704 * * %true if every byte in @struct_instance_ between the end of @member_ and
705 * the end of @union_ is zeroed, or
706 * * %false otherwise.
707 */
708#define PVR_IOCTL_UNION_PADDING_CHECK(struct_instance_, union_, member_) \
709 ({ \
710 typeof(struct_instance_) __instance = (struct_instance_); \
711 size_t __union_offset = PVR_STATIC_ASSERT_64BIT_ALIGNED( \
712 offsetof(typeof(*__instance), union_)); \
713 size_t __union_size = PVR_STATIC_ASSERT_64BIT_ALIGNED( \
714 sizeof(__instance->union_)); \
715 size_t __member_size = PVR_STATIC_ASSERT_64BIT_ALIGNED( \
716 sizeof(__instance->union_.member_)); \
717 pvr_ioctl_union_padding_check(__instance, __union_offset, \
718 __union_size, __member_size); \
719 })
720
721#define PVR_FW_PROCESSOR_TYPE_META 0
722#define PVR_FW_PROCESSOR_TYPE_MIPS 1
723#define PVR_FW_PROCESSOR_TYPE_RISCV 2
724
725#endif /* PVR_DEVICE_H */