1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2006-2020 B.A.T.M.A.N. contributors: 3 * 4 * Simon Wunderlich, Marek Lindner 5 */ 6 7 #include "hash.h" 8 #include "main.h" 9 10 #include <linux/gfp.h> 11 #include <linux/lockdep.h> 12 #include <linux/slab.h> 13 14 /* clears the hash */ 15 static void batadv_hash_init(struct batadv_hashtable *hash) 16 { 17 u32 i; 18 19 for (i = 0; i < hash->size; i++) { 20 INIT_HLIST_HEAD(&hash->table[i]); 21 spin_lock_init(&hash->list_locks[i]); 22 } 23 24 atomic_set(&hash->generation, 0); 25 } 26 27 /** 28 * batadv_hash_destroy() - Free only the hashtable and the hash itself 29 * @hash: hash object to destroy 30 */ 31 void batadv_hash_destroy(struct batadv_hashtable *hash) 32 { 33 kfree(hash->list_locks); 34 kfree(hash->table); 35 kfree(hash); 36 } 37 38 /** 39 * batadv_hash_new() - Allocates and clears the hashtable 40 * @size: number of hash buckets to allocate 41 * 42 * Return: newly allocated hashtable, NULL on errors 43 */ 44 struct batadv_hashtable *batadv_hash_new(u32 size) 45 { 46 struct batadv_hashtable *hash; 47 48 hash = kmalloc(sizeof(*hash), GFP_ATOMIC); 49 if (!hash) 50 return NULL; 51 52 hash->table = kmalloc_array(size, sizeof(*hash->table), GFP_ATOMIC); 53 if (!hash->table) 54 goto free_hash; 55 56 hash->list_locks = kmalloc_array(size, sizeof(*hash->list_locks), 57 GFP_ATOMIC); 58 if (!hash->list_locks) 59 goto free_table; 60 61 hash->size = size; 62 batadv_hash_init(hash); 63 return hash; 64 65 free_table: 66 kfree(hash->table); 67 free_hash: 68 kfree(hash); 69 return NULL; 70 } 71 72 /** 73 * batadv_hash_set_lock_class() - Set specific lockdep class for hash spinlocks 74 * @hash: hash object to modify 75 * @key: lockdep class key address 76 */ 77 void batadv_hash_set_lock_class(struct batadv_hashtable *hash, 78 struct lock_class_key *key) 79 { 80 u32 i; 81 82 for (i = 0; i < hash->size; i++) 83 lockdep_set_class(&hash->list_locks[i], key); 84 } 85