|
@@ -237,13 +237,29 @@ static inline bool is_etherdev_addr(const struct net_device *dev,
|
|
|
* entry points.
|
|
|
*/
|
|
|
|
|
|
-static inline int compare_ether_header(const void *a, const void *b)
|
|
|
+static inline unsigned long compare_ether_header(const void *a, const void *b)
|
|
|
{
|
|
|
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
|
|
|
+ unsigned long fold;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We want to compare 14 bytes:
|
|
|
+ * [a0 ... a13] ^ [b0 ... b13]
|
|
|
+ * Use two long XOR, ORed together, with an overlap of two bytes.
|
|
|
+ * [a0 a1 a2 a3 a4 a5 a6 a7 ] ^ [b0 b1 b2 b3 b4 b5 b6 b7 ] |
|
|
|
+ * [a6 a7 a8 a9 a10 a11 a12 a13] ^ [b6 b7 b8 b9 b10 b11 b12 b13]
|
|
|
+ * This means the [a6 a7] ^ [b6 b7] part is done two times.
|
|
|
+ */
|
|
|
+ fold = *(unsigned long *)a ^ *(unsigned long *)b;
|
|
|
+ fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6);
|
|
|
+ return fold;
|
|
|
+#else
|
|
|
u32 *a32 = (u32 *)((u8 *)a + 2);
|
|
|
u32 *b32 = (u32 *)((u8 *)b + 2);
|
|
|
|
|
|
return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) |
|
|
|
(a32[1] ^ b32[1]) | (a32[2] ^ b32[2]);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
#endif /* _LINUX_ETHERDEVICE_H */
|