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