1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright 2012 Red Hat Inc.
3d722e3fbSopenharmony_ci *
4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10d722e3fbSopenharmony_ci *
11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice shall be included in
12d722e3fbSopenharmony_ci * all copies or substantial portions of the Software.
13d722e3fbSopenharmony_ci *
14d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17d722e3fbSopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21d722e3fbSopenharmony_ci *
22d722e3fbSopenharmony_ci * Authors: Ben Skeggs
23d722e3fbSopenharmony_ci */
24d722e3fbSopenharmony_ci
25d722e3fbSopenharmony_ci#include <stdio.h>
26d722e3fbSopenharmony_ci#include <stdlib.h>
27d722e3fbSopenharmony_ci#include <stdint.h>
28d722e3fbSopenharmony_ci#include <stdbool.h>
29d722e3fbSopenharmony_ci#include <assert.h>
30d722e3fbSopenharmony_ci#include <errno.h>
31d722e3fbSopenharmony_ci
32d722e3fbSopenharmony_ci#include "libdrm_lists.h"
33d722e3fbSopenharmony_ci
34d722e3fbSopenharmony_ci#include "nouveau.h"
35d722e3fbSopenharmony_ci#include "private.h"
36d722e3fbSopenharmony_ci
37d722e3fbSopenharmony_cistruct nouveau_bufref_priv {
38d722e3fbSopenharmony_ci	struct nouveau_bufref base;
39d722e3fbSopenharmony_ci	struct nouveau_bufref_priv *next;
40d722e3fbSopenharmony_ci	struct nouveau_bufctx *bufctx;
41d722e3fbSopenharmony_ci};
42d722e3fbSopenharmony_ci
43d722e3fbSopenharmony_cistruct nouveau_bufbin_priv {
44d722e3fbSopenharmony_ci	struct nouveau_bufref_priv *list;
45d722e3fbSopenharmony_ci	int relocs;
46d722e3fbSopenharmony_ci};
47d722e3fbSopenharmony_ci
48d722e3fbSopenharmony_cistruct nouveau_bufctx_priv {
49d722e3fbSopenharmony_ci	struct nouveau_bufctx base;
50d722e3fbSopenharmony_ci	struct nouveau_bufref_priv *free;
51d722e3fbSopenharmony_ci	int nr_bins;
52d722e3fbSopenharmony_ci	struct nouveau_bufbin_priv bins[];
53d722e3fbSopenharmony_ci};
54d722e3fbSopenharmony_ci
55d722e3fbSopenharmony_cistatic inline struct nouveau_bufctx_priv *
56d722e3fbSopenharmony_cinouveau_bufctx(struct nouveau_bufctx *bctx)
57d722e3fbSopenharmony_ci{
58d722e3fbSopenharmony_ci	return (struct nouveau_bufctx_priv *)bctx;
59d722e3fbSopenharmony_ci}
60d722e3fbSopenharmony_ci
61d722e3fbSopenharmony_cidrm_public int
62d722e3fbSopenharmony_cinouveau_bufctx_new(struct nouveau_client *client, int bins,
63d722e3fbSopenharmony_ci		   struct nouveau_bufctx **pbctx)
64d722e3fbSopenharmony_ci{
65d722e3fbSopenharmony_ci	struct nouveau_bufctx_priv *priv;
66d722e3fbSopenharmony_ci
67d722e3fbSopenharmony_ci	priv = calloc(1, sizeof(*priv) + sizeof(priv->bins[0]) * bins);
68d722e3fbSopenharmony_ci	if (priv) {
69d722e3fbSopenharmony_ci		DRMINITLISTHEAD(&priv->base.head);
70d722e3fbSopenharmony_ci		DRMINITLISTHEAD(&priv->base.pending);
71d722e3fbSopenharmony_ci		DRMINITLISTHEAD(&priv->base.current);
72d722e3fbSopenharmony_ci		priv->base.client = client;
73d722e3fbSopenharmony_ci		priv->nr_bins = bins;
74d722e3fbSopenharmony_ci		*pbctx = &priv->base;
75d722e3fbSopenharmony_ci		return 0;
76d722e3fbSopenharmony_ci	}
77d722e3fbSopenharmony_ci
78d722e3fbSopenharmony_ci	return -ENOMEM;
79d722e3fbSopenharmony_ci}
80d722e3fbSopenharmony_ci
81d722e3fbSopenharmony_cidrm_public void
82d722e3fbSopenharmony_cinouveau_bufctx_del(struct nouveau_bufctx **pbctx)
83d722e3fbSopenharmony_ci{
84d722e3fbSopenharmony_ci	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx);
85d722e3fbSopenharmony_ci	struct nouveau_bufref_priv *pref;
86d722e3fbSopenharmony_ci	if (pctx) {
87d722e3fbSopenharmony_ci		while (pctx->nr_bins--)
88d722e3fbSopenharmony_ci			nouveau_bufctx_reset(&pctx->base, pctx->nr_bins);
89d722e3fbSopenharmony_ci		while ((pref = pctx->free)) {
90d722e3fbSopenharmony_ci			pctx->free = pref->next;
91d722e3fbSopenharmony_ci			free(pref);
92d722e3fbSopenharmony_ci		}
93d722e3fbSopenharmony_ci		free(pctx);
94d722e3fbSopenharmony_ci		*pbctx = NULL;
95d722e3fbSopenharmony_ci	}
96d722e3fbSopenharmony_ci}
97d722e3fbSopenharmony_ci
98d722e3fbSopenharmony_cidrm_public void
99d722e3fbSopenharmony_cinouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin)
100d722e3fbSopenharmony_ci{
101d722e3fbSopenharmony_ci	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
102d722e3fbSopenharmony_ci	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
103d722e3fbSopenharmony_ci	struct nouveau_bufref_priv *pref;
104d722e3fbSopenharmony_ci
105d722e3fbSopenharmony_ci	while ((pref = pbin->list)) {
106d722e3fbSopenharmony_ci		DRMLISTDELINIT(&pref->base.thead);
107d722e3fbSopenharmony_ci		pbin->list = pref->next;
108d722e3fbSopenharmony_ci		pref->next = pctx->free;
109d722e3fbSopenharmony_ci		pctx->free = pref;
110d722e3fbSopenharmony_ci	}
111d722e3fbSopenharmony_ci
112d722e3fbSopenharmony_ci	bctx->relocs -= pbin->relocs;
113d722e3fbSopenharmony_ci	pbin->relocs  = 0;
114d722e3fbSopenharmony_ci}
115d722e3fbSopenharmony_ci
116d722e3fbSopenharmony_cidrm_public struct nouveau_bufref *
117d722e3fbSopenharmony_cinouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin,
118d722e3fbSopenharmony_ci		    struct nouveau_bo *bo, uint32_t flags)
119d722e3fbSopenharmony_ci{
120d722e3fbSopenharmony_ci	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
121d722e3fbSopenharmony_ci	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
122d722e3fbSopenharmony_ci	struct nouveau_bufref_priv *pref = pctx->free;
123d722e3fbSopenharmony_ci
124d722e3fbSopenharmony_ci	if (!pref)
125d722e3fbSopenharmony_ci		pref = malloc(sizeof(*pref));
126d722e3fbSopenharmony_ci	else
127d722e3fbSopenharmony_ci		pctx->free = pref->next;
128d722e3fbSopenharmony_ci
129d722e3fbSopenharmony_ci	if (pref) {
130d722e3fbSopenharmony_ci		pref->base.bo = bo;
131d722e3fbSopenharmony_ci		pref->base.flags = flags;
132d722e3fbSopenharmony_ci		pref->base.packet = 0;
133d722e3fbSopenharmony_ci
134d722e3fbSopenharmony_ci		DRMLISTADDTAIL(&pref->base.thead, &bctx->pending);
135d722e3fbSopenharmony_ci		pref->bufctx = bctx;
136d722e3fbSopenharmony_ci		pref->next = pbin->list;
137d722e3fbSopenharmony_ci		pbin->list = pref;
138d722e3fbSopenharmony_ci	}
139d722e3fbSopenharmony_ci
140d722e3fbSopenharmony_ci	return &pref->base;
141d722e3fbSopenharmony_ci}
142d722e3fbSopenharmony_ci
143d722e3fbSopenharmony_cidrm_public struct nouveau_bufref *
144d722e3fbSopenharmony_cinouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet,
145d722e3fbSopenharmony_ci		    struct nouveau_bo *bo, uint64_t data, uint32_t flags,
146d722e3fbSopenharmony_ci		    uint32_t vor, uint32_t tor)
147d722e3fbSopenharmony_ci{
148d722e3fbSopenharmony_ci	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
149d722e3fbSopenharmony_ci	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
150d722e3fbSopenharmony_ci	struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags);
151d722e3fbSopenharmony_ci	if (bref) {
152d722e3fbSopenharmony_ci		bref->packet = packet;
153d722e3fbSopenharmony_ci		bref->data = data;
154d722e3fbSopenharmony_ci		bref->vor = vor;
155d722e3fbSopenharmony_ci		bref->tor = tor;
156d722e3fbSopenharmony_ci		pbin->relocs++;
157d722e3fbSopenharmony_ci		bctx->relocs++;
158d722e3fbSopenharmony_ci	}
159d722e3fbSopenharmony_ci	return bref;
160d722e3fbSopenharmony_ci}
161