162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci// Copyright (c) 2019 Facebook
362306a36Sopenharmony_ci#include <features.h>
462306a36Sopenharmony_ci
562306a36Sopenharmony_citypedef unsigned int u32;
662306a36Sopenharmony_ci
762306a36Sopenharmony_cistatic __always_inline u32 rol32(u32 word, unsigned int shift)
862306a36Sopenharmony_ci{
962306a36Sopenharmony_ci	return (word << shift) | (word >> ((-shift) & 31));
1062306a36Sopenharmony_ci}
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define __jhash_mix(a, b, c)			\
1362306a36Sopenharmony_ci{						\
1462306a36Sopenharmony_ci	a -= c;  a ^= rol32(c, 4);  c += b;	\
1562306a36Sopenharmony_ci	b -= a;  b ^= rol32(a, 6);  a += c;	\
1662306a36Sopenharmony_ci	c -= b;  c ^= rol32(b, 8);  b += a;	\
1762306a36Sopenharmony_ci	a -= c;  a ^= rol32(c, 16); c += b;	\
1862306a36Sopenharmony_ci	b -= a;  b ^= rol32(a, 19); a += c;	\
1962306a36Sopenharmony_ci	c -= b;  c ^= rol32(b, 4);  b += a;	\
2062306a36Sopenharmony_ci}
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define __jhash_final(a, b, c)			\
2362306a36Sopenharmony_ci{						\
2462306a36Sopenharmony_ci	c ^= b; c -= rol32(b, 14);		\
2562306a36Sopenharmony_ci	a ^= c; a -= rol32(c, 11);		\
2662306a36Sopenharmony_ci	b ^= a; b -= rol32(a, 25);		\
2762306a36Sopenharmony_ci	c ^= b; c -= rol32(b, 16);		\
2862306a36Sopenharmony_ci	a ^= c; a -= rol32(c, 4);		\
2962306a36Sopenharmony_ci	b ^= a; b -= rol32(a, 14);		\
3062306a36Sopenharmony_ci	c ^= b; c -= rol32(b, 24);		\
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define JHASH_INITVAL		0xdeadbeef
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic ATTR
3662306a36Sopenharmony_ciu32 jhash(const void *key, u32 length, u32 initval)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	u32 a, b, c;
3962306a36Sopenharmony_ci	const unsigned char *k = key;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	a = b = c = JHASH_INITVAL + length + initval;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	while (length > 12) {
4462306a36Sopenharmony_ci		a += *(volatile u32 *)(k);
4562306a36Sopenharmony_ci		b += *(volatile u32 *)(k + 4);
4662306a36Sopenharmony_ci		c += *(volatile u32 *)(k + 8);
4762306a36Sopenharmony_ci		__jhash_mix(a, b, c);
4862306a36Sopenharmony_ci		length -= 12;
4962306a36Sopenharmony_ci		k += 12;
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci	switch (length) {
5262306a36Sopenharmony_ci	case 12: c += (u32)k[11]<<24;
5362306a36Sopenharmony_ci	case 11: c += (u32)k[10]<<16;
5462306a36Sopenharmony_ci	case 10: c += (u32)k[9]<<8;
5562306a36Sopenharmony_ci	case 9:  c += k[8];
5662306a36Sopenharmony_ci	case 8:  b += (u32)k[7]<<24;
5762306a36Sopenharmony_ci	case 7:  b += (u32)k[6]<<16;
5862306a36Sopenharmony_ci	case 6:  b += (u32)k[5]<<8;
5962306a36Sopenharmony_ci	case 5:  b += k[4];
6062306a36Sopenharmony_ci	case 4:  a += (u32)k[3]<<24;
6162306a36Sopenharmony_ci	case 3:  a += (u32)k[2]<<16;
6262306a36Sopenharmony_ci	case 2:  a += (u32)k[1]<<8;
6362306a36Sopenharmony_ci	case 1:  a += k[0];
6462306a36Sopenharmony_ci		 c ^= a;
6562306a36Sopenharmony_ci		 __jhash_final(a, b, c);
6662306a36Sopenharmony_ci	case 0: /* Nothing left to add */
6762306a36Sopenharmony_ci		break;
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	return c;
7162306a36Sopenharmony_ci}
72