Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/vmwgfx: Copy DRM hash-table code into driver

Besides some legacy code, vmwgfx is the only user of DRM's hash-
table implementation. Copy the code into the driver, so that the
core code can be retired.

No functional changes. However, the real solution for vmwgfx is to
use Linux' generic hash-table functions.

v2:
* add TODO item for updating vmwgfx (Sam)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211129094841.22499-3-tzimmermann@suse.de

+353 -60
+11
Documentation/gpu/todo.rst
··· 646 646 647 647 Contact: Harry Wentland, Alex Deucher 648 648 649 + vmwgfx: Replace hashtable with Linux' implementation 650 + ---------------------------------------------------- 651 + 652 + The vmwgfx driver uses its own hashtable implementation. Replace the 653 + code with Linux' implementation and update the callers. It's mostly a 654 + refactoring task, but the interfaces are different. 655 + 656 + Contact: Zack Rusin, Thomas Zimmermann <tzimmermann@suse.de> 657 + 658 + Level: Intermediate 659 + 649 660 Bootsplash 650 661 ========== 651 662
+1 -1
drivers/gpu/drm/vmwgfx/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ 2 + vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_hashtab.o vmwgfx_kms.o vmwgfx_drv.o \ 3 3 vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \ 4 4 vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ 5 5 vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \
+26 -26
drivers/gpu/drm/vmwgfx/ttm_object.c
··· 73 73 struct ttm_object_device *tdev; 74 74 spinlock_t lock; 75 75 struct list_head ref_list; 76 - struct drm_open_hash ref_hash[TTM_REF_NUM]; 76 + struct vmwgfx_open_hash ref_hash[TTM_REF_NUM]; 77 77 struct kref refcount; 78 78 }; 79 79 ··· 91 91 92 92 struct ttm_object_device { 93 93 spinlock_t object_lock; 94 - struct drm_open_hash object_hash; 94 + struct vmwgfx_open_hash object_hash; 95 95 atomic_t object_count; 96 96 struct ttm_mem_global *mem_glob; 97 97 struct dma_buf_ops ops; ··· 123 123 124 124 struct ttm_ref_object { 125 125 struct rcu_head rcu_head; 126 - struct drm_hash_item hash; 126 + struct vmwgfx_hash_item hash; 127 127 struct list_head head; 128 128 struct kref kref; 129 129 enum ttm_ref_type ref_type; ··· 247 247 struct ttm_base_object * 248 248 ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key) 249 249 { 250 - struct drm_hash_item *hash; 251 - struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; 250 + struct vmwgfx_hash_item *hash; 251 + struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; 252 252 int ret; 253 253 254 254 rcu_read_lock(); 255 - ret = drm_ht_find_item_rcu(ht, key, &hash); 255 + ret = vmwgfx_ht_find_item_rcu(ht, key, &hash); 256 256 if (ret) { 257 257 rcu_read_unlock(); 258 258 return NULL; ··· 267 267 uint32_t key) 268 268 { 269 269 struct ttm_base_object *base = NULL; 270 - struct drm_hash_item *hash; 271 - struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; 270 + struct vmwgfx_hash_item *hash; 271 + struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; 272 272 int ret; 273 273 274 274 rcu_read_lock(); 275 - ret = drm_ht_find_item_rcu(ht, key, &hash); 275 + ret = vmwgfx_ht_find_item_rcu(ht, key, &hash); 276 276 277 277 if (likely(ret == 0)) { 278 278 base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj; ··· 312 312 bool ttm_ref_object_exists(struct ttm_object_file *tfile, 313 313 struct ttm_base_object *base) 314 314 { 315 - struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; 316 - struct drm_hash_item *hash; 315 + struct vmwgfx_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; 316 + struct vmwgfx_hash_item *hash; 317 317 struct ttm_ref_object *ref; 318 318 319 319 rcu_read_lock(); 320 - if (unlikely(drm_ht_find_item_rcu(ht, base->handle, &hash) != 0)) 320 + if (unlikely(vmwgfx_ht_find_item_rcu(ht, base->handle, &hash) != 0)) 321 321 goto out_false; 322 322 323 323 /* ··· 349 349 enum ttm_ref_type ref_type, bool *existed, 350 350 bool require_existed) 351 351 { 352 - struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; 352 + struct vmwgfx_open_hash *ht = &tfile->ref_hash[ref_type]; 353 353 struct ttm_ref_object *ref; 354 - struct drm_hash_item *hash; 354 + struct vmwgfx_hash_item *hash; 355 355 struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; 356 356 struct ttm_operation_ctx ctx = { 357 357 .interruptible = false, ··· 367 367 368 368 while (ret == -EINVAL) { 369 369 rcu_read_lock(); 370 - ret = drm_ht_find_item_rcu(ht, base->handle, &hash); 370 + ret = vmwgfx_ht_find_item_rcu(ht, base->handle, &hash); 371 371 372 372 if (ret == 0) { 373 373 ref = drm_hash_entry(hash, struct ttm_ref_object, hash); ··· 398 398 kref_init(&ref->kref); 399 399 400 400 spin_lock(&tfile->lock); 401 - ret = drm_ht_insert_item_rcu(ht, &ref->hash); 401 + ret = vmwgfx_ht_insert_item_rcu(ht, &ref->hash); 402 402 403 403 if (likely(ret == 0)) { 404 404 list_add_tail(&ref->head, &tfile->ref_list); ··· 426 426 container_of(kref, struct ttm_ref_object, kref); 427 427 struct ttm_base_object *base = ref->obj; 428 428 struct ttm_object_file *tfile = ref->tfile; 429 - struct drm_open_hash *ht; 429 + struct vmwgfx_open_hash *ht; 430 430 struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; 431 431 432 432 ht = &tfile->ref_hash[ref->ref_type]; 433 - (void)drm_ht_remove_item_rcu(ht, &ref->hash); 433 + (void)vmwgfx_ht_remove_item_rcu(ht, &ref->hash); 434 434 list_del(&ref->head); 435 435 spin_unlock(&tfile->lock); 436 436 ··· 446 446 int ttm_ref_object_base_unref(struct ttm_object_file *tfile, 447 447 unsigned long key, enum ttm_ref_type ref_type) 448 448 { 449 - struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; 449 + struct vmwgfx_open_hash *ht = &tfile->ref_hash[ref_type]; 450 450 struct ttm_ref_object *ref; 451 - struct drm_hash_item *hash; 451 + struct vmwgfx_hash_item *hash; 452 452 int ret; 453 453 454 454 spin_lock(&tfile->lock); 455 - ret = drm_ht_find_item(ht, key, &hash); 455 + ret = vmwgfx_ht_find_item(ht, key, &hash); 456 456 if (unlikely(ret != 0)) { 457 457 spin_unlock(&tfile->lock); 458 458 return -EINVAL; ··· 486 486 487 487 spin_unlock(&tfile->lock); 488 488 for (i = 0; i < TTM_REF_NUM; ++i) 489 - drm_ht_remove(&tfile->ref_hash[i]); 489 + vmwgfx_ht_remove(&tfile->ref_hash[i]); 490 490 491 491 ttm_object_file_unref(&tfile); 492 492 } ··· 508 508 INIT_LIST_HEAD(&tfile->ref_list); 509 509 510 510 for (i = 0; i < TTM_REF_NUM; ++i) { 511 - ret = drm_ht_create(&tfile->ref_hash[i], hash_order); 511 + ret = vmwgfx_ht_create(&tfile->ref_hash[i], hash_order); 512 512 if (ret) { 513 513 j = i; 514 514 goto out_err; ··· 518 518 return tfile; 519 519 out_err: 520 520 for (i = 0; i < j; ++i) 521 - drm_ht_remove(&tfile->ref_hash[i]); 521 + vmwgfx_ht_remove(&tfile->ref_hash[i]); 522 522 523 523 kfree(tfile); 524 524 ··· 539 539 tdev->mem_glob = mem_glob; 540 540 spin_lock_init(&tdev->object_lock); 541 541 atomic_set(&tdev->object_count, 0); 542 - ret = drm_ht_create(&tdev->object_hash, hash_order); 542 + ret = vmwgfx_ht_create(&tdev->object_hash, hash_order); 543 543 if (ret != 0) 544 544 goto out_no_object_hash; 545 545 ··· 564 564 565 565 WARN_ON_ONCE(!idr_is_empty(&tdev->idr)); 566 566 idr_destroy(&tdev->idr); 567 - drm_ht_remove(&tdev->object_hash); 567 + vmwgfx_ht_remove(&tdev->object_hash); 568 568 569 569 kfree(tdev); 570 570 }
+1 -2
drivers/gpu/drm/vmwgfx/ttm_object.h
··· 42 42 #include <linux/list.h> 43 43 #include <linux/rcupdate.h> 44 44 45 - #include <drm/drm_hashtab.h> 46 - 47 45 #include "ttm_memory.h" 46 + #include "vmwgfx_hashtab.h" 48 47 49 48 /** 50 49 * enum ttm_ref_type
+12 -12
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
··· 42 42 */ 43 43 struct vmw_cmdbuf_res { 44 44 struct vmw_resource *res; 45 - struct drm_hash_item hash; 45 + struct vmwgfx_hash_item hash; 46 46 struct list_head head; 47 47 enum vmw_cmdbuf_res_state state; 48 48 struct vmw_cmdbuf_res_manager *man; ··· 59 59 * @resources and @list are protected by the cmdbuf mutex for now. 60 60 */ 61 61 struct vmw_cmdbuf_res_manager { 62 - struct drm_open_hash resources; 62 + struct vmwgfx_open_hash resources; 63 63 struct list_head list; 64 64 struct vmw_private *dev_priv; 65 65 }; ··· 81 81 enum vmw_cmdbuf_res_type res_type, 82 82 u32 user_key) 83 83 { 84 - struct drm_hash_item *hash; 84 + struct vmwgfx_hash_item *hash; 85 85 int ret; 86 86 unsigned long key = user_key | (res_type << 24); 87 87 88 - ret = drm_ht_find_item(&man->resources, key, &hash); 88 + ret = vmwgfx_ht_find_item(&man->resources, key, &hash); 89 89 if (unlikely(ret != 0)) 90 90 return ERR_PTR(ret); 91 91 ··· 105 105 struct vmw_cmdbuf_res *entry) 106 106 { 107 107 list_del(&entry->head); 108 - WARN_ON(drm_ht_remove_item(&man->resources, &entry->hash)); 108 + WARN_ON(vmwgfx_ht_remove_item(&man->resources, &entry->hash)); 109 109 vmw_resource_unreference(&entry->res); 110 110 kfree(entry); 111 111 } ··· 167 167 vmw_cmdbuf_res_free(entry->man, entry); 168 168 break; 169 169 case VMW_CMDBUF_RES_DEL: 170 - ret = drm_ht_insert_item(&entry->man->resources, &entry->hash); 170 + ret = vmwgfx_ht_insert_item(&entry->man->resources, &entry->hash); 171 171 BUG_ON(ret); 172 172 list_move_tail(&entry->head, &entry->man->list); 173 173 entry->state = VMW_CMDBUF_RES_COMMITTED; ··· 206 206 return -ENOMEM; 207 207 208 208 cres->hash.key = user_key | (res_type << 24); 209 - ret = drm_ht_insert_item(&man->resources, &cres->hash); 209 + ret = vmwgfx_ht_insert_item(&man->resources, &cres->hash); 210 210 if (unlikely(ret != 0)) { 211 211 kfree(cres); 212 212 goto out_invalid_key; ··· 244 244 struct vmw_resource **res_p) 245 245 { 246 246 struct vmw_cmdbuf_res *entry; 247 - struct drm_hash_item *hash; 247 + struct vmwgfx_hash_item *hash; 248 248 int ret; 249 249 250 - ret = drm_ht_find_item(&man->resources, user_key | (res_type << 24), 250 + ret = vmwgfx_ht_find_item(&man->resources, user_key | (res_type << 24), 251 251 &hash); 252 252 if (likely(ret != 0)) 253 253 return -EINVAL; ··· 260 260 *res_p = NULL; 261 261 break; 262 262 case VMW_CMDBUF_RES_COMMITTED: 263 - (void) drm_ht_remove_item(&man->resources, &entry->hash); 263 + (void) vmwgfx_ht_remove_item(&man->resources, &entry->hash); 264 264 list_del(&entry->head); 265 265 entry->state = VMW_CMDBUF_RES_DEL; 266 266 list_add_tail(&entry->head, list); ··· 295 295 296 296 man->dev_priv = dev_priv; 297 297 INIT_LIST_HEAD(&man->list); 298 - ret = drm_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER); 298 + ret = vmwgfx_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER); 299 299 if (ret == 0) 300 300 return man; 301 301 ··· 320 320 list_for_each_entry_safe(entry, next, &man->list, head) 321 321 vmw_cmdbuf_res_free(man, entry); 322 322 323 - drm_ht_remove(&man->resources); 323 + vmwgfx_ht_remove(&man->resources); 324 324 kfree(man); 325 325 } 326 326
+1 -1
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
··· 1155 1155 unregister_pm_notifier(&dev_priv->pm_nb); 1156 1156 1157 1157 if (dev_priv->ctx.res_ht_initialized) 1158 - drm_ht_remove(&dev_priv->ctx.res_ht); 1158 + vmwgfx_ht_remove(&dev_priv->ctx.res_ht); 1159 1159 vfree(dev_priv->ctx.cmd_bounce); 1160 1160 if (dev_priv->enable_fb) { 1161 1161 vmw_fb_off(dev_priv);
+3 -3
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
··· 34 34 #include <drm/drm_auth.h> 35 35 #include <drm/drm_device.h> 36 36 #include <drm/drm_file.h> 37 - #include <drm/drm_hashtab.h> 38 37 #include <drm/drm_rect.h> 39 38 40 39 #include <drm/ttm/ttm_bo_driver.h> ··· 42 43 #include "ttm_object.h" 43 44 44 45 #include "vmwgfx_fence.h" 46 + #include "vmwgfx_hashtab.h" 45 47 #include "vmwgfx_reg.h" 46 48 #include "vmwgfx_validation.h" 47 49 ··· 133 133 */ 134 134 struct vmw_validate_buffer { 135 135 struct ttm_validate_buffer base; 136 - struct drm_hash_item hash; 136 + struct vmwgfx_hash_item hash; 137 137 bool validate_as_mob; 138 138 }; 139 139 ··· 406 406 * @ctx: The validation context 407 407 */ 408 408 struct vmw_sw_context{ 409 - struct drm_open_hash res_ht; 409 + struct vmwgfx_open_hash res_ht; 410 410 bool res_ht_initialized; 411 411 bool kernel; 412 412 struct vmw_fpriv *fp;
+1 -1
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
··· 4117 4117 vmw_binding_state_reset(sw_context->staged_bindings); 4118 4118 4119 4119 if (!sw_context->res_ht_initialized) { 4120 - ret = drm_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER); 4120 + ret = vmwgfx_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER); 4121 4121 if (unlikely(ret != 0)) 4122 4122 goto out_unlock; 4123 4123
+199
drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c
··· 1 + /* 2 + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. 3 + * All Rights Reserved. 4 + * 5 + * Permission is hereby granted, free of charge, to any person obtaining a 6 + * copy of this software and associated documentation files (the 7 + * "Software"), to deal in the Software without restriction, including 8 + * without limitation the rights to use, copy, modify, merge, publish, 9 + * distribute, sub license, and/or sell copies of the Software, and to 10 + * permit persons to whom the Software is furnished to do so, subject to 11 + * the following conditions: 12 + * 13 + * The above copyright notice and this permission notice (including the 14 + * next paragraph) shall be included in all copies or substantial portions 15 + * of the Software. 16 + * 17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20 + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21 + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 + * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 + */ 25 + 26 + /* 27 + * Simple open hash tab implementation. 28 + * 29 + * Authors: 30 + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> 31 + */ 32 + 33 + #include <linux/export.h> 34 + #include <linux/hash.h> 35 + #include <linux/mm.h> 36 + #include <linux/rculist.h> 37 + #include <linux/slab.h> 38 + #include <linux/vmalloc.h> 39 + 40 + #include <drm/drm_print.h> 41 + 42 + #include "vmwgfx_hashtab.h" 43 + 44 + int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order) 45 + { 46 + unsigned int size = 1 << order; 47 + 48 + ht->order = order; 49 + ht->table = NULL; 50 + if (size <= PAGE_SIZE / sizeof(*ht->table)) 51 + ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL); 52 + else 53 + ht->table = vzalloc(array_size(size, sizeof(*ht->table))); 54 + if (!ht->table) { 55 + DRM_ERROR("Out of memory for hash table\n"); 56 + return -ENOMEM; 57 + } 58 + return 0; 59 + } 60 + 61 + void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key) 62 + { 63 + struct vmwgfx_hash_item *entry; 64 + struct hlist_head *h_list; 65 + unsigned int hashed_key; 66 + int count = 0; 67 + 68 + hashed_key = hash_long(key, ht->order); 69 + DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key); 70 + h_list = &ht->table[hashed_key]; 71 + hlist_for_each_entry(entry, h_list, head) 72 + DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key); 73 + } 74 + 75 + static struct hlist_node *vmwgfx_ht_find_key(struct vmwgfx_open_hash *ht, unsigned long key) 76 + { 77 + struct vmwgfx_hash_item *entry; 78 + struct hlist_head *h_list; 79 + unsigned int hashed_key; 80 + 81 + hashed_key = hash_long(key, ht->order); 82 + h_list = &ht->table[hashed_key]; 83 + hlist_for_each_entry(entry, h_list, head) { 84 + if (entry->key == key) 85 + return &entry->head; 86 + if (entry->key > key) 87 + break; 88 + } 89 + return NULL; 90 + } 91 + 92 + static struct hlist_node *vmwgfx_ht_find_key_rcu(struct vmwgfx_open_hash *ht, unsigned long key) 93 + { 94 + struct vmwgfx_hash_item *entry; 95 + struct hlist_head *h_list; 96 + unsigned int hashed_key; 97 + 98 + hashed_key = hash_long(key, ht->order); 99 + h_list = &ht->table[hashed_key]; 100 + hlist_for_each_entry_rcu(entry, h_list, head) { 101 + if (entry->key == key) 102 + return &entry->head; 103 + if (entry->key > key) 104 + break; 105 + } 106 + return NULL; 107 + } 108 + 109 + int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item) 110 + { 111 + struct vmwgfx_hash_item *entry; 112 + struct hlist_head *h_list; 113 + struct hlist_node *parent; 114 + unsigned int hashed_key; 115 + unsigned long key = item->key; 116 + 117 + hashed_key = hash_long(key, ht->order); 118 + h_list = &ht->table[hashed_key]; 119 + parent = NULL; 120 + hlist_for_each_entry(entry, h_list, head) { 121 + if (entry->key == key) 122 + return -EINVAL; 123 + if (entry->key > key) 124 + break; 125 + parent = &entry->head; 126 + } 127 + if (parent) 128 + hlist_add_behind_rcu(&item->head, parent); 129 + else 130 + hlist_add_head_rcu(&item->head, h_list); 131 + return 0; 132 + } 133 + 134 + /* 135 + * Just insert an item and return any "bits" bit key that hasn't been 136 + * used before. 137 + */ 138 + int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item, 139 + unsigned long seed, int bits, int shift, 140 + unsigned long add) 141 + { 142 + int ret; 143 + unsigned long mask = (1UL << bits) - 1; 144 + unsigned long first, unshifted_key; 145 + 146 + unshifted_key = hash_long(seed, bits); 147 + first = unshifted_key; 148 + do { 149 + item->key = (unshifted_key << shift) + add; 150 + ret = vmwgfx_ht_insert_item(ht, item); 151 + if (ret) 152 + unshifted_key = (unshifted_key + 1) & mask; 153 + } while (ret && (unshifted_key != first)); 154 + 155 + if (ret) { 156 + DRM_ERROR("Available key bit space exhausted\n"); 157 + return -EINVAL; 158 + } 159 + return 0; 160 + } 161 + 162 + int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key, 163 + struct vmwgfx_hash_item **item) 164 + { 165 + struct hlist_node *list; 166 + 167 + list = vmwgfx_ht_find_key_rcu(ht, key); 168 + if (!list) 169 + return -EINVAL; 170 + 171 + *item = hlist_entry(list, struct vmwgfx_hash_item, head); 172 + return 0; 173 + } 174 + 175 + int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key) 176 + { 177 + struct hlist_node *list; 178 + 179 + list = vmwgfx_ht_find_key(ht, key); 180 + if (list) { 181 + hlist_del_init_rcu(list); 182 + return 0; 183 + } 184 + return -EINVAL; 185 + } 186 + 187 + int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item) 188 + { 189 + hlist_del_init_rcu(&item->head); 190 + return 0; 191 + } 192 + 193 + void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht) 194 + { 195 + if (ht->table) { 196 + kvfree(ht->table); 197 + ht->table = NULL; 198 + } 199 + }
+83
drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h
··· 1 + /* 2 + * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA. 3 + * All Rights Reserved. 4 + * 5 + * Permission is hereby granted, free of charge, to any person obtaining a 6 + * copy of this software and associated documentation files (the 7 + * "Software"), to deal in the Software without restriction, including 8 + * without limitation the rights to use, copy, modify, merge, publish, 9 + * distribute, sub license, and/or sell copies of the Software, and to 10 + * permit persons to whom the Software is furnished to do so, subject to 11 + * the following conditions: 12 + * 13 + * The above copyright notice and this permission notice (including the 14 + * next paragraph) shall be included in all copies or substantial portions 15 + * of the Software. 16 + * 17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20 + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21 + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 + * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 + */ 25 + 26 + /* 27 + * Simple open hash tab implementation. 28 + * 29 + * Authors: 30 + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> 31 + */ 32 + 33 + /* 34 + * TODO: Replace this hashtable with Linux' generic implementation 35 + * from <linux/hashtable.h>. 36 + */ 37 + 38 + #ifndef VMWGFX_HASHTAB_H 39 + #define VMWGFX_HASHTAB_H 40 + 41 + #include <linux/list.h> 42 + 43 + #define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) 44 + 45 + struct vmwgfx_hash_item { 46 + struct hlist_node head; 47 + unsigned long key; 48 + }; 49 + 50 + struct vmwgfx_open_hash { 51 + struct hlist_head *table; 52 + u8 order; 53 + }; 54 + 55 + int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order); 56 + int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item); 57 + int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item, 58 + unsigned long seed, int bits, int shift, 59 + unsigned long add); 60 + int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key, 61 + struct vmwgfx_hash_item **item); 62 + 63 + void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key); 64 + int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key); 65 + int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item); 66 + void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht); 67 + 68 + /* 69 + * RCU-safe interface 70 + * 71 + * The user of this API needs to make sure that two or more instances of the 72 + * hash table manipulation functions are never run simultaneously. 73 + * The lookup function vmwgfx_ht_find_item_rcu may, however, run simultaneously 74 + * with any of the manipulation functions as long as it's called from within 75 + * an RCU read-locked section. 76 + */ 77 + #define vmwgfx_ht_insert_item_rcu vmwgfx_ht_insert_item 78 + #define vmwgfx_ht_just_insert_please_rcu vmwgfx_ht_just_insert_please 79 + #define vmwgfx_ht_remove_key_rcu vmwgfx_ht_remove_key 80 + #define vmwgfx_ht_remove_item_rcu vmwgfx_ht_remove_item 81 + #define vmwgfx_ht_find_item_rcu vmwgfx_ht_find_item 82 + 83 + #endif
+11 -11
drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
··· 43 43 */ 44 44 struct vmw_validation_bo_node { 45 45 struct ttm_validate_buffer base; 46 - struct drm_hash_item hash; 46 + struct vmwgfx_hash_item hash; 47 47 unsigned int coherent_count; 48 48 u32 as_mob : 1; 49 49 u32 cpu_blit : 1; ··· 72 72 */ 73 73 struct vmw_validation_res_node { 74 74 struct list_head head; 75 - struct drm_hash_item hash; 75 + struct vmwgfx_hash_item hash; 76 76 struct vmw_resource *res; 77 77 struct vmw_buffer_object *new_backup; 78 78 unsigned long new_backup_offset; ··· 184 184 return NULL; 185 185 186 186 if (ctx->ht) { 187 - struct drm_hash_item *hash; 187 + struct vmwgfx_hash_item *hash; 188 188 189 - if (!drm_ht_find_item(ctx->ht, (unsigned long) vbo, &hash)) 189 + if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) vbo, &hash)) 190 190 bo_node = container_of(hash, typeof(*bo_node), hash); 191 191 } else { 192 192 struct vmw_validation_bo_node *entry; ··· 221 221 return NULL; 222 222 223 223 if (ctx->ht) { 224 - struct drm_hash_item *hash; 224 + struct vmwgfx_hash_item *hash; 225 225 226 - if (!drm_ht_find_item(ctx->ht, (unsigned long) res, &hash)) 226 + if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) res, &hash)) 227 227 res_node = container_of(hash, typeof(*res_node), hash); 228 228 } else { 229 229 struct vmw_validation_res_node *entry; ··· 280 280 281 281 if (ctx->ht) { 282 282 bo_node->hash.key = (unsigned long) vbo; 283 - ret = drm_ht_insert_item(ctx->ht, &bo_node->hash); 283 + ret = vmwgfx_ht_insert_item(ctx->ht, &bo_node->hash); 284 284 if (ret) { 285 285 DRM_ERROR("Failed to initialize a buffer " 286 286 "validation entry.\n"); ··· 335 335 336 336 if (ctx->ht) { 337 337 node->hash.key = (unsigned long) res; 338 - ret = drm_ht_insert_item(ctx->ht, &node->hash); 338 + ret = vmwgfx_ht_insert_item(ctx->ht, &node->hash); 339 339 if (ret) { 340 340 DRM_ERROR("Failed to initialize a resource validation " 341 341 "entry.\n"); ··· 688 688 return; 689 689 690 690 list_for_each_entry(entry, &ctx->bo_list, base.head) 691 - (void) drm_ht_remove_item(ctx->ht, &entry->hash); 691 + (void) vmwgfx_ht_remove_item(ctx->ht, &entry->hash); 692 692 693 693 list_for_each_entry(val, &ctx->resource_list, head) 694 - (void) drm_ht_remove_item(ctx->ht, &val->hash); 694 + (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash); 695 695 696 696 list_for_each_entry(val, &ctx->resource_ctx_list, head) 697 - (void) drm_ht_remove_item(ctx->ht, &val->hash); 697 + (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash); 698 698 699 699 ctx->ht = NULL; 700 700 }
+4 -3
drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
··· 31 31 #include <linux/list.h> 32 32 #include <linux/ww_mutex.h> 33 33 34 - #include <drm/drm_hashtab.h> 35 34 #include <drm/ttm/ttm_execbuf_util.h> 35 + 36 + #include "vmwgfx_hashtab.h" 36 37 37 38 #define VMW_RES_DIRTY_NONE 0 38 39 #define VMW_RES_DIRTY_SET BIT(0) ··· 74 73 * @total_mem: Amount of reserved memory. 75 74 */ 76 75 struct vmw_validation_context { 77 - struct drm_open_hash *ht; 76 + struct vmwgfx_open_hash *ht; 78 77 struct list_head resource_list; 79 78 struct list_head resource_ctx_list; 80 79 struct list_head bo_list; ··· 152 151 * available at validation context declaration time 153 152 */ 154 153 static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx, 155 - struct drm_open_hash *ht) 154 + struct vmwgfx_open_hash *ht) 156 155 { 157 156 ctx->ht = ht; 158 157 }