18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (C) 2006-2020 B.A.T.M.A.N. contributors: 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Simon Wunderlich, Marek Lindner 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include "hash.h" 88c2ecf20Sopenharmony_ci#include "main.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/gfp.h> 118c2ecf20Sopenharmony_ci#include <linux/lockdep.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* clears the hash */ 158c2ecf20Sopenharmony_cistatic void batadv_hash_init(struct batadv_hashtable *hash) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci u32 i; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci for (i = 0; i < hash->size; i++) { 208c2ecf20Sopenharmony_ci INIT_HLIST_HEAD(&hash->table[i]); 218c2ecf20Sopenharmony_ci spin_lock_init(&hash->list_locks[i]); 228c2ecf20Sopenharmony_ci } 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci atomic_set(&hash->generation, 0); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/** 288c2ecf20Sopenharmony_ci * batadv_hash_destroy() - Free only the hashtable and the hash itself 298c2ecf20Sopenharmony_ci * @hash: hash object to destroy 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_civoid batadv_hash_destroy(struct batadv_hashtable *hash) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci kfree(hash->list_locks); 348c2ecf20Sopenharmony_ci kfree(hash->table); 358c2ecf20Sopenharmony_ci kfree(hash); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/** 398c2ecf20Sopenharmony_ci * batadv_hash_new() - Allocates and clears the hashtable 408c2ecf20Sopenharmony_ci * @size: number of hash buckets to allocate 418c2ecf20Sopenharmony_ci * 428c2ecf20Sopenharmony_ci * Return: newly allocated hashtable, NULL on errors 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_cistruct batadv_hashtable *batadv_hash_new(u32 size) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci struct batadv_hashtable *hash; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci hash = kmalloc(sizeof(*hash), GFP_ATOMIC); 498c2ecf20Sopenharmony_ci if (!hash) 508c2ecf20Sopenharmony_ci return NULL; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci hash->table = kmalloc_array(size, sizeof(*hash->table), GFP_ATOMIC); 538c2ecf20Sopenharmony_ci if (!hash->table) 548c2ecf20Sopenharmony_ci goto free_hash; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci hash->list_locks = kmalloc_array(size, sizeof(*hash->list_locks), 578c2ecf20Sopenharmony_ci GFP_ATOMIC); 588c2ecf20Sopenharmony_ci if (!hash->list_locks) 598c2ecf20Sopenharmony_ci goto free_table; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci hash->size = size; 628c2ecf20Sopenharmony_ci batadv_hash_init(hash); 638c2ecf20Sopenharmony_ci return hash; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cifree_table: 668c2ecf20Sopenharmony_ci kfree(hash->table); 678c2ecf20Sopenharmony_cifree_hash: 688c2ecf20Sopenharmony_ci kfree(hash); 698c2ecf20Sopenharmony_ci return NULL; 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/** 738c2ecf20Sopenharmony_ci * batadv_hash_set_lock_class() - Set specific lockdep class for hash spinlocks 748c2ecf20Sopenharmony_ci * @hash: hash object to modify 758c2ecf20Sopenharmony_ci * @key: lockdep class key address 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_civoid batadv_hash_set_lock_class(struct batadv_hashtable *hash, 788c2ecf20Sopenharmony_ci struct lock_class_key *key) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci u32 i; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci for (i = 0; i < hash->size; i++) 838c2ecf20Sopenharmony_ci lockdep_set_class(&hash->list_locks[i], key); 848c2ecf20Sopenharmony_ci} 85