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 | |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 25 | #include <stdio.h> |
| 26 | #include <stdlib.h> |
| 27 | #include <stdint.h> |
| 28 | #include <stdbool.h> |
| 29 | #include <assert.h> |
| 30 | #include <errno.h> |
| 31 | |
| 32 | #include "libdrm_lists.h" |
| 33 | |
| 34 | #include "nouveau.h" |
| 35 | #include "private.h" |
| 36 | |
| 37 | struct nouveau_bufref_priv { |
| 38 | struct nouveau_bufref base; |
| 39 | struct nouveau_bufref_priv *next; |
| 40 | struct nouveau_bufctx *bufctx; |
| 41 | }; |
| 42 | |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 43 | struct nouveau_bufbin_priv { |
| 44 | struct nouveau_bufref_priv *list; |
| 45 | int relocs; |
| 46 | }; |
| 47 | |
| 48 | struct nouveau_bufctx_priv { |
| 49 | struct nouveau_bufctx base; |
| 50 | struct nouveau_bufref_priv *free; |
| 51 | int nr_bins; |
| 52 | struct nouveau_bufbin_priv bins[]; |
| 53 | }; |
| 54 | |
| 55 | static inline struct nouveau_bufctx_priv * |
| 56 | nouveau_bufctx(struct nouveau_bufctx *bctx) |
| 57 | { |
| 58 | return (struct nouveau_bufctx_priv *)bctx; |
| 59 | } |
| 60 | |
Lucas De Marchi | d7320bf | 2018-09-13 14:39:50 -0700 | [diff] [blame] | 61 | drm_public int |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 62 | nouveau_bufctx_new(struct nouveau_client *client, int bins, |
| 63 | struct nouveau_bufctx **pbctx) |
| 64 | { |
| 65 | struct nouveau_bufctx_priv *priv; |
| 66 | |
| 67 | priv = calloc(1, sizeof(*priv) + sizeof(priv->bins[0]) * bins); |
| 68 | if (priv) { |
| 69 | DRMINITLISTHEAD(&priv->base.head); |
| 70 | DRMINITLISTHEAD(&priv->base.pending); |
| 71 | DRMINITLISTHEAD(&priv->base.current); |
| 72 | priv->base.client = client; |
| 73 | priv->nr_bins = bins; |
| 74 | *pbctx = &priv->base; |
| 75 | return 0; |
| 76 | } |
| 77 | |
| 78 | return -ENOMEM; |
| 79 | } |
| 80 | |
Lucas De Marchi | d7320bf | 2018-09-13 14:39:50 -0700 | [diff] [blame] | 81 | drm_public void |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 82 | nouveau_bufctx_del(struct nouveau_bufctx **pbctx) |
| 83 | { |
| 84 | struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx); |
| 85 | struct nouveau_bufref_priv *pref; |
| 86 | if (pctx) { |
| 87 | while (pctx->nr_bins--) |
| 88 | nouveau_bufctx_reset(&pctx->base, pctx->nr_bins); |
| 89 | while ((pref = pctx->free)) { |
| 90 | pctx->free = pref->next; |
| 91 | free(pref); |
| 92 | } |
| 93 | free(pctx); |
| 94 | *pbctx = NULL; |
| 95 | } |
| 96 | } |
| 97 | |
Lucas De Marchi | d7320bf | 2018-09-13 14:39:50 -0700 | [diff] [blame] | 98 | drm_public void |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 99 | nouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin) |
| 100 | { |
| 101 | struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx); |
| 102 | struct nouveau_bufbin_priv *pbin = &pctx->bins[bin]; |
| 103 | struct nouveau_bufref_priv *pref; |
| 104 | |
| 105 | while ((pref = pbin->list)) { |
| 106 | DRMLISTDELINIT(&pref->base.thead); |
| 107 | pbin->list = pref->next; |
| 108 | pref->next = pctx->free; |
| 109 | pctx->free = pref; |
| 110 | } |
| 111 | |
| 112 | bctx->relocs -= pbin->relocs; |
| 113 | pbin->relocs = 0; |
| 114 | } |
| 115 | |
Lucas De Marchi | d7320bf | 2018-09-13 14:39:50 -0700 | [diff] [blame] | 116 | drm_public struct nouveau_bufref * |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 117 | nouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin, |
| 118 | struct nouveau_bo *bo, uint32_t flags) |
| 119 | { |
| 120 | struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx); |
| 121 | struct nouveau_bufbin_priv *pbin = &pctx->bins[bin]; |
| 122 | struct nouveau_bufref_priv *pref = pctx->free; |
| 123 | |
| 124 | if (!pref) |
| 125 | pref = malloc(sizeof(*pref)); |
| 126 | else |
| 127 | pctx->free = pref->next; |
| 128 | |
| 129 | if (pref) { |
| 130 | pref->base.bo = bo; |
| 131 | pref->base.flags = flags; |
| 132 | pref->base.packet = 0; |
| 133 | |
| 134 | DRMLISTADDTAIL(&pref->base.thead, &bctx->pending); |
| 135 | pref->bufctx = bctx; |
| 136 | pref->next = pbin->list; |
| 137 | pbin->list = pref; |
| 138 | } |
| 139 | |
| 140 | return &pref->base; |
| 141 | } |
| 142 | |
Lucas De Marchi | d7320bf | 2018-09-13 14:39:50 -0700 | [diff] [blame] | 143 | drm_public struct nouveau_bufref * |
Ben Skeggs | 292da61 | 2011-12-09 16:11:06 +1000 | [diff] [blame] | 144 | nouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet, |
| 145 | struct nouveau_bo *bo, uint64_t data, uint32_t flags, |
| 146 | uint32_t vor, uint32_t tor) |
| 147 | { |
| 148 | struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx); |
| 149 | struct nouveau_bufbin_priv *pbin = &pctx->bins[bin]; |
| 150 | struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags); |
| 151 | if (bref) { |
| 152 | bref->packet = packet; |
| 153 | bref->data = data; |
| 154 | bref->vor = vor; |
| 155 | bref->tor = tor; |
| 156 | pbin->relocs++; |
| 157 | bctx->relocs++; |
| 158 | } |
| 159 | return bref; |
| 160 | } |