Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /**************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Permission is hereby granted, free of charge, to any person obtaining a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * copy of this software and associated documentation files (the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * "Software"), to deal in the Software without restriction, including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * without limitation the rights to use, copy, modify, merge, publish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * distribute, sub license, and/or sell copies of the Software, and to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * permit persons to whom the Software is furnished to do so, subject to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * the following conditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * The above copyright notice and this permission notice (including the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * next paragraph) shall be included in all copies or substantial portions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * of the Software.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * USE OR OTHER DEALINGS IN THE SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  **************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * Simple open hash tab implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include <linux/hash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include <linux/rculist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #include <drm/drm_hashtab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #include <drm/drm_print.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	unsigned int size = 1 << order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	ht->order = order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	ht->table = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	if (size <= PAGE_SIZE / sizeof(*ht->table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		ht->table = vzalloc(array_size(size, sizeof(*ht->table)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	if (!ht->table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		DRM_ERROR("Out of memory for hash table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) EXPORT_SYMBOL(drm_ht_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	struct drm_hash_item *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	struct hlist_head *h_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	unsigned int hashed_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	hashed_key = hash_long(key, ht->order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	h_list = &ht->table[hashed_key];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	hlist_for_each_entry(entry, h_list, head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 					  unsigned long key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	struct drm_hash_item *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	struct hlist_head *h_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	unsigned int hashed_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	hashed_key = hash_long(key, ht->order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	h_list = &ht->table[hashed_key];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	hlist_for_each_entry(entry, h_list, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		if (entry->key == key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			return &entry->head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		if (entry->key > key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static struct hlist_node *drm_ht_find_key_rcu(struct drm_open_hash *ht,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 					      unsigned long key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	struct drm_hash_item *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	struct hlist_head *h_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	unsigned int hashed_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	hashed_key = hash_long(key, ht->order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	h_list = &ht->table[hashed_key];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	hlist_for_each_entry_rcu(entry, h_list, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		if (entry->key == key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			return &entry->head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		if (entry->key > key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	struct drm_hash_item *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	struct hlist_head *h_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	struct hlist_node *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	unsigned int hashed_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	unsigned long key = item->key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	hashed_key = hash_long(key, ht->order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	h_list = &ht->table[hashed_key];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	hlist_for_each_entry(entry, h_list, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		if (entry->key == key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		if (entry->key > key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		parent = &entry->head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	if (parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		hlist_add_behind_rcu(&item->head, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		hlist_add_head_rcu(&item->head, h_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) EXPORT_SYMBOL(drm_ht_insert_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  * Just insert an item and return any "bits" bit key that hasn't been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * used before.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			      unsigned long seed, int bits, int shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			      unsigned long add)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	unsigned long mask = (1UL << bits) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	unsigned long first, unshifted_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	unshifted_key = hash_long(seed, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	first = unshifted_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		item->key = (unshifted_key << shift) + add;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		ret = drm_ht_insert_item(ht, item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			unshifted_key = (unshifted_key + 1) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	} while(ret && (unshifted_key != first));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		DRM_ERROR("Available key bit space exhausted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) EXPORT_SYMBOL(drm_ht_just_insert_please);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		     struct drm_hash_item **item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	struct hlist_node *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	list = drm_ht_find_key_rcu(ht, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (!list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	*item = hlist_entry(list, struct drm_hash_item, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) EXPORT_SYMBOL(drm_ht_find_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	struct hlist_node *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	list = drm_ht_find_key(ht, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		hlist_del_init_rcu(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	hlist_del_init_rcu(&item->head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) EXPORT_SYMBOL(drm_ht_remove_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) void drm_ht_remove(struct drm_open_hash *ht)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (ht->table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		kvfree(ht->table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		ht->table = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) EXPORT_SYMBOL(drm_ht_remove);