Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2010 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 | #include "drmP.h" |
| 26 | |
| 27 | #include "nouveau_drv.h" |
| 28 | #include "nouveau_ramht.h" |
| 29 | |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 30 | static u32 |
| 31 | nouveau_ramht_hash_handle(struct nouveau_channel *chan, u32 handle) |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 32 | { |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 33 | struct drm_device *dev = chan->dev; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 34 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 35 | struct nouveau_ramht *ramht = chan->ramht; |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 36 | u32 hash = 0; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 37 | int i; |
| 38 | |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 39 | NV_DEBUG(dev, "ch%d handle=0x%08x\n", chan->id, handle); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 40 | |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 41 | for (i = 32; i > 0; i -= ramht->bits) { |
| 42 | hash ^= (handle & ((1 << ramht->bits) - 1)); |
| 43 | handle >>= ramht->bits; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 44 | } |
| 45 | |
| 46 | if (dev_priv->card_type < NV_50) |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 47 | hash ^= chan->id << (ramht->bits - 4); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 48 | hash <<= 3; |
| 49 | |
| 50 | NV_DEBUG(dev, "hash=0x%08x\n", hash); |
| 51 | return hash; |
| 52 | } |
| 53 | |
| 54 | static int |
| 55 | nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 56 | u32 offset) |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 57 | { |
| 58 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 59 | u32 ctx = nv_ro32(ramht, offset + 4); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 60 | |
| 61 | if (dev_priv->card_type < NV_40) |
| 62 | return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); |
| 63 | return (ctx != 0); |
| 64 | } |
| 65 | |
Francisco Jerez | 3bc14b4 | 2010-09-05 06:03:07 +0200 | [diff] [blame] | 66 | static int |
| 67 | nouveau_ramht_entry_same_channel(struct nouveau_channel *chan, |
| 68 | struct nouveau_gpuobj *ramht, u32 offset) |
| 69 | { |
| 70 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; |
| 71 | u32 ctx = nv_ro32(ramht, offset + 4); |
| 72 | |
| 73 | if (dev_priv->card_type >= NV_50) |
| 74 | return true; |
| 75 | else if (dev_priv->card_type >= NV_40) |
| 76 | return chan->id == |
| 77 | ((ctx >> NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); |
| 78 | else |
| 79 | return chan->id == |
| 80 | ((ctx >> NV_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f); |
| 81 | } |
| 82 | |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 83 | int |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 84 | nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, |
| 85 | struct nouveau_gpuobj *gpuobj) |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 86 | { |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 87 | struct drm_device *dev = chan->dev; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 88 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 89 | struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 90 | struct nouveau_ramht_entry *entry; |
| 91 | struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 92 | unsigned long flags; |
| 93 | u32 ctx, co, ho; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 94 | |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 95 | if (nouveau_ramht_find(chan, handle)) |
| 96 | return -EEXIST; |
| 97 | |
| 98 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
| 99 | if (!entry) |
| 100 | return -ENOMEM; |
| 101 | entry->channel = chan; |
| 102 | entry->gpuobj = NULL; |
| 103 | entry->handle = handle; |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 104 | nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 105 | |
| 106 | if (dev_priv->card_type < NV_40) { |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 107 | ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->cinst >> 4) | |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 108 | (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 109 | (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 110 | } else |
| 111 | if (dev_priv->card_type < NV_50) { |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 112 | ctx = (gpuobj->cinst >> 4) | |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 113 | (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 114 | (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 115 | } else { |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 116 | if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { |
| 117 | ctx = (gpuobj->cinst << 10) | 2; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 118 | } else { |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 119 | ctx = (gpuobj->cinst >> 4) | |
| 120 | ((gpuobj->engine << |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 121 | NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); |
| 122 | } |
| 123 | } |
| 124 | |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 125 | spin_lock_irqsave(&chan->ramht->lock, flags); |
| 126 | list_add(&entry->head, &chan->ramht->entries); |
| 127 | |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 128 | co = ho = nouveau_ramht_hash_handle(chan, handle); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 129 | do { |
| 130 | if (!nouveau_ramht_entry_valid(dev, ramht, co)) { |
| 131 | NV_DEBUG(dev, |
| 132 | "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 133 | chan->id, co, handle, ctx); |
| 134 | nv_wo32(ramht, co + 0, handle); |
Ben Skeggs | b3beb16 | 2010-09-01 15:24:29 +1000 | [diff] [blame] | 135 | nv_wo32(ramht, co + 4, ctx); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 136 | |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 137 | spin_unlock_irqrestore(&chan->ramht->lock, flags); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 138 | instmem->flush(dev); |
| 139 | return 0; |
| 140 | } |
| 141 | NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", |
Ben Skeggs | b3beb16 | 2010-09-01 15:24:29 +1000 | [diff] [blame] | 142 | chan->id, co, nv_ro32(ramht, co)); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 143 | |
| 144 | co += 8; |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 145 | if (co >= ramht->size) |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 146 | co = 0; |
| 147 | } while (co != ho); |
| 148 | |
| 149 | NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 150 | list_del(&entry->head); |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 151 | spin_unlock_irqrestore(&chan->ramht->lock, flags); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 152 | kfree(entry); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 153 | return -ENOMEM; |
| 154 | } |
| 155 | |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 156 | static void |
| 157 | nouveau_ramht_remove_locked(struct nouveau_channel *chan, u32 handle) |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 158 | { |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 159 | struct drm_device *dev = chan->dev; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 160 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 161 | struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 162 | struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; |
| 163 | struct nouveau_ramht_entry *entry, *tmp; |
| 164 | u32 co, ho; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 165 | |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 166 | list_for_each_entry_safe(entry, tmp, &chan->ramht->entries, head) { |
| 167 | if (entry->channel != chan || entry->handle != handle) |
| 168 | continue; |
| 169 | |
| 170 | nouveau_gpuobj_ref(NULL, &entry->gpuobj); |
| 171 | list_del(&entry->head); |
| 172 | kfree(entry); |
| 173 | break; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 174 | } |
| 175 | |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 176 | co = ho = nouveau_ramht_hash_handle(chan, handle); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 177 | do { |
| 178 | if (nouveau_ramht_entry_valid(dev, ramht, co) && |
Francisco Jerez | 3bc14b4 | 2010-09-05 06:03:07 +0200 | [diff] [blame] | 179 | nouveau_ramht_entry_same_channel(chan, ramht, co) && |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 180 | (handle == nv_ro32(ramht, co))) { |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 181 | NV_DEBUG(dev, |
| 182 | "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 183 | chan->id, co, handle, nv_ro32(ramht, co + 4)); |
Ben Skeggs | b3beb16 | 2010-09-01 15:24:29 +1000 | [diff] [blame] | 184 | nv_wo32(ramht, co + 0, 0x00000000); |
| 185 | nv_wo32(ramht, co + 4, 0x00000000); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 186 | instmem->flush(dev); |
| 187 | return; |
| 188 | } |
| 189 | |
| 190 | co += 8; |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 191 | if (co >= ramht->size) |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 192 | co = 0; |
| 193 | } while (co != ho); |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 194 | |
| 195 | NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 196 | chan->id, handle); |
| 197 | } |
| 198 | |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 199 | void |
| 200 | nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) |
| 201 | { |
| 202 | struct nouveau_ramht *ramht = chan->ramht; |
| 203 | unsigned long flags; |
| 204 | |
| 205 | spin_lock_irqsave(&ramht->lock, flags); |
| 206 | nouveau_ramht_remove_locked(chan, handle); |
| 207 | spin_unlock_irqrestore(&ramht->lock, flags); |
| 208 | } |
| 209 | |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 210 | struct nouveau_gpuobj * |
| 211 | nouveau_ramht_find(struct nouveau_channel *chan, u32 handle) |
| 212 | { |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 213 | struct nouveau_ramht *ramht = chan->ramht; |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 214 | struct nouveau_ramht_entry *entry; |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 215 | struct nouveau_gpuobj *gpuobj = NULL; |
| 216 | unsigned long flags; |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 217 | |
Ben Skeggs | 2941482 | 2010-09-03 10:25:02 +1000 | [diff] [blame] | 218 | if (unlikely(!chan->ramht)) |
| 219 | return NULL; |
| 220 | |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 221 | spin_lock_irqsave(&ramht->lock, flags); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 222 | list_for_each_entry(entry, &chan->ramht->entries, head) { |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 223 | if (entry->channel == chan && entry->handle == handle) { |
| 224 | gpuobj = entry->gpuobj; |
| 225 | break; |
| 226 | } |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 227 | } |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 228 | spin_unlock_irqrestore(&ramht->lock, flags); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 229 | |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 230 | return gpuobj; |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | int |
| 234 | nouveau_ramht_new(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, |
| 235 | struct nouveau_ramht **pramht) |
| 236 | { |
| 237 | struct nouveau_ramht *ramht; |
| 238 | |
| 239 | ramht = kzalloc(sizeof(*ramht), GFP_KERNEL); |
| 240 | if (!ramht) |
| 241 | return -ENOMEM; |
| 242 | |
| 243 | ramht->dev = dev; |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 244 | kref_init(&ramht->refcount); |
Ben Skeggs | e05c5a3 | 2010-09-01 15:24:35 +1000 | [diff] [blame] | 245 | ramht->bits = drm_order(gpuobj->size / 8); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 246 | INIT_LIST_HEAD(&ramht->entries); |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 247 | spin_lock_init(&ramht->lock); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 248 | nouveau_gpuobj_ref(gpuobj, &ramht->gpuobj); |
| 249 | |
| 250 | *pramht = ramht; |
| 251 | return 0; |
| 252 | } |
| 253 | |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 254 | static void |
| 255 | nouveau_ramht_del(struct kref *ref) |
| 256 | { |
| 257 | struct nouveau_ramht *ramht = |
| 258 | container_of(ref, struct nouveau_ramht, refcount); |
| 259 | |
| 260 | nouveau_gpuobj_ref(NULL, &ramht->gpuobj); |
| 261 | kfree(ramht); |
| 262 | } |
| 263 | |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 264 | void |
| 265 | nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr, |
| 266 | struct nouveau_channel *chan) |
| 267 | { |
| 268 | struct nouveau_ramht_entry *entry, *tmp; |
| 269 | struct nouveau_ramht *ramht; |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 270 | unsigned long flags; |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 271 | |
| 272 | if (ref) |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 273 | kref_get(&ref->refcount); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 274 | |
| 275 | ramht = *ptr; |
| 276 | if (ramht) { |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 277 | spin_lock_irqsave(&ramht->lock, flags); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 278 | list_for_each_entry_safe(entry, tmp, &ramht->entries, head) { |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 279 | if (entry->channel != chan) |
| 280 | continue; |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 281 | |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 282 | nouveau_ramht_remove_locked(chan, entry->handle); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 283 | } |
Ben Skeggs | dac7900 | 2010-09-01 15:24:36 +1000 | [diff] [blame] | 284 | spin_unlock_irqrestore(&ramht->lock, flags); |
| 285 | |
| 286 | kref_put(&ramht->refcount, nouveau_ramht_del); |
Ben Skeggs | a8eaebc | 2010-09-01 15:24:31 +1000 | [diff] [blame] | 287 | } |
| 288 | *ptr = ref; |
Ben Skeggs | 479dcae | 2010-09-01 15:24:28 +1000 | [diff] [blame] | 289 | } |