1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
5bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
6bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights
7bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
9bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <assert.h>
25bf215546Sopenharmony_ci#include <stdbool.h>
26bf215546Sopenharmony_ci#include <stdint.h>
27bf215546Sopenharmony_ci#include <xf86drm.h>
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "hwdef/rogue_hw_utils.h"
30bf215546Sopenharmony_ci#include "pvr_csb.h"
31bf215546Sopenharmony_ci#include "pvr_device_info.h"
32bf215546Sopenharmony_ci#include "pvr_private.h"
33bf215546Sopenharmony_ci#include "pvr_srv.h"
34bf215546Sopenharmony_ci#include "pvr_srv_bo.h"
35bf215546Sopenharmony_ci#include "pvr_srv_bridge.h"
36bf215546Sopenharmony_ci#include "pvr_srv_job_compute.h"
37bf215546Sopenharmony_ci#include "pvr_srv_job_render.h"
38bf215546Sopenharmony_ci#include "pvr_srv_job_transfer.h"
39bf215546Sopenharmony_ci#include "pvr_srv_public.h"
40bf215546Sopenharmony_ci#include "pvr_srv_sync.h"
41bf215546Sopenharmony_ci#include "pvr_srv_job_null.h"
42bf215546Sopenharmony_ci#include "pvr_types.h"
43bf215546Sopenharmony_ci#include "pvr_winsys.h"
44bf215546Sopenharmony_ci#include "pvr_winsys_helper.h"
45bf215546Sopenharmony_ci#include "util/log.h"
46bf215546Sopenharmony_ci#include "util/macros.h"
47bf215546Sopenharmony_ci#include "util/os_misc.h"
48bf215546Sopenharmony_ci#include "vk_log.h"
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci/* Amount of space used to hold sync prim values (in bytes). */
51bf215546Sopenharmony_ci#define PVR_SRV_SYNC_PRIM_VALUE_SIZE 4U
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistatic VkResult pvr_srv_heap_init(
54bf215546Sopenharmony_ci   struct pvr_srv_winsys *srv_ws,
55bf215546Sopenharmony_ci   struct pvr_srv_winsys_heap *srv_heap,
56bf215546Sopenharmony_ci   uint32_t heap_idx,
57bf215546Sopenharmony_ci   const struct pvr_winsys_static_data_offsets *const static_data_offsets)
58bf215546Sopenharmony_ci{
59bf215546Sopenharmony_ci   pvr_dev_addr_t base_address;
60bf215546Sopenharmony_ci   uint32_t log2_page_size;
61bf215546Sopenharmony_ci   uint64_t reserved_size;
62bf215546Sopenharmony_ci   VkResult result;
63bf215546Sopenharmony_ci   uint64_t size;
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   result = pvr_srv_get_heap_details(srv_ws->render_fd,
66bf215546Sopenharmony_ci                                     heap_idx,
67bf215546Sopenharmony_ci                                     0,
68bf215546Sopenharmony_ci                                     NULL,
69bf215546Sopenharmony_ci                                     &base_address,
70bf215546Sopenharmony_ci                                     &size,
71bf215546Sopenharmony_ci                                     &reserved_size,
72bf215546Sopenharmony_ci                                     &log2_page_size);
73bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
74bf215546Sopenharmony_ci      return result;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   result = pvr_winsys_helper_winsys_heap_init(&srv_ws->base,
77bf215546Sopenharmony_ci                                               base_address,
78bf215546Sopenharmony_ci                                               size,
79bf215546Sopenharmony_ci                                               base_address,
80bf215546Sopenharmony_ci                                               reserved_size,
81bf215546Sopenharmony_ci                                               log2_page_size,
82bf215546Sopenharmony_ci                                               static_data_offsets,
83bf215546Sopenharmony_ci                                               &srv_heap->base);
84bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
85bf215546Sopenharmony_ci      return result;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   assert(srv_heap->base.page_size == srv_ws->base.page_size);
88bf215546Sopenharmony_ci   assert(srv_heap->base.log2_page_size == srv_ws->base.log2_page_size);
89bf215546Sopenharmony_ci   assert(srv_heap->base.reserved_size % PVR_SRV_RESERVED_SIZE_GRANULARITY ==
90bf215546Sopenharmony_ci          0);
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   /* Create server-side counterpart of Device Memory heap */
93bf215546Sopenharmony_ci   result = pvr_srv_int_heap_create(srv_ws->render_fd,
94bf215546Sopenharmony_ci                                    srv_heap->base.base_addr,
95bf215546Sopenharmony_ci                                    srv_heap->base.size,
96bf215546Sopenharmony_ci                                    srv_heap->base.log2_page_size,
97bf215546Sopenharmony_ci                                    srv_ws->server_memctx,
98bf215546Sopenharmony_ci                                    &srv_heap->server_heap);
99bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
100bf215546Sopenharmony_ci      pvr_winsys_helper_winsys_heap_finish(&srv_heap->base);
101bf215546Sopenharmony_ci      return result;
102bf215546Sopenharmony_ci   }
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   return VK_SUCCESS;
105bf215546Sopenharmony_ci}
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_cistatic bool pvr_srv_heap_finish(struct pvr_srv_winsys *srv_ws,
108bf215546Sopenharmony_ci                                struct pvr_srv_winsys_heap *srv_heap)
109bf215546Sopenharmony_ci{
110bf215546Sopenharmony_ci   if (!pvr_winsys_helper_winsys_heap_finish(&srv_heap->base))
111bf215546Sopenharmony_ci      return false;
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   pvr_srv_int_heap_destroy(srv_ws->render_fd, srv_heap->server_heap);
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   return true;
116bf215546Sopenharmony_ci}
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_cistatic VkResult pvr_srv_memctx_init(struct pvr_srv_winsys *srv_ws)
119bf215546Sopenharmony_ci{
120bf215546Sopenharmony_ci   const struct pvr_winsys_static_data_offsets
121bf215546Sopenharmony_ci      general_heap_static_data_offsets = {
122bf215546Sopenharmony_ci         .yuv_csc = FWIF_GENERAL_HEAP_YUV_CSC_OFFSET_BYTES,
123bf215546Sopenharmony_ci      };
124bf215546Sopenharmony_ci   const struct pvr_winsys_static_data_offsets pds_heap_static_data_offsets = {
125bf215546Sopenharmony_ci      .eot = FWIF_PDS_HEAP_EOT_OFFSET_BYTES,
126bf215546Sopenharmony_ci      .vdm_sync = FWIF_PDS_HEAP_VDM_SYNC_OFFSET_BYTES,
127bf215546Sopenharmony_ci   };
128bf215546Sopenharmony_ci   const struct pvr_winsys_static_data_offsets usc_heap_static_data_offsets = {
129bf215546Sopenharmony_ci      .vdm_sync = FWIF_USC_HEAP_VDM_SYNC_OFFSET_BYTES,
130bf215546Sopenharmony_ci   };
131bf215546Sopenharmony_ci   const struct pvr_winsys_static_data_offsets no_static_data_offsets = { 0 };
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   char heap_name[PVR_SRV_DEVMEM_HEAPNAME_MAXLENGTH];
134bf215546Sopenharmony_ci   int transfer_3d_heap_idx = -1;
135bf215546Sopenharmony_ci   int vis_test_heap_idx = -1;
136bf215546Sopenharmony_ci   int general_heap_idx = -1;
137bf215546Sopenharmony_ci   int rgn_hdr_heap_idx = -1;
138bf215546Sopenharmony_ci   int pds_heap_idx = -1;
139bf215546Sopenharmony_ci   int usc_heap_idx = -1;
140bf215546Sopenharmony_ci   uint32_t heap_count;
141bf215546Sopenharmony_ci   VkResult result;
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   result = pvr_srv_int_ctx_create(srv_ws->render_fd,
144bf215546Sopenharmony_ci                                   &srv_ws->server_memctx,
145bf215546Sopenharmony_ci                                   &srv_ws->server_memctx_data);
146bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
147bf215546Sopenharmony_ci      return result;
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   os_get_page_size(&srv_ws->base.page_size);
150bf215546Sopenharmony_ci   srv_ws->base.log2_page_size = util_logbase2(srv_ws->base.page_size);
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci   result = pvr_srv_get_heap_count(srv_ws->render_fd, &heap_count);
153bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
154bf215546Sopenharmony_ci      goto err_pvr_srv_int_ctx_destroy;
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   assert(heap_count > 0);
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   for (uint32_t i = 0; i < heap_count; i++) {
159bf215546Sopenharmony_ci      result = pvr_srv_get_heap_details(srv_ws->render_fd,
160bf215546Sopenharmony_ci                                        i,
161bf215546Sopenharmony_ci                                        sizeof(heap_name),
162bf215546Sopenharmony_ci                                        heap_name,
163bf215546Sopenharmony_ci                                        NULL,
164bf215546Sopenharmony_ci                                        NULL,
165bf215546Sopenharmony_ci                                        NULL,
166bf215546Sopenharmony_ci                                        NULL);
167bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
168bf215546Sopenharmony_ci         goto err_pvr_srv_int_ctx_destroy;
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci      if (general_heap_idx == -1 &&
171bf215546Sopenharmony_ci          strncmp(heap_name,
172bf215546Sopenharmony_ci                  PVR_SRV_GENERAL_HEAP_IDENT,
173bf215546Sopenharmony_ci                  sizeof(PVR_SRV_GENERAL_HEAP_IDENT)) == 0) {
174bf215546Sopenharmony_ci         general_heap_idx = i;
175bf215546Sopenharmony_ci      } else if (pds_heap_idx == -1 &&
176bf215546Sopenharmony_ci                 strncmp(heap_name,
177bf215546Sopenharmony_ci                         PVR_SRV_PDSCODEDATA_HEAP_IDENT,
178bf215546Sopenharmony_ci                         sizeof(PVR_SRV_PDSCODEDATA_HEAP_IDENT)) == 0) {
179bf215546Sopenharmony_ci         pds_heap_idx = i;
180bf215546Sopenharmony_ci      } else if (rgn_hdr_heap_idx == -1 &&
181bf215546Sopenharmony_ci                 strncmp(heap_name,
182bf215546Sopenharmony_ci                         PVR_SRV_RGNHDR_BRN_63142_HEAP_IDENT,
183bf215546Sopenharmony_ci                         sizeof(PVR_SRV_RGNHDR_BRN_63142_HEAP_IDENT)) == 0) {
184bf215546Sopenharmony_ci         rgn_hdr_heap_idx = i;
185bf215546Sopenharmony_ci      } else if (transfer_3d_heap_idx == -1 &&
186bf215546Sopenharmony_ci                 strncmp(heap_name,
187bf215546Sopenharmony_ci                         PVR_SRV_TRANSFER_3D_HEAP_IDENT,
188bf215546Sopenharmony_ci                         sizeof(PVR_SRV_TRANSFER_3D_HEAP_IDENT)) == 0) {
189bf215546Sopenharmony_ci         transfer_3d_heap_idx = i;
190bf215546Sopenharmony_ci      } else if (usc_heap_idx == -1 &&
191bf215546Sopenharmony_ci                 strncmp(heap_name,
192bf215546Sopenharmony_ci                         PVR_SRV_USCCODE_HEAP_IDENT,
193bf215546Sopenharmony_ci                         sizeof(PVR_SRV_USCCODE_HEAP_IDENT)) == 0) {
194bf215546Sopenharmony_ci         usc_heap_idx = i;
195bf215546Sopenharmony_ci      } else if (vis_test_heap_idx == -1 &&
196bf215546Sopenharmony_ci                 strncmp(heap_name,
197bf215546Sopenharmony_ci                         PVR_SRV_VISIBILITY_TEST_HEAP_IDENT,
198bf215546Sopenharmony_ci                         sizeof(PVR_SRV_VISIBILITY_TEST_HEAP_IDENT)) == 0) {
199bf215546Sopenharmony_ci         vis_test_heap_idx = i;
200bf215546Sopenharmony_ci      }
201bf215546Sopenharmony_ci   }
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci   /* Check for and initialise required heaps. */
204bf215546Sopenharmony_ci   if (general_heap_idx == -1 || pds_heap_idx == -1 ||
205bf215546Sopenharmony_ci       transfer_3d_heap_idx == -1 || usc_heap_idx == -1 ||
206bf215546Sopenharmony_ci       vis_test_heap_idx == -1) {
207bf215546Sopenharmony_ci      result = vk_error(NULL, VK_ERROR_INITIALIZATION_FAILED);
208bf215546Sopenharmony_ci      goto err_pvr_srv_int_ctx_destroy;
209bf215546Sopenharmony_ci   }
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   result = pvr_srv_heap_init(srv_ws,
212bf215546Sopenharmony_ci                              &srv_ws->general_heap,
213bf215546Sopenharmony_ci                              general_heap_idx,
214bf215546Sopenharmony_ci                              &general_heap_static_data_offsets);
215bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
216bf215546Sopenharmony_ci      goto err_pvr_srv_int_ctx_destroy;
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   result = pvr_srv_heap_init(srv_ws,
219bf215546Sopenharmony_ci                              &srv_ws->pds_heap,
220bf215546Sopenharmony_ci                              pds_heap_idx,
221bf215546Sopenharmony_ci                              &pds_heap_static_data_offsets);
222bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
223bf215546Sopenharmony_ci      goto err_pvr_srv_heap_finish_general;
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   result = pvr_srv_heap_init(srv_ws,
226bf215546Sopenharmony_ci                              &srv_ws->transfer_3d_heap,
227bf215546Sopenharmony_ci                              transfer_3d_heap_idx,
228bf215546Sopenharmony_ci                              &no_static_data_offsets);
229bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
230bf215546Sopenharmony_ci      goto err_pvr_srv_heap_finish_pds;
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   result = pvr_srv_heap_init(srv_ws,
233bf215546Sopenharmony_ci                              &srv_ws->usc_heap,
234bf215546Sopenharmony_ci                              usc_heap_idx,
235bf215546Sopenharmony_ci                              &usc_heap_static_data_offsets);
236bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
237bf215546Sopenharmony_ci      goto err_pvr_srv_heap_finish_transfer_3d;
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   result = pvr_srv_heap_init(srv_ws,
240bf215546Sopenharmony_ci                              &srv_ws->vis_test_heap,
241bf215546Sopenharmony_ci                              vis_test_heap_idx,
242bf215546Sopenharmony_ci                              &no_static_data_offsets);
243bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
244bf215546Sopenharmony_ci      goto err_pvr_srv_heap_finish_usc;
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci   /* Check for and set up optional heaps. */
247bf215546Sopenharmony_ci   if (rgn_hdr_heap_idx != -1) {
248bf215546Sopenharmony_ci      result = pvr_srv_heap_init(srv_ws,
249bf215546Sopenharmony_ci                                 &srv_ws->rgn_hdr_heap,
250bf215546Sopenharmony_ci                                 rgn_hdr_heap_idx,
251bf215546Sopenharmony_ci                                 &no_static_data_offsets);
252bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
253bf215546Sopenharmony_ci         goto err_pvr_srv_heap_finish_vis_test;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci      srv_ws->rgn_hdr_heap_present = true;
256bf215546Sopenharmony_ci   } else {
257bf215546Sopenharmony_ci      srv_ws->rgn_hdr_heap_present = false;
258bf215546Sopenharmony_ci   }
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci   result =
261bf215546Sopenharmony_ci      pvr_winsys_helper_allocate_static_memory(&srv_ws->base,
262bf215546Sopenharmony_ci                                               pvr_srv_heap_alloc_reserved,
263bf215546Sopenharmony_ci                                               &srv_ws->general_heap.base,
264bf215546Sopenharmony_ci                                               &srv_ws->pds_heap.base,
265bf215546Sopenharmony_ci                                               &srv_ws->usc_heap.base,
266bf215546Sopenharmony_ci                                               &srv_ws->general_vma,
267bf215546Sopenharmony_ci                                               &srv_ws->pds_vma,
268bf215546Sopenharmony_ci                                               &srv_ws->usc_vma);
269bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
270bf215546Sopenharmony_ci      goto err_pvr_srv_heap_finish_rgn_hdr;
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci   result = pvr_winsys_helper_fill_static_memory(&srv_ws->base,
273bf215546Sopenharmony_ci                                                 srv_ws->general_vma,
274bf215546Sopenharmony_ci                                                 srv_ws->pds_vma,
275bf215546Sopenharmony_ci                                                 srv_ws->usc_vma);
276bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
277bf215546Sopenharmony_ci      goto err_pvr_srv_free_static_memory;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   return VK_SUCCESS;
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_cierr_pvr_srv_free_static_memory:
282bf215546Sopenharmony_ci   pvr_winsys_helper_free_static_memory(srv_ws->general_vma,
283bf215546Sopenharmony_ci                                        srv_ws->pds_vma,
284bf215546Sopenharmony_ci                                        srv_ws->usc_vma);
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_cierr_pvr_srv_heap_finish_rgn_hdr:
287bf215546Sopenharmony_ci   if (srv_ws->rgn_hdr_heap_present)
288bf215546Sopenharmony_ci      pvr_srv_heap_finish(srv_ws, &srv_ws->rgn_hdr_heap);
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_cierr_pvr_srv_heap_finish_vis_test:
291bf215546Sopenharmony_ci   pvr_srv_heap_finish(srv_ws, &srv_ws->vis_test_heap);
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_cierr_pvr_srv_heap_finish_usc:
294bf215546Sopenharmony_ci   pvr_srv_heap_finish(srv_ws, &srv_ws->usc_heap);
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_cierr_pvr_srv_heap_finish_transfer_3d:
297bf215546Sopenharmony_ci   pvr_srv_heap_finish(srv_ws, &srv_ws->transfer_3d_heap);
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_cierr_pvr_srv_heap_finish_pds:
300bf215546Sopenharmony_ci   pvr_srv_heap_finish(srv_ws, &srv_ws->pds_heap);
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_cierr_pvr_srv_heap_finish_general:
303bf215546Sopenharmony_ci   pvr_srv_heap_finish(srv_ws, &srv_ws->general_heap);
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_cierr_pvr_srv_int_ctx_destroy:
306bf215546Sopenharmony_ci   pvr_srv_int_ctx_destroy(srv_ws->render_fd, srv_ws->server_memctx);
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci   return result;
309bf215546Sopenharmony_ci}
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_cistatic void pvr_srv_memctx_finish(struct pvr_srv_winsys *srv_ws)
312bf215546Sopenharmony_ci{
313bf215546Sopenharmony_ci   pvr_winsys_helper_free_static_memory(srv_ws->general_vma,
314bf215546Sopenharmony_ci                                        srv_ws->pds_vma,
315bf215546Sopenharmony_ci                                        srv_ws->usc_vma);
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   if (srv_ws->rgn_hdr_heap_present) {
318bf215546Sopenharmony_ci      if (!pvr_srv_heap_finish(srv_ws, &srv_ws->rgn_hdr_heap)) {
319bf215546Sopenharmony_ci         vk_errorf(NULL,
320bf215546Sopenharmony_ci                   VK_ERROR_UNKNOWN,
321bf215546Sopenharmony_ci                   "Region header heap in use, can not deinit");
322bf215546Sopenharmony_ci      }
323bf215546Sopenharmony_ci   }
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci   if (!pvr_srv_heap_finish(srv_ws, &srv_ws->vis_test_heap)) {
326bf215546Sopenharmony_ci      vk_errorf(NULL,
327bf215546Sopenharmony_ci                VK_ERROR_UNKNOWN,
328bf215546Sopenharmony_ci                "Visibility test heap in use, can not deinit");
329bf215546Sopenharmony_ci   }
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   if (!pvr_srv_heap_finish(srv_ws, &srv_ws->usc_heap))
332bf215546Sopenharmony_ci      vk_errorf(NULL, VK_ERROR_UNKNOWN, "USC heap in use, can not deinit");
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   if (!pvr_srv_heap_finish(srv_ws, &srv_ws->transfer_3d_heap)) {
335bf215546Sopenharmony_ci      vk_errorf(NULL,
336bf215546Sopenharmony_ci                VK_ERROR_UNKNOWN,
337bf215546Sopenharmony_ci                "Transfer 3D heap in use, can not deinit");
338bf215546Sopenharmony_ci   }
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci   if (!pvr_srv_heap_finish(srv_ws, &srv_ws->pds_heap))
341bf215546Sopenharmony_ci      vk_errorf(NULL, VK_ERROR_UNKNOWN, "PDS heap in use, can not deinit");
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   if (!pvr_srv_heap_finish(srv_ws, &srv_ws->general_heap)) {
344bf215546Sopenharmony_ci      vk_errorf(NULL, VK_ERROR_UNKNOWN, "General heap in use, can not deinit");
345bf215546Sopenharmony_ci   }
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   pvr_srv_int_ctx_destroy(srv_ws->render_fd, srv_ws->server_memctx);
348bf215546Sopenharmony_ci}
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_cistatic VkResult pvr_srv_sync_prim_block_init(struct pvr_srv_winsys *srv_ws)
351bf215546Sopenharmony_ci{
352bf215546Sopenharmony_ci   /* We don't currently make use of this value, but we're required to provide
353bf215546Sopenharmony_ci    * a valid pointer to pvr_srv_alloc_sync_primitive_block.
354bf215546Sopenharmony_ci    */
355bf215546Sopenharmony_ci   void *sync_block_pmr;
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci   return pvr_srv_alloc_sync_primitive_block(srv_ws->render_fd,
358bf215546Sopenharmony_ci                                             &srv_ws->sync_block_handle,
359bf215546Sopenharmony_ci                                             &sync_block_pmr,
360bf215546Sopenharmony_ci                                             &srv_ws->sync_block_size,
361bf215546Sopenharmony_ci                                             &srv_ws->sync_block_fw_addr);
362bf215546Sopenharmony_ci}
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_cistatic void pvr_srv_sync_prim_block_finish(struct pvr_srv_winsys *srv_ws)
365bf215546Sopenharmony_ci{
366bf215546Sopenharmony_ci   pvr_srv_free_sync_primitive_block(srv_ws->render_fd,
367bf215546Sopenharmony_ci                                     srv_ws->sync_block_handle);
368bf215546Sopenharmony_ci   srv_ws->sync_block_handle = NULL;
369bf215546Sopenharmony_ci}
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_cistatic void pvr_srv_winsys_destroy(struct pvr_winsys *ws)
372bf215546Sopenharmony_ci{
373bf215546Sopenharmony_ci   struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
374bf215546Sopenharmony_ci   int fd = srv_ws->render_fd;
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci   pvr_srv_sync_prim_block_finish(srv_ws);
377bf215546Sopenharmony_ci   pvr_srv_memctx_finish(srv_ws);
378bf215546Sopenharmony_ci   vk_free(srv_ws->alloc, srv_ws);
379bf215546Sopenharmony_ci   pvr_srv_connection_destroy(fd);
380bf215546Sopenharmony_ci}
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_cistatic uint64_t
383bf215546Sopenharmony_cipvr_srv_get_min_free_list_size(const struct pvr_device_info *dev_info)
384bf215546Sopenharmony_ci{
385bf215546Sopenharmony_ci   uint64_t min_num_pages;
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   if (PVR_HAS_FEATURE(dev_info, roguexe)) {
388bf215546Sopenharmony_ci      if (PVR_HAS_QUIRK(dev_info, 66011))
389bf215546Sopenharmony_ci         min_num_pages = 40U;
390bf215546Sopenharmony_ci      else
391bf215546Sopenharmony_ci         min_num_pages = 25U;
392bf215546Sopenharmony_ci   } else {
393bf215546Sopenharmony_ci      min_num_pages = 50U;
394bf215546Sopenharmony_ci   }
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci   return min_num_pages << ROGUE_BIF_PM_PHYSICAL_PAGE_SHIFT;
397bf215546Sopenharmony_ci}
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_cistatic inline uint64_t
400bf215546Sopenharmony_cipvr_srv_get_num_phantoms(const struct pvr_device_info *dev_info)
401bf215546Sopenharmony_ci{
402bf215546Sopenharmony_ci   return DIV_ROUND_UP(PVR_GET_FEATURE_VALUE(dev_info, num_clusters, 1U), 4U);
403bf215546Sopenharmony_ci}
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci/* Return the total reserved size of partition in dwords. */
406bf215546Sopenharmony_cistatic inline uint64_t pvr_srv_get_total_reserved_partition_size(
407bf215546Sopenharmony_ci   const struct pvr_device_info *dev_info)
408bf215546Sopenharmony_ci{
409bf215546Sopenharmony_ci   uint32_t tile_size_x = PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 0);
410bf215546Sopenharmony_ci   uint32_t tile_size_y = PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 0);
411bf215546Sopenharmony_ci   uint32_t max_partitions = PVR_GET_FEATURE_VALUE(dev_info, max_partitions, 0);
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci   if (tile_size_x == 16 && tile_size_y == 16) {
414bf215546Sopenharmony_ci      return tile_size_x * tile_size_y * max_partitions *
415bf215546Sopenharmony_ci             PVR_GET_FEATURE_VALUE(dev_info,
416bf215546Sopenharmony_ci                                   usc_min_output_registers_per_pix,
417bf215546Sopenharmony_ci                                   0);
418bf215546Sopenharmony_ci   }
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   return max_partitions * 1024U;
421bf215546Sopenharmony_ci}
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_cistatic inline uint64_t
424bf215546Sopenharmony_cipvr_srv_get_reserved_shared_size(const struct pvr_device_info *dev_info)
425bf215546Sopenharmony_ci{
426bf215546Sopenharmony_ci   uint32_t common_store_size_in_dwords =
427bf215546Sopenharmony_ci      PVR_GET_FEATURE_VALUE(dev_info,
428bf215546Sopenharmony_ci                            common_store_size_in_dwords,
429bf215546Sopenharmony_ci                            512U * 4U * 4U);
430bf215546Sopenharmony_ci   uint32_t reserved_shared_size =
431bf215546Sopenharmony_ci      common_store_size_in_dwords - (256U * 4U) -
432bf215546Sopenharmony_ci      pvr_srv_get_total_reserved_partition_size(dev_info);
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci   if (PVR_HAS_QUIRK(dev_info, 44079)) {
435bf215546Sopenharmony_ci      uint32_t common_store_split_point = (768U * 4U * 4U);
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci      return MIN2(common_store_split_point - (256U * 4U), reserved_shared_size);
438bf215546Sopenharmony_ci   }
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   return reserved_shared_size;
441bf215546Sopenharmony_ci}
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_cistatic inline uint64_t
444bf215546Sopenharmony_cipvr_srv_get_max_coeffs(const struct pvr_device_info *dev_info)
445bf215546Sopenharmony_ci{
446bf215546Sopenharmony_ci   uint32_t max_coeff_additional_portion = ROGUE_MAX_VERTEX_SHARED_REGISTERS;
447bf215546Sopenharmony_ci   uint32_t pending_allocation_shared_regs = 2U * 1024U;
448bf215546Sopenharmony_ci   uint32_t pending_allocation_coeff_regs = 0U;
449bf215546Sopenharmony_ci   uint32_t num_phantoms = pvr_srv_get_num_phantoms(dev_info);
450bf215546Sopenharmony_ci   uint32_t tiles_in_flight =
451bf215546Sopenharmony_ci      PVR_GET_FEATURE_VALUE(dev_info, isp_max_tiles_in_flight, 0);
452bf215546Sopenharmony_ci   uint32_t max_coeff_pixel_portion =
453bf215546Sopenharmony_ci      DIV_ROUND_UP(tiles_in_flight, num_phantoms);
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci   max_coeff_pixel_portion *= ROGUE_MAX_PIXEL_SHARED_REGISTERS;
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci   /* Compute tasks on cores with BRN48492 and without compute overlap may lock
458bf215546Sopenharmony_ci    * up without two additional lines of coeffs.
459bf215546Sopenharmony_ci    */
460bf215546Sopenharmony_ci   if (PVR_HAS_QUIRK(dev_info, 48492) &&
461bf215546Sopenharmony_ci       !PVR_HAS_FEATURE(dev_info, compute_overlap)) {
462bf215546Sopenharmony_ci      pending_allocation_coeff_regs = 2U * 1024U;
463bf215546Sopenharmony_ci   }
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   if (PVR_HAS_ERN(dev_info, 38748))
466bf215546Sopenharmony_ci      pending_allocation_shared_regs = 0U;
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci   if (PVR_HAS_ERN(dev_info, 38020)) {
469bf215546Sopenharmony_ci      max_coeff_additional_portion +=
470bf215546Sopenharmony_ci         rogue_max_compute_shared_registers(dev_info);
471bf215546Sopenharmony_ci   }
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   return pvr_srv_get_reserved_shared_size(dev_info) +
474bf215546Sopenharmony_ci          pending_allocation_coeff_regs -
475bf215546Sopenharmony_ci          (max_coeff_pixel_portion + max_coeff_additional_portion +
476bf215546Sopenharmony_ci           pending_allocation_shared_regs);
477bf215546Sopenharmony_ci}
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_cistatic inline uint64_t
480bf215546Sopenharmony_cipvr_srv_get_cdm_max_local_mem_size_regs(const struct pvr_device_info *dev_info)
481bf215546Sopenharmony_ci{
482bf215546Sopenharmony_ci   uint32_t available_coeffs_in_dwords = pvr_srv_get_max_coeffs(dev_info);
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci   if (PVR_HAS_QUIRK(dev_info, 48492) && PVR_HAS_FEATURE(dev_info, roguexe) &&
485bf215546Sopenharmony_ci       !PVR_HAS_FEATURE(dev_info, compute_overlap)) {
486bf215546Sopenharmony_ci      /* Driver must not use the 2 reserved lines. */
487bf215546Sopenharmony_ci      available_coeffs_in_dwords -= ROGUE_CSRM_LINE_SIZE_IN_DWORDS * 2;
488bf215546Sopenharmony_ci   }
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci   /* The maximum amount of local memory available to a kernel is the minimum
491bf215546Sopenharmony_ci    * of the total number of coefficient registers available and the max common
492bf215546Sopenharmony_ci    * store allocation size which can be made by the CDM.
493bf215546Sopenharmony_ci    *
494bf215546Sopenharmony_ci    * If any coeff lines are reserved for tessellation or pixel then we need to
495bf215546Sopenharmony_ci    * subtract those too.
496bf215546Sopenharmony_ci    */
497bf215546Sopenharmony_ci   return MIN2(available_coeffs_in_dwords,
498bf215546Sopenharmony_ci               ROGUE_MAX_PER_KERNEL_LOCAL_MEM_SIZE_REGS);
499bf215546Sopenharmony_ci}
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_cistatic int
502bf215546Sopenharmony_cipvr_srv_winsys_device_info_init(struct pvr_winsys *ws,
503bf215546Sopenharmony_ci                                struct pvr_device_info *dev_info,
504bf215546Sopenharmony_ci                                struct pvr_device_runtime_info *runtime_info)
505bf215546Sopenharmony_ci{
506bf215546Sopenharmony_ci   struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
507bf215546Sopenharmony_ci   VkResult result;
508bf215546Sopenharmony_ci   int ret;
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci   ret = pvr_device_info_init(dev_info, srv_ws->bvnc);
511bf215546Sopenharmony_ci   if (ret) {
512bf215546Sopenharmony_ci      mesa_logw("Unsupported BVNC: %u.%u.%u.%u\n",
513bf215546Sopenharmony_ci                PVR_BVNC_UNPACK_B(srv_ws->bvnc),
514bf215546Sopenharmony_ci                PVR_BVNC_UNPACK_V(srv_ws->bvnc),
515bf215546Sopenharmony_ci                PVR_BVNC_UNPACK_N(srv_ws->bvnc),
516bf215546Sopenharmony_ci                PVR_BVNC_UNPACK_C(srv_ws->bvnc));
517bf215546Sopenharmony_ci      return ret;
518bf215546Sopenharmony_ci   }
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci   runtime_info->min_free_list_size = pvr_srv_get_min_free_list_size(dev_info);
521bf215546Sopenharmony_ci   runtime_info->reserved_shared_size =
522bf215546Sopenharmony_ci      pvr_srv_get_reserved_shared_size(dev_info);
523bf215546Sopenharmony_ci   runtime_info->total_reserved_partition_size =
524bf215546Sopenharmony_ci      pvr_srv_get_total_reserved_partition_size(dev_info);
525bf215546Sopenharmony_ci   runtime_info->num_phantoms = pvr_srv_get_num_phantoms(dev_info);
526bf215546Sopenharmony_ci   runtime_info->max_coeffs = pvr_srv_get_max_coeffs(dev_info);
527bf215546Sopenharmony_ci   runtime_info->cdm_max_local_mem_size_regs =
528bf215546Sopenharmony_ci      pvr_srv_get_cdm_max_local_mem_size_regs(dev_info);
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci   if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) {
531bf215546Sopenharmony_ci      result = pvr_srv_get_multicore_info(srv_ws->render_fd,
532bf215546Sopenharmony_ci                                          0,
533bf215546Sopenharmony_ci                                          NULL,
534bf215546Sopenharmony_ci                                          &runtime_info->core_count);
535bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
536bf215546Sopenharmony_ci         return -ENODEV;
537bf215546Sopenharmony_ci   } else {
538bf215546Sopenharmony_ci      runtime_info->core_count = 1;
539bf215546Sopenharmony_ci   }
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci   return 0;
542bf215546Sopenharmony_ci}
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_cistatic void pvr_srv_winsys_get_heaps_info(struct pvr_winsys *ws,
545bf215546Sopenharmony_ci                                          struct pvr_winsys_heaps *heaps)
546bf215546Sopenharmony_ci{
547bf215546Sopenharmony_ci   struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_ci   heaps->general_heap = &srv_ws->general_heap.base;
550bf215546Sopenharmony_ci   heaps->pds_heap = &srv_ws->pds_heap.base;
551bf215546Sopenharmony_ci   heaps->transfer_3d_heap = &srv_ws->transfer_3d_heap.base;
552bf215546Sopenharmony_ci   heaps->usc_heap = &srv_ws->usc_heap.base;
553bf215546Sopenharmony_ci   heaps->vis_test_heap = &srv_ws->vis_test_heap.base;
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci   if (srv_ws->rgn_hdr_heap_present)
556bf215546Sopenharmony_ci      heaps->rgn_hdr_heap = &srv_ws->rgn_hdr_heap.base;
557bf215546Sopenharmony_ci   else
558bf215546Sopenharmony_ci      heaps->rgn_hdr_heap = &srv_ws->general_heap.base;
559bf215546Sopenharmony_ci}
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_cistatic const struct pvr_winsys_ops srv_winsys_ops = {
562bf215546Sopenharmony_ci   .destroy = pvr_srv_winsys_destroy,
563bf215546Sopenharmony_ci   .device_info_init = pvr_srv_winsys_device_info_init,
564bf215546Sopenharmony_ci   .get_heaps_info = pvr_srv_winsys_get_heaps_info,
565bf215546Sopenharmony_ci   .buffer_create = pvr_srv_winsys_buffer_create,
566bf215546Sopenharmony_ci   .buffer_create_from_fd = pvr_srv_winsys_buffer_create_from_fd,
567bf215546Sopenharmony_ci   .buffer_destroy = pvr_srv_winsys_buffer_destroy,
568bf215546Sopenharmony_ci   .buffer_get_fd = pvr_srv_winsys_buffer_get_fd,
569bf215546Sopenharmony_ci   .buffer_map = pvr_srv_winsys_buffer_map,
570bf215546Sopenharmony_ci   .buffer_unmap = pvr_srv_winsys_buffer_unmap,
571bf215546Sopenharmony_ci   .heap_alloc = pvr_srv_winsys_heap_alloc,
572bf215546Sopenharmony_ci   .heap_free = pvr_srv_winsys_heap_free,
573bf215546Sopenharmony_ci   .vma_map = pvr_srv_winsys_vma_map,
574bf215546Sopenharmony_ci   .vma_unmap = pvr_srv_winsys_vma_unmap,
575bf215546Sopenharmony_ci   .free_list_create = pvr_srv_winsys_free_list_create,
576bf215546Sopenharmony_ci   .free_list_destroy = pvr_srv_winsys_free_list_destroy,
577bf215546Sopenharmony_ci   .render_target_dataset_create = pvr_srv_render_target_dataset_create,
578bf215546Sopenharmony_ci   .render_target_dataset_destroy = pvr_srv_render_target_dataset_destroy,
579bf215546Sopenharmony_ci   .render_ctx_create = pvr_srv_winsys_render_ctx_create,
580bf215546Sopenharmony_ci   .render_ctx_destroy = pvr_srv_winsys_render_ctx_destroy,
581bf215546Sopenharmony_ci   .render_submit = pvr_srv_winsys_render_submit,
582bf215546Sopenharmony_ci   .compute_ctx_create = pvr_srv_winsys_compute_ctx_create,
583bf215546Sopenharmony_ci   .compute_ctx_destroy = pvr_srv_winsys_compute_ctx_destroy,
584bf215546Sopenharmony_ci   .compute_submit = pvr_srv_winsys_compute_submit,
585bf215546Sopenharmony_ci   .transfer_ctx_create = pvr_srv_winsys_transfer_ctx_create,
586bf215546Sopenharmony_ci   .transfer_ctx_destroy = pvr_srv_winsys_transfer_ctx_destroy,
587bf215546Sopenharmony_ci   .transfer_submit = pvr_srv_winsys_transfer_submit,
588bf215546Sopenharmony_ci   .null_job_submit = pvr_srv_winsys_null_job_submit,
589bf215546Sopenharmony_ci};
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_cistatic bool pvr_is_driver_compatible(int render_fd)
592bf215546Sopenharmony_ci{
593bf215546Sopenharmony_ci   drmVersionPtr version;
594bf215546Sopenharmony_ci
595bf215546Sopenharmony_ci   version = drmGetVersion(render_fd);
596bf215546Sopenharmony_ci   if (!version)
597bf215546Sopenharmony_ci      return false;
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_ci   assert(strcmp(version->name, "pvr") == 0);
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci   /* Only the 1.17 driver is supported for now. */
602bf215546Sopenharmony_ci   if (version->version_major != PVR_SRV_VERSION_MAJ ||
603bf215546Sopenharmony_ci       version->version_minor != PVR_SRV_VERSION_MIN) {
604bf215546Sopenharmony_ci      vk_errorf(NULL,
605bf215546Sopenharmony_ci                VK_ERROR_INCOMPATIBLE_DRIVER,
606bf215546Sopenharmony_ci                "Unsupported downstream driver version (%u.%u)",
607bf215546Sopenharmony_ci                version->version_major,
608bf215546Sopenharmony_ci                version->version_minor);
609bf215546Sopenharmony_ci      drmFreeVersion(version);
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci      return false;
612bf215546Sopenharmony_ci   }
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_ci   drmFreeVersion(version);
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci   return true;
617bf215546Sopenharmony_ci}
618bf215546Sopenharmony_ci
619bf215546Sopenharmony_cistruct pvr_winsys *pvr_srv_winsys_create(int master_fd,
620bf215546Sopenharmony_ci                                         int render_fd,
621bf215546Sopenharmony_ci                                         const VkAllocationCallbacks *alloc)
622bf215546Sopenharmony_ci{
623bf215546Sopenharmony_ci   struct pvr_srv_winsys *srv_ws;
624bf215546Sopenharmony_ci   VkResult result;
625bf215546Sopenharmony_ci   uint64_t bvnc;
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci   if (!pvr_is_driver_compatible(render_fd))
628bf215546Sopenharmony_ci      return NULL;
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci   result = pvr_srv_init_module(render_fd, PVR_SRVKM_MODULE_TYPE_SERVICES);
631bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
632bf215546Sopenharmony_ci      return NULL;
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci   result = pvr_srv_connection_create(render_fd, &bvnc);
635bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
636bf215546Sopenharmony_ci      return NULL;
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci   srv_ws =
639bf215546Sopenharmony_ci      vk_zalloc(alloc, sizeof(*srv_ws), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
640bf215546Sopenharmony_ci   if (!srv_ws) {
641bf215546Sopenharmony_ci      vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
642bf215546Sopenharmony_ci      goto err_pvr_srv_connection_destroy;
643bf215546Sopenharmony_ci   }
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci   srv_ws->base.ops = &srv_winsys_ops;
646bf215546Sopenharmony_ci   srv_ws->bvnc = bvnc;
647bf215546Sopenharmony_ci   srv_ws->master_fd = master_fd;
648bf215546Sopenharmony_ci   srv_ws->render_fd = render_fd;
649bf215546Sopenharmony_ci   srv_ws->alloc = alloc;
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci   srv_ws->base.syncobj_type = pvr_srv_sync_type;
652bf215546Sopenharmony_ci   srv_ws->base.sync_types[0] = &srv_ws->base.syncobj_type;
653bf215546Sopenharmony_ci   srv_ws->base.sync_types[1] = NULL;
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci   result = pvr_srv_memctx_init(srv_ws);
656bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
657bf215546Sopenharmony_ci      goto err_vk_free_srv_ws;
658bf215546Sopenharmony_ci
659bf215546Sopenharmony_ci   result = pvr_srv_sync_prim_block_init(srv_ws);
660bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
661bf215546Sopenharmony_ci      goto err_pvr_srv_memctx_finish;
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci   return &srv_ws->base;
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_cierr_pvr_srv_memctx_finish:
666bf215546Sopenharmony_ci   pvr_srv_memctx_finish(srv_ws);
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_cierr_vk_free_srv_ws:
669bf215546Sopenharmony_ci   vk_free(alloc, srv_ws);
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_cierr_pvr_srv_connection_destroy:
672bf215546Sopenharmony_ci   pvr_srv_connection_destroy(render_fd);
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci   return NULL;
675bf215546Sopenharmony_ci}
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_cistruct pvr_srv_sync_prim *pvr_srv_sync_prim_alloc(struct pvr_srv_winsys *srv_ws)
678bf215546Sopenharmony_ci{
679bf215546Sopenharmony_ci   struct pvr_srv_sync_prim *sync_prim;
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_ci   if (p_atomic_read(&srv_ws->sync_block_offset) == srv_ws->sync_block_size) {
682bf215546Sopenharmony_ci      vk_error(NULL, VK_ERROR_UNKNOWN);
683bf215546Sopenharmony_ci      return NULL;
684bf215546Sopenharmony_ci   }
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci   sync_prim = vk_alloc(srv_ws->alloc,
687bf215546Sopenharmony_ci                        sizeof(*sync_prim),
688bf215546Sopenharmony_ci                        8,
689bf215546Sopenharmony_ci                        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
690bf215546Sopenharmony_ci   if (!sync_prim) {
691bf215546Sopenharmony_ci      vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
692bf215546Sopenharmony_ci      return NULL;
693bf215546Sopenharmony_ci   }
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ci   /* p_atomic_add_return() returns the new value rather than the old one, so
696bf215546Sopenharmony_ci    * we have to subtract PVR_SRV_SYNC_PRIM_VALUE_SIZE to get the old value.
697bf215546Sopenharmony_ci    */
698bf215546Sopenharmony_ci   sync_prim->offset = p_atomic_add_return(&srv_ws->sync_block_offset,
699bf215546Sopenharmony_ci                                           PVR_SRV_SYNC_PRIM_VALUE_SIZE);
700bf215546Sopenharmony_ci   sync_prim->offset -= PVR_SRV_SYNC_PRIM_VALUE_SIZE;
701bf215546Sopenharmony_ci   if (sync_prim->offset == srv_ws->sync_block_size) {
702bf215546Sopenharmony_ci      /* FIXME: need to free offset back to srv_ws->sync_block_offset. */
703bf215546Sopenharmony_ci      vk_free(srv_ws->alloc, sync_prim);
704bf215546Sopenharmony_ci
705bf215546Sopenharmony_ci      vk_error(NULL, VK_ERROR_UNKNOWN);
706bf215546Sopenharmony_ci
707bf215546Sopenharmony_ci      return NULL;
708bf215546Sopenharmony_ci   }
709bf215546Sopenharmony_ci
710bf215546Sopenharmony_ci   sync_prim->srv_ws = srv_ws;
711bf215546Sopenharmony_ci
712bf215546Sopenharmony_ci   return sync_prim;
713bf215546Sopenharmony_ci}
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci/* FIXME: Add support for freeing offsets back to the sync block. */
716bf215546Sopenharmony_civoid pvr_srv_sync_prim_free(struct pvr_srv_sync_prim *sync_prim)
717bf215546Sopenharmony_ci{
718bf215546Sopenharmony_ci   if (sync_prim) {
719bf215546Sopenharmony_ci      struct pvr_srv_winsys *srv_ws = sync_prim->srv_ws;
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci      vk_free(srv_ws->alloc, sync_prim);
722bf215546Sopenharmony_ci   }
723bf215546Sopenharmony_ci}
724