162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (C) B.A.T.M.A.N. contributors: 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Simon Wunderlich, Marek Lindner 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include "hash.h" 862306a36Sopenharmony_ci#include "main.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/gfp.h> 1162306a36Sopenharmony_ci#include <linux/lockdep.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* clears the hash */ 1562306a36Sopenharmony_cistatic void batadv_hash_init(struct batadv_hashtable *hash) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci u32 i; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci for (i = 0; i < hash->size; i++) { 2062306a36Sopenharmony_ci INIT_HLIST_HEAD(&hash->table[i]); 2162306a36Sopenharmony_ci spin_lock_init(&hash->list_locks[i]); 2262306a36Sopenharmony_ci } 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci atomic_set(&hash->generation, 0); 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/** 2862306a36Sopenharmony_ci * batadv_hash_destroy() - Free only the hashtable and the hash itself 2962306a36Sopenharmony_ci * @hash: hash object to destroy 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_civoid batadv_hash_destroy(struct batadv_hashtable *hash) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci kfree(hash->list_locks); 3462306a36Sopenharmony_ci kfree(hash->table); 3562306a36Sopenharmony_ci kfree(hash); 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/** 3962306a36Sopenharmony_ci * batadv_hash_new() - Allocates and clears the hashtable 4062306a36Sopenharmony_ci * @size: number of hash buckets to allocate 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * Return: newly allocated hashtable, NULL on errors 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_cistruct batadv_hashtable *batadv_hash_new(u32 size) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci struct batadv_hashtable *hash; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci hash = kmalloc(sizeof(*hash), GFP_ATOMIC); 4962306a36Sopenharmony_ci if (!hash) 5062306a36Sopenharmony_ci return NULL; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci hash->table = kmalloc_array(size, sizeof(*hash->table), GFP_ATOMIC); 5362306a36Sopenharmony_ci if (!hash->table) 5462306a36Sopenharmony_ci goto free_hash; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci hash->list_locks = kmalloc_array(size, sizeof(*hash->list_locks), 5762306a36Sopenharmony_ci GFP_ATOMIC); 5862306a36Sopenharmony_ci if (!hash->list_locks) 5962306a36Sopenharmony_ci goto free_table; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci hash->size = size; 6262306a36Sopenharmony_ci batadv_hash_init(hash); 6362306a36Sopenharmony_ci return hash; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cifree_table: 6662306a36Sopenharmony_ci kfree(hash->table); 6762306a36Sopenharmony_cifree_hash: 6862306a36Sopenharmony_ci kfree(hash); 6962306a36Sopenharmony_ci return NULL; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/** 7362306a36Sopenharmony_ci * batadv_hash_set_lock_class() - Set specific lockdep class for hash spinlocks 7462306a36Sopenharmony_ci * @hash: hash object to modify 7562306a36Sopenharmony_ci * @key: lockdep class key address 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_civoid batadv_hash_set_lock_class(struct batadv_hashtable *hash, 7862306a36Sopenharmony_ci struct lock_class_key *key) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci u32 i; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci for (i = 0; i < hash->size; i++) 8362306a36Sopenharmony_ci lockdep_set_class(&hash->list_locks[i], key); 8462306a36Sopenharmony_ci} 85