18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/export.h> 38c2ecf20Sopenharmony_ci#include <linux/bug.h> 48c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci/** 78c2ecf20Sopenharmony_ci * memweight - count the total number of bits set in memory area 88c2ecf20Sopenharmony_ci * @ptr: pointer to the start of the area 98c2ecf20Sopenharmony_ci * @bytes: the size of the area 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_cisize_t memweight(const void *ptr, size_t bytes) 128c2ecf20Sopenharmony_ci{ 138c2ecf20Sopenharmony_ci size_t ret = 0; 148c2ecf20Sopenharmony_ci size_t longs; 158c2ecf20Sopenharmony_ci const unsigned char *bitmap = ptr; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci for (; bytes > 0 && ((unsigned long)bitmap) % sizeof(long); 188c2ecf20Sopenharmony_ci bytes--, bitmap++) 198c2ecf20Sopenharmony_ci ret += hweight8(*bitmap); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci longs = bytes / sizeof(long); 228c2ecf20Sopenharmony_ci if (longs) { 238c2ecf20Sopenharmony_ci BUG_ON(longs >= INT_MAX / BITS_PER_LONG); 248c2ecf20Sopenharmony_ci ret += bitmap_weight((unsigned long *)bitmap, 258c2ecf20Sopenharmony_ci longs * BITS_PER_LONG); 268c2ecf20Sopenharmony_ci bytes -= longs * sizeof(long); 278c2ecf20Sopenharmony_ci bitmap += longs * sizeof(long); 288c2ecf20Sopenharmony_ci } 298c2ecf20Sopenharmony_ci /* 308c2ecf20Sopenharmony_ci * The reason that this last loop is distinct from the preceding 318c2ecf20Sopenharmony_ci * bitmap_weight() call is to compute 1-bits in the last region smaller 328c2ecf20Sopenharmony_ci * than sizeof(long) properly on big-endian systems. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci for (; bytes > 0; bytes--, bitmap++) 358c2ecf20Sopenharmony_ci ret += hweight8(*bitmap); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci return ret; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(memweight); 40