diff options
Diffstat (limited to 'drivers/gpu/nvgpu/boardobj/boardobjgrp.h')
-rw-r--r-- | drivers/gpu/nvgpu/boardobj/boardobjgrp.h | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp.h b/drivers/gpu/nvgpu/boardobj/boardobjgrp.h new file mode 100644 index 00000000..32e92ae0 --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp.h | |||
@@ -0,0 +1,416 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef _BOARDOBJGRP_H_ | ||
24 | #define _BOARDOBJGRP_H_ | ||
25 | |||
26 | struct boardobjgrp; | ||
27 | struct gk20a; | ||
28 | |||
29 | /* ------------------------ Includes ----------------------------------------*/ | ||
30 | #include "ctrl/ctrlboardobj.h" | ||
31 | #include "boardobj.h" | ||
32 | #include "boardobjgrpmask.h" | ||
33 | |||
34 | /* | ||
35 | * Board Object Group destructor. | ||
36 | * | ||
37 | */ | ||
38 | typedef u32 boardobjgrp_destruct(struct boardobjgrp *pboardobjgrp); | ||
39 | |||
40 | /* | ||
41 | * Inserts a previously constructed Board Object into a Board Object Group for | ||
42 | * tracking. Objects are inserted in the array based on the given index. | ||
43 | */ | ||
44 | typedef u32 boardobjgrp_objinsert(struct boardobjgrp *pboardobjgrp, | ||
45 | struct boardobj *pboardobj, u8 index); | ||
46 | |||
47 | /* | ||
48 | * Retrieves a Board Object from a Board Object Group using the group's index. | ||
49 | * | ||
50 | */ | ||
51 | typedef struct boardobj *boardobjgrp_objgetbyidx( | ||
52 | struct boardobjgrp *pBobrdobjgrp, u8 index); | ||
53 | |||
54 | /* | ||
55 | * Retrieve Board Object immediately following one pointed by @ref pcurrentindex | ||
56 | * filtered out by the provided mask. If (pMask == NULL) => no filtering. | ||
57 | */ | ||
58 | typedef struct boardobj *boardobjgrp_objgetnext( | ||
59 | struct boardobjgrp *pboardobjgrp, | ||
60 | u8 *currentindex, struct boardobjgrpmask *mask); | ||
61 | |||
62 | /* | ||
63 | * Board Object Group Remover and destructor. This is used to remove and | ||
64 | * destruct specific entry from the Board Object Group. | ||
65 | */ | ||
66 | typedef u32 boardobjgrp_objremoveanddestroy(struct boardobjgrp *pboardobjgrp, | ||
67 | u8 index); | ||
68 | |||
69 | /* | ||
70 | * BOARDOBJGRP handler for PMU_UNIT_INIT. Calls the PMU_UNIT_INIT handlers | ||
71 | * for the constructed PMU CMDs, and then sets the object via the | ||
72 | * PMU_BOARDOBJ_CMD_GRP interface (if constructed). | ||
73 | */ | ||
74 | typedef u32 boardobjgrp_pmuinithandle(struct gk20a *g, | ||
75 | struct boardobjgrp *pboardobjGrp); | ||
76 | |||
77 | /* | ||
78 | * Fills out the appropriate the PMU_BOARDOBJGRP_<xyz> driver<->PMU description | ||
79 | * header structure, more specifically a mask of BOARDOBJs. | ||
80 | */ | ||
81 | typedef u32 boardobjgrp_pmuhdrdatainit(struct gk20a *g, | ||
82 | struct boardobjgrp *pboardobjgrp, | ||
83 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu, | ||
84 | struct boardobjgrpmask *mask); | ||
85 | |||
86 | /* | ||
87 | * Fills out the appropriate the PMU_BOARDOBJGRP_<xyz> driver->PMU description | ||
88 | * structure, describing the BOARDOBJGRP and all of its BOARDOBJs to the PMU. | ||
89 | */ | ||
90 | typedef u32 boardobjgrp_pmudatainit(struct gk20a *g, | ||
91 | struct boardobjgrp *pboardobjgrp, | ||
92 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu); | ||
93 | |||
94 | /* | ||
95 | * Sends a BOARDOBJGRP to the PMU via the PMU_BOARDOBJ_CMD_GRP interface. | ||
96 | * This interface leverages @ref boardobjgrp_pmudatainit to populate the | ||
97 | * structure. | ||
98 | */ | ||
99 | typedef u32 boardobjgrp_pmuset(struct gk20a *g, | ||
100 | struct boardobjgrp *pboardobjgrp); | ||
101 | |||
102 | /* | ||
103 | * Gets the dynamic status of the PMU BOARDOBJGRP via the | ||
104 | * PMU_BOARDOBJ_CMD_GRP GET_STATUS interface. | ||
105 | */ | ||
106 | typedef u32 boardobjgrp_pmugetstatus(struct gk20a *g, | ||
107 | struct boardobjgrp *pboardobjgrp, | ||
108 | struct boardobjgrpmask *mask); | ||
109 | |||
110 | typedef u32 boardobjgrp_pmudatainstget(struct gk20a *g, | ||
111 | struct nv_pmu_boardobjgrp *boardobjgrppmu, | ||
112 | struct nv_pmu_boardobj **ppboardobjpmudata, u8 idx); | ||
113 | |||
114 | typedef u32 boardobjgrp_pmustatusinstget(struct gk20a *g, void *pboardobjgrppmu, | ||
115 | struct nv_pmu_boardobj_query **ppBoardobjpmustatus, u8 idx); | ||
116 | |||
117 | /* | ||
118 | * Structure describing an PMU CMD for interacting with the representaition | ||
119 | * of this BOARDOBJGRP within the PMU. | ||
120 | */ | ||
121 | struct boardobjgrp_pmu_cmd { | ||
122 | u8 id; | ||
123 | u8 msgid; | ||
124 | u8 hdrsize; | ||
125 | u8 entrysize; | ||
126 | u16 fbsize; | ||
127 | struct nv_pmu_boardobjgrp_super *buf; | ||
128 | struct pmu_surface surf; | ||
129 | }; | ||
130 | |||
131 | /* | ||
132 | * Structure of state describing how to communicate with representation of this | ||
133 | * BOARDOBJGRP in the PMU. | ||
134 | */ | ||
135 | struct boardobjgrp_pmu { | ||
136 | u8 unitid; | ||
137 | u8 classid; | ||
138 | bool bset; | ||
139 | struct boardobjgrp_pmu_cmd set; | ||
140 | struct boardobjgrp_pmu_cmd getstatus; | ||
141 | }; | ||
142 | |||
143 | /* | ||
144 | * Function by which a class which implements BOARDOBJGRP can construct a PMU | ||
145 | * CMD. This provides the various information describing the PMU CMD including | ||
146 | * the CMD and MSG ID and the size of the various sturctures in the payload. | ||
147 | */ | ||
148 | typedef u32 boardobjgrp_pmucmd_construct(struct gk20a *g, | ||
149 | struct boardobjgrp *pboardobjgrp, | ||
150 | struct boardobjgrp_pmu_cmd *cmd, u8 id, u8 msgid, | ||
151 | u8 hdrsize, u8 entrysize, u16 fbsize); | ||
152 | |||
153 | /* | ||
154 | * Destroys BOARDOBJGRP PMU SW state. CMD. | ||
155 | */ | ||
156 | typedef u32 boardobjgrp_pmucmd_destroy(struct gk20a *g, | ||
157 | struct boardobjgrp_pmu_cmd *cmd); | ||
158 | |||
159 | /* | ||
160 | * init handler for the BOARDOBJGRP PMU CMD. Allocates and maps the | ||
161 | * PMU CMD payload within both the PMU and driver so that it can be referenced | ||
162 | * at run-time. | ||
163 | */ | ||
164 | typedef u32 boardobjgrp_pmucmd_pmuinithandle(struct gk20a *g, | ||
165 | struct boardobjgrp *pboardobjgrp, | ||
166 | struct boardobjgrp_pmu_cmd *cmd); | ||
167 | |||
168 | /* | ||
169 | * Base Class Group for all physical or logical device on the PCB. | ||
170 | * Contains fields common to all devices on the board. Specific types of | ||
171 | * devices groups may extend this object adding any details specific to that | ||
172 | * device group or device-type. | ||
173 | */ | ||
174 | struct boardobjgrp { | ||
175 | struct gk20a *g; | ||
176 | u32 objmask; | ||
177 | bool bconstructed; | ||
178 | u8 type; | ||
179 | u8 classid; | ||
180 | struct boardobj **ppobjects; | ||
181 | struct boardobjgrpmask *mask; | ||
182 | u8 objslots; | ||
183 | u8 objmaxidx; | ||
184 | struct boardobjgrp_pmu pmu; | ||
185 | |||
186 | /* Basic interfaces */ | ||
187 | boardobjgrp_destruct *destruct; | ||
188 | boardobjgrp_objinsert *objinsert; | ||
189 | boardobjgrp_objgetbyidx *objgetbyidx; | ||
190 | boardobjgrp_objgetnext *objgetnext; | ||
191 | boardobjgrp_objremoveanddestroy *objremoveanddestroy; | ||
192 | |||
193 | /* PMU interfaces */ | ||
194 | boardobjgrp_pmuinithandle *pmuinithandle; | ||
195 | boardobjgrp_pmuhdrdatainit *pmuhdrdatainit; | ||
196 | boardobjgrp_pmudatainit *pmudatainit; | ||
197 | boardobjgrp_pmuset *pmuset; | ||
198 | boardobjgrp_pmugetstatus *pmugetstatus; | ||
199 | |||
200 | boardobjgrp_pmudatainstget *pmudatainstget; | ||
201 | boardobjgrp_pmustatusinstget *pmustatusinstget; | ||
202 | struct nvgpu_list_node node; | ||
203 | }; | ||
204 | |||
205 | /* | ||
206 | * Macro test whether a specified index into the BOARDOBJGRP is valid. | ||
207 | * | ||
208 | */ | ||
209 | #define boardobjgrp_idxisvalid(_pboardobjgrp, _idx) \ | ||
210 | (((_idx) < (_pboardobjgrp)->objslots) && \ | ||
211 | ((_pboardobjgrp)->ppobjects[(_idx)] != NULL)) | ||
212 | |||
213 | /* | ||
214 | * Macro test whether a specified BOARDOBJGRP is empty. | ||
215 | */ | ||
216 | #define BOARDOBJGRP_IS_EMPTY(_pboardobjgrp) \ | ||
217 | ((!((_pboardobjgrp)->bconstructed)) || \ | ||
218 | ((_pboardobjgrp)->objmaxidx == CTRL_BOARDOBJ_IDX_INVALID)) | ||
219 | |||
220 | #define boardobjgrp_objinsert(_pboardobjgrp, _pboardobj, _idx) \ | ||
221 | ((_pboardobjgrp)->objinsert((_pboardobjgrp), (_pboardobj), (_idx))) | ||
222 | |||
223 | /* | ||
224 | * Helper macro to determine the "next" open/empty index after all allocated | ||
225 | * objects. This is intended to be used to find the index at which objects can | ||
226 | * be inserted contiguously (i.e. w/o fear of colliding with existing objects). | ||
227 | */ | ||
228 | #define BOARDOBJGRP_NEXT_EMPTY_IDX(_pboardobjgrp) \ | ||
229 | ((CTRL_BOARDOBJ_IDX_INVALID == (_pboardobjgrp)->objmaxidx) ? 0 : \ | ||
230 | ((((_pboardobjgrp)->objmaxidx + 1) >= (_pboardobjgrp)->objslots) ? \ | ||
231 | (u8)CTRL_BOARDOBJ_IDX_INVALID : (u8)((_pboardobjgrp)->objmaxidx + 1))) | ||
232 | |||
233 | /* | ||
234 | * Helper macro to determine the number of @ref BOARDOBJ pointers | ||
235 | * that are required to be allocated in PMU @ref ppObjects. | ||
236 | */ | ||
237 | #define BOARDOBJGRP_PMU_SLOTS_GET(_pboardobjgrp) \ | ||
238 | ((CTRL_BOARDOBJ_IDX_INVALID == (_pboardobjgrp)->objmaxidx) ? 0 : \ | ||
239 | (u8)((_pboardobjgrp)->objmaxidx + 1)) | ||
240 | |||
241 | #define BOARDOBJGRP_OBJ_GET_BY_IDX(_pboardobjgrp, _idx) \ | ||
242 | ((_pboardobjgrp)->objgetbyidx((_pboardobjgrp), (_idx))) | ||
243 | |||
244 | /* | ||
245 | * macro to look-up next object while tolerating error if | ||
246 | * Board Object Group is not constructed. | ||
247 | */ | ||
248 | |||
249 | #define boardobjgrpobjgetnextsafe(_pgrp, _pindex, _pmask) \ | ||
250 | ((_pgrp)->bconstructed ? \ | ||
251 | (_pgrp)->objgetnext((_pgrp), (_pindex), (_pmask)) : NULL) | ||
252 | |||
253 | /* | ||
254 | * Used to traverse all Board Objects stored within @ref _pgrp in the increasing | ||
255 | * index order. | ||
256 | * If @ref _pmask is provided only objects specified by the mask are traversed. | ||
257 | */ | ||
258 | #define BOARDOBJGRP_ITERATOR(_pgrp, _ptype, _pobj, _index, _pmask) \ | ||
259 | for (_index = CTRL_BOARDOBJ_IDX_INVALID, \ | ||
260 | _pobj = (_ptype)boardobjgrpobjgetnextsafe((_pgrp), &_index, (_pmask));\ | ||
261 | _pobj != NULL; \ | ||
262 | _pobj = (_ptype)boardobjgrpobjgetnextsafe((_pgrp), &_index, (_pmask))) | ||
263 | #define BOARDOBJGRP_FOR_EACH(_pgrp, _ptype, _pobj, _index) \ | ||
264 | BOARDOBJGRP_ITERATOR(_pgrp, _ptype, _pobj, _index, NULL) | ||
265 | |||
266 | #define BOARDOBJGRP_FOR_EACH_INDEX_IN_MASK(mask_width, index, mask) \ | ||
267 | { \ | ||
268 | u##mask_width lcl_msk = (u##mask_width)(mask); \ | ||
269 | for (index = 0; lcl_msk != 0; index++, lcl_msk >>= 1) { \ | ||
270 | if (((u##mask_width)((u64)1) & lcl_msk) == 0) { \ | ||
271 | continue; \ | ||
272 | } | ||
273 | |||
274 | #define BOARDOBJGRP_FOR_EACH_INDEX_IN_MASK_END \ | ||
275 | } \ | ||
276 | } | ||
277 | |||
278 | |||
279 | /*! | ||
280 | * Invalid UNIT_ID. Used to indicate that the implementing class has not set | ||
281 | * @ref BOARDOBJGRP::unitId and, thus, certain BOARDOBJGRP PMU interfaces are | ||
282 | * not supported. | ||
283 | */ | ||
284 | #define BOARDOBJGRP_UNIT_ID_INVALID 255 | ||
285 | |||
286 | /*! | ||
287 | * Invalid UNIT_ID. Used to indicate that the implementing class has not set | ||
288 | * @ref BOARDOBJGRP::grpType and, thus, certain BOARDOBJGRP PMU interfaces are | ||
289 | * not supported. | ||
290 | */ | ||
291 | #define BOARDOBJGRP_GRP_CLASS_ID_INVALID 255 | ||
292 | |||
293 | /*! | ||
294 | * Invalid UNIT_ID. Used to indicate that the implementing class has not set | ||
295 | * @ref BOARDOBJGRP::grpSetCmdId and, thus, certain BOARDOBJGRP PMU interfaces | ||
296 | * are not supported. | ||
297 | */ | ||
298 | #define BOARDOBJGRP_GRP_CMD_ID_INVALID 255 | ||
299 | |||
300 | /*! | ||
301 | * Helper macro to construct a BOARDOBJGRP's PMU SW state. | ||
302 | * | ||
303 | * @param[out] pboardobjgrp BOARDOBJGRP pointer | ||
304 | * @param[in] _eng | ||
305 | * Implementing engine/unit which manages the BOARDOBJGRP. | ||
306 | * @param[in] _class | ||
307 | * Class ID of BOARDOBJGRP. | ||
308 | */ | ||
309 | #define BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, _ENG, _CLASS) \ | ||
310 | do { \ | ||
311 | (pboardobjgrp)->pmu.unitid = PMU_UNIT_##_ENG; \ | ||
312 | (pboardobjgrp)->pmu.classid = \ | ||
313 | NV_PMU_##_ENG##_BOARDOBJGRP_CLASS_ID_##_CLASS; \ | ||
314 | } while (0) | ||
315 | |||
316 | #define BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(pgpu, pboardobjgrp, eng, ENG, \ | ||
317 | class, CLASS) \ | ||
318 | boardobjgrp_pmucmd_construct_impl( \ | ||
319 | pgpu, /* pgpu */ \ | ||
320 | pboardobjgrp, /* pboardobjgrp */ \ | ||
321 | &((pboardobjgrp)->pmu.set), /* pcmd */ \ | ||
322 | NV_PMU_##ENG##_CMD_ID_BOARDOBJ_GRP_SET, /* id */ \ | ||
323 | NV_PMU_##ENG##_MSG_ID_BOARDOBJ_GRP_SET, /* msgid */ \ | ||
324 | (u32)sizeof(union nv_pmu_##eng##_##class##_boardobjgrp_set_header_aligned), \ | ||
325 | (u32)sizeof(union nv_pmu_##eng##_##class##_boardobj_set_union_aligned), \ | ||
326 | (u32)sizeof(struct nv_pmu_##eng##_##class##_boardobj_grp_set)) | ||
327 | |||
328 | #define BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(pgpu, pboardobjgrp, \ | ||
329 | eng, ENG, class, CLASS) \ | ||
330 | boardobjgrp_pmucmd_construct_impl( \ | ||
331 | pgpu, /* pGpu */ \ | ||
332 | pboardobjgrp, /* pBoardObjGrp */ \ | ||
333 | &((pboardobjgrp)->pmu.getstatus), /* pCmd */ \ | ||
334 | NV_PMU_##ENG##_CMD_ID_BOARDOBJ_GRP_GET_STATUS, /* id */ \ | ||
335 | NV_PMU_##ENG##_MSG_ID_BOARDOBJ_GRP_GET_STATUS, /* msgid */ \ | ||
336 | (u32)sizeof(union nv_pmu_##eng##_##class##_boardobjgrp_get_status_header_aligned), \ | ||
337 | (u32)sizeof(union nv_pmu_##eng##_##class##_boardobj_get_status_union_aligned), \ | ||
338 | (u32)sizeof(struct nv_pmu_##eng##_##class##_boardobj_grp_get_status)) | ||
339 | |||
340 | /* ------------------------ Function Prototypes ----------------------------- */ | ||
341 | /* Constructor and destructor */ | ||
342 | u32 boardobjgrp_construct_super(struct gk20a *g, struct boardobjgrp *pboardobjgrp); | ||
343 | boardobjgrp_destruct boardobjgrp_destruct_impl; | ||
344 | boardobjgrp_destruct boardobjgrp_destruct_super; | ||
345 | |||
346 | /* PMU_CMD interfaces */ | ||
347 | boardobjgrp_pmucmd_construct boardobjgrp_pmucmd_construct_impl; | ||
348 | boardobjgrp_pmucmd_destroy boardobjgrp_pmucmd_destroy_impl; | ||
349 | boardobjgrp_pmucmd_pmuinithandle boardobjgrp_pmucmd_pmuinithandle_impl; | ||
350 | |||
351 | /* BOARDOBJGRP interfaces */ | ||
352 | boardobjgrp_pmuinithandle boardobjgrp_pmuinithandle_impl; | ||
353 | boardobjgrp_pmuhdrdatainit boardobjgrp_pmuhdrdatainit_super; | ||
354 | boardobjgrp_pmudatainit boardobjgrp_pmudatainit_super; | ||
355 | |||
356 | boardobjgrp_pmudatainit boardobjgrp_pmudatainit_legacy; | ||
357 | boardobjgrp_pmuset boardobjgrp_pmuset_impl; | ||
358 | boardobjgrp_pmugetstatus boardobjgrp_pmugetstatus_impl; | ||
359 | |||
360 | void boardobjgrpe32hdrset(struct nv_pmu_boardobjgrp *hdr, u32 objmask); | ||
361 | |||
362 | #define HIGHESTBITIDX_32(n32) \ | ||
363 | { \ | ||
364 | u32 count = 0; \ | ||
365 | while (n32 >>= 1) \ | ||
366 | count++; \ | ||
367 | n32 = count; \ | ||
368 | } | ||
369 | |||
370 | #define LOWESTBIT(x) ((x) & (((x)-1) ^ (x))) | ||
371 | |||
372 | #define HIGHESTBIT(n32) \ | ||
373 | { \ | ||
374 | HIGHESTBITIDX_32(n32); \ | ||
375 | n32 = NVBIT(n32); \ | ||
376 | } | ||
377 | |||
378 | #define ONEBITSET(x) ((x) && (((x) & ((x)-1)) == 0)) | ||
379 | |||
380 | #define LOWESTBITIDX_32(n32) \ | ||
381 | { \ | ||
382 | n32 = LOWESTBIT(n32); \ | ||
383 | IDX_32(n32); \ | ||
384 | } | ||
385 | |||
386 | #define NUMSETBITS_32(n32) \ | ||
387 | { \ | ||
388 | n32 = n32 - ((n32 >> 1) & 0x55555555); \ | ||
389 | n32 = (n32 & 0x33333333) + ((n32 >> 2) & 0x33333333); \ | ||
390 | n32 = (((n32 + (n32 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; \ | ||
391 | } | ||
392 | |||
393 | #define IDX_32(n32) \ | ||
394 | { \ | ||
395 | u32 idx = 0; \ | ||
396 | if ((n32) & 0xFFFF0000) \ | ||
397 | idx += 16; \ | ||
398 | if ((n32) & 0xFF00FF00) \ | ||
399 | idx += 8; \ | ||
400 | if ((n32) & 0xF0F0F0F0) \ | ||
401 | idx += 4; \ | ||
402 | if ((n32) & 0xCCCCCCCC) \ | ||
403 | idx += 2; \ | ||
404 | if ((n32) & 0xAAAAAAAA) \ | ||
405 | idx += 1; \ | ||
406 | (n32) = idx; \ | ||
407 | } | ||
408 | |||
409 | static inline struct boardobjgrp * | ||
410 | boardobjgrp_from_node(struct nvgpu_list_node *node) | ||
411 | { | ||
412 | return (struct boardobjgrp *) | ||
413 | ((uintptr_t)node - offsetof(struct boardobjgrp, node)); | ||
414 | }; | ||
415 | |||
416 | #endif | ||