bufctx.c revision e88f27b3
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#ifdef HAVE_CONFIG_H
26e88f27b3Smrg#include <config.h>
27e88f27b3Smrg#endif
28e88f27b3Smrg
29e88f27b3Smrg#include <stdio.h>
30e88f27b3Smrg#include <stdlib.h>
31e88f27b3Smrg#include <stdint.h>
32e88f27b3Smrg#include <stdbool.h>
33e88f27b3Smrg#include <assert.h>
34e88f27b3Smrg#include <errno.h>
35e88f27b3Smrg
36e88f27b3Smrg#include "libdrm_lists.h"
37e88f27b3Smrg
38e88f27b3Smrg#include "nouveau.h"
39e88f27b3Smrg#include "private.h"
40e88f27b3Smrg
41e88f27b3Smrgstruct nouveau_bufref_priv {
42e88f27b3Smrg	struct nouveau_bufref base;
43e88f27b3Smrg	struct nouveau_bufref_priv *next;
44e88f27b3Smrg	struct nouveau_bufctx *bufctx;
45e88f27b3Smrg};
46e88f27b3Smrg
47e88f27b3Smrgstatic inline struct nouveau_bufref_priv *
48e88f27b3Smrgnouveau_bufref(struct nouveau_bufref *bctx)
49e88f27b3Smrg{
50e88f27b3Smrg	return (struct nouveau_bufref_priv *)bctx;
51e88f27b3Smrg}
52e88f27b3Smrg
53e88f27b3Smrgstruct nouveau_bufbin_priv {
54e88f27b3Smrg	struct nouveau_bufref_priv *list;
55e88f27b3Smrg	int relocs;
56e88f27b3Smrg};
57e88f27b3Smrg
58e88f27b3Smrgstruct nouveau_bufctx_priv {
59e88f27b3Smrg	struct nouveau_bufctx base;
60e88f27b3Smrg	struct nouveau_bufref_priv *free;
61e88f27b3Smrg	int nr_bins;
62e88f27b3Smrg	struct nouveau_bufbin_priv bins[];
63e88f27b3Smrg};
64e88f27b3Smrg
65e88f27b3Smrgstatic inline struct nouveau_bufctx_priv *
66e88f27b3Smrgnouveau_bufctx(struct nouveau_bufctx *bctx)
67e88f27b3Smrg{
68e88f27b3Smrg	return (struct nouveau_bufctx_priv *)bctx;
69e88f27b3Smrg}
70e88f27b3Smrg
71e88f27b3Smrgint
72e88f27b3Smrgnouveau_bufctx_new(struct nouveau_client *client, int bins,
73e88f27b3Smrg		   struct nouveau_bufctx **pbctx)
74e88f27b3Smrg{
75e88f27b3Smrg	struct nouveau_bufctx_priv *priv;
76e88f27b3Smrg
77e88f27b3Smrg	priv = calloc(1, sizeof(*priv) + sizeof(priv->bins[0]) * bins);
78e88f27b3Smrg	if (priv) {
79e88f27b3Smrg		DRMINITLISTHEAD(&priv->base.head);
80e88f27b3Smrg		DRMINITLISTHEAD(&priv->base.pending);
81e88f27b3Smrg		DRMINITLISTHEAD(&priv->base.current);
82e88f27b3Smrg		priv->base.client = client;
83e88f27b3Smrg		priv->nr_bins = bins;
84e88f27b3Smrg		*pbctx = &priv->base;
85e88f27b3Smrg		return 0;
86e88f27b3Smrg	}
87e88f27b3Smrg
88e88f27b3Smrg	return -ENOMEM;
89e88f27b3Smrg}
90e88f27b3Smrg
91e88f27b3Smrgvoid
92e88f27b3Smrgnouveau_bufctx_del(struct nouveau_bufctx **pbctx)
93e88f27b3Smrg{
94e88f27b3Smrg	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx);
95e88f27b3Smrg	struct nouveau_bufref_priv *pref;
96e88f27b3Smrg	if (pctx) {
97e88f27b3Smrg		while (pctx->nr_bins--)
98e88f27b3Smrg			nouveau_bufctx_reset(&pctx->base, pctx->nr_bins);
99e88f27b3Smrg		while ((pref = pctx->free)) {
100e88f27b3Smrg			pctx->free = pref->next;
101e88f27b3Smrg			free(pref);
102e88f27b3Smrg		}
103e88f27b3Smrg		free(pctx);
104e88f27b3Smrg		*pbctx = NULL;
105e88f27b3Smrg	}
106e88f27b3Smrg}
107e88f27b3Smrg
108e88f27b3Smrgvoid
109e88f27b3Smrgnouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin)
110e88f27b3Smrg{
111e88f27b3Smrg	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
112e88f27b3Smrg	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
113e88f27b3Smrg	struct nouveau_bufref_priv *pref;
114e88f27b3Smrg
115e88f27b3Smrg	while ((pref = pbin->list)) {
116e88f27b3Smrg		DRMLISTDELINIT(&pref->base.thead);
117e88f27b3Smrg		pbin->list = pref->next;
118e88f27b3Smrg		pref->next = pctx->free;
119e88f27b3Smrg		pctx->free = pref;
120e88f27b3Smrg	}
121e88f27b3Smrg
122e88f27b3Smrg	bctx->relocs -= pbin->relocs;
123e88f27b3Smrg	pbin->relocs  = 0;
124e88f27b3Smrg}
125e88f27b3Smrg
126e88f27b3Smrgstruct nouveau_bufref *
127e88f27b3Smrgnouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin,
128e88f27b3Smrg		    struct nouveau_bo *bo, uint32_t flags)
129e88f27b3Smrg{
130e88f27b3Smrg	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
131e88f27b3Smrg	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
132e88f27b3Smrg	struct nouveau_bufref_priv *pref = pctx->free;
133e88f27b3Smrg
134e88f27b3Smrg	if (!pref)
135e88f27b3Smrg		pref = malloc(sizeof(*pref));
136e88f27b3Smrg	else
137e88f27b3Smrg		pctx->free = pref->next;
138e88f27b3Smrg
139e88f27b3Smrg	if (pref) {
140e88f27b3Smrg		pref->base.bo = bo;
141e88f27b3Smrg		pref->base.flags = flags;
142e88f27b3Smrg		pref->base.packet = 0;
143e88f27b3Smrg
144e88f27b3Smrg		DRMLISTADDTAIL(&pref->base.thead, &bctx->pending);
145e88f27b3Smrg		pref->bufctx = bctx;
146e88f27b3Smrg		pref->next = pbin->list;
147e88f27b3Smrg		pbin->list = pref;
148e88f27b3Smrg	}
149e88f27b3Smrg
150e88f27b3Smrg	return &pref->base;
151e88f27b3Smrg}
152e88f27b3Smrg
153e88f27b3Smrgstruct nouveau_bufref *
154e88f27b3Smrgnouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet,
155e88f27b3Smrg		    struct nouveau_bo *bo, uint64_t data, uint32_t flags,
156e88f27b3Smrg		    uint32_t vor, uint32_t tor)
157e88f27b3Smrg{
158e88f27b3Smrg	struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
159e88f27b3Smrg	struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
160e88f27b3Smrg	struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags);
161e88f27b3Smrg	if (bref) {
162e88f27b3Smrg		bref->packet = packet;
163e88f27b3Smrg		bref->data = data;
164e88f27b3Smrg		bref->vor = vor;
165e88f27b3Smrg		bref->tor = tor;
166e88f27b3Smrg		pbin->relocs++;
167e88f27b3Smrg		bctx->relocs++;
168e88f27b3Smrg	}
169e88f27b3Smrg	return bref;
170e88f27b3Smrg}
171