Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2012 Red Hat Inc. |
| 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 20 | * OTHER DEALINGS IN THE SOFTWARE. |
| 21 | * |
| 22 | * Authors: Ben Skeggs |
| 23 | */ |
| 24 | |
| 25 | #ifdef HAVE_CONFIG_H |
| 26 | #include <config.h> |
| 27 | #endif |
| 28 | |
| 29 | #include <stdio.h> |
| 30 | #include <stdlib.h> |
| 31 | #include <stdint.h> |
| 32 | #include <stdbool.h> |
| 33 | #include <assert.h> |
| 34 | #include <errno.h> |
| 35 | |
| 36 | #include "libdrm_lists.h" |
| 37 | |
| 38 | #include "nouveau.h" |
| 39 | #include "private.h" |
| 40 | |
| 41 | struct nouveau_bufref_priv { |
| 42 | struct nouveau_bufref base; |
| 43 | struct nouveau_bufref_priv *next; |
| 44 | struct nouveau_bufctx *bufctx; |
| 45 | }; |
| 46 | |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 47 | struct nouveau_bufbin_priv { |
| 48 | struct nouveau_bufref_priv *list; |
| 49 | int relocs; |
| 50 | }; |
| 51 | |
| 52 | struct nouveau_bufctx_priv { |
| 53 | struct nouveau_bufctx base; |
| 54 | struct nouveau_bufref_priv *free; |
| 55 | int nr_bins; |
| 56 | struct nouveau_bufbin_priv bins[]; |
| 57 | }; |
| 58 | |
| 59 | static inline struct nouveau_bufctx_priv * |
| 60 | nouveau_bufctx(struct nouveau_bufctx *bctx) |
| 61 | { |
| 62 | return (struct nouveau_bufctx_priv *)bctx; |
| 63 | } |
| 64 | |
Emil Velikov | 0f8da82 | 2015-03-31 22:32:11 +0100 | [diff] [blame^] | 65 | int |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 66 | nouveau_bufctx_new(struct nouveau_client *client, int bins, |
| 67 | struct nouveau_bufctx **pbctx) |
| 68 | { |
| 69 | struct nouveau_bufctx_priv *priv; |
| 70 | |
| 71 | priv = calloc(1, sizeof(*priv) + sizeof(priv->bins[0]) * bins); |
| 72 | if (priv) { |
| 73 | DRMINITLISTHEAD(&priv->base.head); |
| 74 | DRMINITLISTHEAD(&priv->base.pending); |
| 75 | DRMINITLISTHEAD(&priv->base.current); |
| 76 | priv->base.client = client; |
| 77 | priv->nr_bins = bins; |
| 78 | *pbctx = &priv->base; |
| 79 | return 0; |
| 80 | } |
| 81 | |
| 82 | return -ENOMEM; |
| 83 | } |
| 84 | |
Emil Velikov | 0f8da82 | 2015-03-31 22:32:11 +0100 | [diff] [blame^] | 85 | void |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 86 | nouveau_bufctx_del(struct nouveau_bufctx **pbctx) |
| 87 | { |
| 88 | struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx); |
| 89 | struct nouveau_bufref_priv *pref; |
| 90 | if (pctx) { |
| 91 | while (pctx->nr_bins--) |
| 92 | nouveau_bufctx_reset(&pctx->base, pctx->nr_bins); |
| 93 | while ((pref = pctx->free)) { |
| 94 | pctx->free = pref->next; |
| 95 | free(pref); |
| 96 | } |
| 97 | free(pctx); |
| 98 | *pbctx = NULL; |
| 99 | } |
| 100 | } |
| 101 | |
Emil Velikov | 0f8da82 | 2015-03-31 22:32:11 +0100 | [diff] [blame^] | 102 | void |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 103 | nouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin) |
| 104 | { |
| 105 | struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx); |
| 106 | struct nouveau_bufbin_priv *pbin = &pctx->bins[bin]; |
| 107 | struct nouveau_bufref_priv *pref; |
| 108 | |
| 109 | while ((pref = pbin->list)) { |
| 110 | DRMLISTDELINIT(&pref->base.thead); |
| 111 | pbin->list = pref->next; |
| 112 | pref->next = pctx->free; |
| 113 | pctx->free = pref; |
| 114 | } |
| 115 | |
| 116 | bctx->relocs -= pbin->relocs; |
| 117 | pbin->relocs = 0; |
| 118 | } |
| 119 | |
Emil Velikov | 0f8da82 | 2015-03-31 22:32:11 +0100 | [diff] [blame^] | 120 | struct nouveau_bufref * |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 121 | nouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin, |
| 122 | struct nouveau_bo *bo, uint32_t flags) |
| 123 | { |
| 124 | struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx); |
| 125 | struct nouveau_bufbin_priv *pbin = &pctx->bins[bin]; |
| 126 | struct nouveau_bufref_priv *pref = pctx->free; |
| 127 | |
| 128 | if (!pref) |
| 129 | pref = malloc(sizeof(*pref)); |
| 130 | else |
| 131 | pctx->free = pref->next; |
| 132 | |
| 133 | if (pref) { |
| 134 | pref->base.bo = bo; |
| 135 | pref->base.flags = flags; |
| 136 | pref->base.packet = 0; |
| 137 | |
| 138 | DRMLISTADDTAIL(&pref->base.thead, &bctx->pending); |
| 139 | pref->bufctx = bctx; |
| 140 | pref->next = pbin->list; |
| 141 | pbin->list = pref; |
| 142 | } |
| 143 | |
| 144 | return &pref->base; |
| 145 | } |
| 146 | |
Emil Velikov | 0f8da82 | 2015-03-31 22:32:11 +0100 | [diff] [blame^] | 147 | struct nouveau_bufref * |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 148 | nouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet, |
| 149 | struct nouveau_bo *bo, uint64_t data, uint32_t flags, |
| 150 | uint32_t vor, uint32_t tor) |
| 151 | { |
| 152 | struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx); |
| 153 | struct nouveau_bufbin_priv *pbin = &pctx->bins[bin]; |
| 154 | struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags); |
| 155 | if (bref) { |
| 156 | bref->packet = packet; |
| 157 | bref->data = data; |
| 158 | bref->vor = vor; |
| 159 | bref->tor = tor; |
| 160 | pbin->relocs++; |
| 161 | bctx->relocs++; |
| 162 | } |
| 163 | return bref; |
| 164 | } |