Skip to content

Commit b7f4256

Browse files
Maaz Mombasawalakerneltoast
authored andcommitted
drm/vmwgfx: Refactor ttm reference object hashtable to use linux/hashtable.
This is part of an effort to move from the vmwgfx_open_hash hashtable to linux/hashtable implementation. Refactor the ref_hash hashtable, used for fast lookup of reference objects associated with a ttm file. This also exposed a problem related to inconsistently using 32-bit and 64-bit keys with this hashtable. The hash function used changes depending on the size of the type, and results are not consistent across numbers, for example, hash_32(329) = 329, but hash_long(329) = 328. This would cause the lookup to fail for objects already in the hashtable, since keys of different sizes were being passed during adding and lookup. This was not an issue before because vmwgfx_open_hash always used hash_long. Fix this by always using 64-bit keys for this hashtable, which means that hash_long is always used. Signed-off-by: Maaz Mombasawala <mombasawalam@vmware.com> Reviewed-by: Zack Rusin <zackr@vmware.com> Signed-off-by: Zack Rusin <zackr@vmware.com> Link: https://patchwork.freedesktop.org/patch/msgid/20221022040236.616490-11-zack@kde.org
1 parent 3053acb commit b7f4256

File tree

3 files changed

+56
-49
lines changed

3 files changed

+56
-49
lines changed

drivers/gpu/drm/vmwgfx/ttm_object.c

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@
4848
#include <linux/spinlock.h>
4949
#include <linux/slab.h>
5050
#include <linux/atomic.h>
51+
#include <linux/hashtable.h>
5152
#include "ttm_object.h"
5253
#include "vmwgfx_drv.h"
5354

55+
#define VMW_TTM_OBJECT_REF_HT_ORDER 10
56+
5457
/**
5558
* struct ttm_object_file
5659
*
@@ -71,7 +74,7 @@ struct ttm_object_file {
7174
struct ttm_object_device *tdev;
7275
spinlock_t lock;
7376
struct list_head ref_list;
74-
struct vmwgfx_open_hash ref_hash;
77+
DECLARE_HASHTABLE(ref_hash, VMW_TTM_OBJECT_REF_HT_ORDER);
7578
struct kref refcount;
7679
};
7780

@@ -135,6 +138,36 @@ ttm_object_file_ref(struct ttm_object_file *tfile)
135138
return tfile;
136139
}
137140

141+
static int ttm_tfile_find_ref_rcu(struct ttm_object_file *tfile,
142+
uint64_t key,
143+
struct vmwgfx_hash_item **p_hash)
144+
{
145+
struct vmwgfx_hash_item *hash;
146+
147+
hash_for_each_possible_rcu(tfile->ref_hash, hash, head, key) {
148+
if (hash->key == key) {
149+
*p_hash = hash;
150+
return 0;
151+
}
152+
}
153+
return -EINVAL;
154+
}
155+
156+
static int ttm_tfile_find_ref(struct ttm_object_file *tfile,
157+
uint64_t key,
158+
struct vmwgfx_hash_item **p_hash)
159+
{
160+
struct vmwgfx_hash_item *hash;
161+
162+
hash_for_each_possible(tfile->ref_hash, hash, head, key) {
163+
if (hash->key == key) {
164+
*p_hash = hash;
165+
return 0;
166+
}
167+
}
168+
return -EINVAL;
169+
}
170+
138171
static void ttm_object_file_destroy(struct kref *kref)
139172
{
140173
struct ttm_object_file *tfile =
@@ -237,14 +270,13 @@ void ttm_base_object_unref(struct ttm_base_object **p_base)
237270
* Return: A pointer to the object if successful or NULL otherwise.
238271
*/
239272
struct ttm_base_object *
240-
ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key)
273+
ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key)
241274
{
242275
struct vmwgfx_hash_item *hash;
243-
struct vmwgfx_open_hash *ht = &tfile->ref_hash;
244276
int ret;
245277

246278
rcu_read_lock();
247-
ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
279+
ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
248280
if (ret) {
249281
rcu_read_unlock();
250282
return NULL;
@@ -256,15 +288,14 @@ ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key)
256288
EXPORT_SYMBOL(ttm_base_object_noref_lookup);
257289

258290
struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
259-
uint32_t key)
291+
uint64_t key)
260292
{
261293
struct ttm_base_object *base = NULL;
262294
struct vmwgfx_hash_item *hash;
263-
struct vmwgfx_open_hash *ht = &tfile->ref_hash;
264295
int ret;
265296

266297
rcu_read_lock();
267-
ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
298+
ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
268299

269300
if (likely(ret == 0)) {
270301
base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
@@ -277,7 +308,7 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
277308
}
278309

279310
struct ttm_base_object *
280-
ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
311+
ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint64_t key)
281312
{
282313
struct ttm_base_object *base;
283314

@@ -296,7 +327,6 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
296327
bool *existed,
297328
bool require_existed)
298329
{
299-
struct vmwgfx_open_hash *ht = &tfile->ref_hash;
300330
struct ttm_ref_object *ref;
301331
struct vmwgfx_hash_item *hash;
302332
int ret = -EINVAL;
@@ -309,7 +339,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
309339

310340
while (ret == -EINVAL) {
311341
rcu_read_lock();
312-
ret = vmwgfx_ht_find_item_rcu(ht, base->handle, &hash);
342+
ret = ttm_tfile_find_ref_rcu(tfile, base->handle, &hash);
313343

314344
if (ret == 0) {
315345
ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
@@ -334,21 +364,14 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
334364
kref_init(&ref->kref);
335365

336366
spin_lock(&tfile->lock);
337-
ret = vmwgfx_ht_insert_item_rcu(ht, &ref->hash);
338-
339-
if (likely(ret == 0)) {
340-
list_add_tail(&ref->head, &tfile->ref_list);
341-
kref_get(&base->refcount);
342-
spin_unlock(&tfile->lock);
343-
if (existed != NULL)
344-
*existed = false;
345-
break;
346-
}
367+
hash_add_rcu(tfile->ref_hash, &ref->hash.head, ref->hash.key);
368+
ret = 0;
347369

370+
list_add_tail(&ref->head, &tfile->ref_list);
371+
kref_get(&base->refcount);
348372
spin_unlock(&tfile->lock);
349-
BUG_ON(ret != -EINVAL);
350-
351-
kfree(ref);
373+
if (existed != NULL)
374+
*existed = false;
352375
}
353376

354377
return ret;
@@ -360,10 +383,8 @@ ttm_ref_object_release(struct kref *kref)
360383
struct ttm_ref_object *ref =
361384
container_of(kref, struct ttm_ref_object, kref);
362385
struct ttm_object_file *tfile = ref->tfile;
363-
struct vmwgfx_open_hash *ht;
364386

365-
ht = &tfile->ref_hash;
366-
(void)vmwgfx_ht_remove_item_rcu(ht, &ref->hash);
387+
hash_del_rcu(&ref->hash.head);
367388
list_del(&ref->head);
368389
spin_unlock(&tfile->lock);
369390

@@ -375,13 +396,12 @@ ttm_ref_object_release(struct kref *kref)
375396
int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
376397
unsigned long key)
377398
{
378-
struct vmwgfx_open_hash *ht = &tfile->ref_hash;
379399
struct ttm_ref_object *ref;
380400
struct vmwgfx_hash_item *hash;
381401
int ret;
382402

383403
spin_lock(&tfile->lock);
384-
ret = vmwgfx_ht_find_item(ht, key, &hash);
404+
ret = ttm_tfile_find_ref(tfile, key, &hash);
385405
if (unlikely(ret != 0)) {
386406
spin_unlock(&tfile->lock);
387407
return -EINVAL;
@@ -413,16 +433,13 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)
413433
}
414434

415435
spin_unlock(&tfile->lock);
416-
vmwgfx_ht_remove(&tfile->ref_hash);
417436

418437
ttm_object_file_unref(&tfile);
419438
}
420439

421-
struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
422-
unsigned int hash_order)
440+
struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev)
423441
{
424442
struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
425-
int ret;
426443

427444
if (unlikely(tfile == NULL))
428445
return NULL;
@@ -432,17 +449,9 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
432449
kref_init(&tfile->refcount);
433450
INIT_LIST_HEAD(&tfile->ref_list);
434451

435-
ret = vmwgfx_ht_create(&tfile->ref_hash, hash_order);
436-
if (ret)
437-
goto out_err;
452+
hash_init(tfile->ref_hash);
438453

439454
return tfile;
440-
out_err:
441-
vmwgfx_ht_remove(&tfile->ref_hash);
442-
443-
kfree(tfile);
444-
445-
return NULL;
446455
}
447456

448457
struct ttm_object_device *

drivers/gpu/drm/vmwgfx/ttm_object.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ struct ttm_base_object {
104104
struct ttm_object_file *tfile;
105105
struct kref refcount;
106106
void (*refcount_release) (struct ttm_base_object **base);
107-
u32 handle;
107+
u64 handle;
108108
enum ttm_object_type object_type;
109109
u32 shareable;
110110
};
@@ -164,7 +164,7 @@ extern int ttm_base_object_init(struct ttm_object_file *tfile,
164164
*/
165165

166166
extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
167-
*tfile, uint32_t key);
167+
*tfile, uint64_t key);
168168

169169
/**
170170
* ttm_base_object_lookup_for_ref
@@ -178,7 +178,7 @@ extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
178178
*/
179179

180180
extern struct ttm_base_object *
181-
ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key);
181+
ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint64_t key);
182182

183183
/**
184184
* ttm_base_object_unref
@@ -237,14 +237,12 @@ extern int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
237237
* ttm_object_file_init - initialize a struct ttm_object file
238238
*
239239
* @tdev: A struct ttm_object device this file is initialized on.
240-
* @hash_order: Order of the hash table used to hold the reference objects.
241240
*
242241
* This is typically called by the file_ops::open function.
243242
*/
244243

245244
extern struct ttm_object_file *ttm_object_file_init(struct ttm_object_device
246-
*tdev,
247-
unsigned int hash_order);
245+
*tdev);
248246

249247
/**
250248
* ttm_object_file_release - release data held by a ttm_object_file
@@ -314,7 +312,7 @@ extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
314312
kfree_rcu(__obj, __prime.base.rhead)
315313

316314
struct ttm_base_object *
317-
ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key);
315+
ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key);
318316

319317
/**
320318
* ttm_base_object_noref_release - release a base object pointer looked up

drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1203,7 +1203,7 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv)
12031203
if (unlikely(!vmw_fp))
12041204
return ret;
12051205

1206-
vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10);
1206+
vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev);
12071207
if (unlikely(vmw_fp->tfile == NULL))
12081208
goto out_no_tfile;
12091209

0 commit comments

Comments
 (0)