1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2019 Facebook
3 
4 typedef unsigned int u32;
5 
6 static __attribute__((always_inline)) u32 rol32(u32 word, unsigned int shift)
7 {
8 	return (word << shift) | (word >> ((-shift) & 31));
9 }
10 
11 #define __jhash_mix(a, b, c)			\
12 {						\
13 	a -= c;  a ^= rol32(c, 4);  c += b;	\
14 	b -= a;  b ^= rol32(a, 6);  a += c;	\
15 	c -= b;  c ^= rol32(b, 8);  b += a;	\
16 	a -= c;  a ^= rol32(c, 16); c += b;	\
17 	b -= a;  b ^= rol32(a, 19); a += c;	\
18 	c -= b;  c ^= rol32(b, 4);  b += a;	\
19 }
20 
21 #define __jhash_final(a, b, c)			\
22 {						\
23 	c ^= b; c -= rol32(b, 14);		\
24 	a ^= c; a -= rol32(c, 11);		\
25 	b ^= a; b -= rol32(a, 25);		\
26 	c ^= b; c -= rol32(b, 16);		\
27 	a ^= c; a -= rol32(c, 4);		\
28 	b ^= a; b -= rol32(a, 14);		\
29 	c ^= b; c -= rol32(b, 24);		\
30 }
31 
32 #define JHASH_INITVAL		0xdeadbeef
33 
34 static ATTR
35 u32 jhash(const void *key, u32 length, u32 initval)
36 {
37 	u32 a, b, c;
38 	const unsigned char *k = key;
39 
40 	a = b = c = JHASH_INITVAL + length + initval;
41 
42 	while (length > 12) {
43 		a += *(volatile u32 *)(k);
44 		b += *(volatile u32 *)(k + 4);
45 		c += *(volatile u32 *)(k + 8);
46 		__jhash_mix(a, b, c);
47 		length -= 12;
48 		k += 12;
49 	}
50 	switch (length) {
51 	case 12: c += (u32)k[11]<<24;
52 	case 11: c += (u32)k[10]<<16;
53 	case 10: c += (u32)k[9]<<8;
54 	case 9:  c += k[8];
55 	case 8:  b += (u32)k[7]<<24;
56 	case 7:  b += (u32)k[6]<<16;
57 	case 6:  b += (u32)k[5]<<8;
58 	case 5:  b += k[4];
59 	case 4:  a += (u32)k[3]<<24;
60 	case 3:  a += (u32)k[2]<<16;
61 	case 2:  a += (u32)k[1]<<8;
62 	case 1:  a += k[0];
63 		 c ^= a;
64 		 __jhash_final(a, b, c);
65 	case 0: /* Nothing left to add */
66 		break;
67 	}
68 
69 	return c;
70 }
71