Commit 9e9c6725 authored by Jeff Garzik's avatar Jeff Garzik

[netdrvr] ethernet crc fixes

* ether_crc has always been wrong in 2.5.x. ug. we want
  bitreverse crc32_le instead
* use ether_crc in natsemi
parent 26bc6d92
...@@ -164,6 +164,7 @@ ...@@ -164,6 +164,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/mii.h> #include <linux/mii.h>
#include <linux/crc32.h>
#include <asm/processor.h> /* Processor type for cache alignment. */ #include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -1898,44 +1899,6 @@ static struct net_device_stats *get_stats(struct net_device *dev) ...@@ -1898,44 +1899,6 @@ static struct net_device_stats *get_stats(struct net_device *dev)
return &np->stats; return &np->stats;
} }
/**
* dp83815_crc - computer CRC for hash table entries
*
* Note - this is, for some reason, *not* the same function
* as ether_crc_le() or ether_crc(), though it uses the
* same big-endian polynomial.
*/
#define DP_POLYNOMIAL 0x04C11DB7
static unsigned dp83815_crc(int length, unsigned char *data)
{
u32 crc;
u8 cur_byte;
u8 msb;
u8 byte, bit;
crc = ~0;
for (byte=0; byte<length; byte++) {
cur_byte = *data++;
for (bit=0; bit<8; bit++) {
msb = crc >> 31;
crc <<= 1;
if (msb ^ (cur_byte & 1)) {
crc ^= DP_POLYNOMIAL;
crc |= 1;
}
cur_byte >>= 1;
}
}
crc >>= 23;
return (crc);
}
void set_bit_le(int offset, unsigned char * data)
{
data[offset >> 3] |= (1 << (offset & 0x07));
}
#define HASH_TABLE 0x200 #define HASH_TABLE 0x200
static void __set_rx_mode(struct net_device *dev) static void __set_rx_mode(struct net_device *dev)
{ {
...@@ -1960,9 +1923,8 @@ static void __set_rx_mode(struct net_device *dev) ...@@ -1960,9 +1923,8 @@ static void __set_rx_mode(struct net_device *dev)
memset(mc_filter, 0, sizeof(mc_filter)); memset(mc_filter, 0, sizeof(mc_filter));
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist = mclist->next) { i++, mclist = mclist->next) {
set_bit_le( int i = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 23) & 0x1ff;
dp83815_crc(ETH_ALEN, mclist->dmi_addr) & 0x1ff, mc_filter[i/8] |= (1 << (i & 0x07));
mc_filter);
} }
rx_mode = RxFilterEnable | AcceptBroadcast rx_mode = RxFilterEnable | AcceptBroadcast
| AcceptMulticast | AcceptMyPhys; | AcceptMulticast | AcceptMyPhys;
......
...@@ -9,9 +9,19 @@ ...@@ -9,9 +9,19 @@
extern u32 crc32_le(u32 crc, unsigned char const *p, size_t len); extern u32 crc32_le(u32 crc, unsigned char const *p, size_t len);
extern u32 crc32_be(u32 crc, unsigned char const *p, size_t len); extern u32 crc32_be(u32 crc, unsigned char const *p, size_t len);
extern u32 bitreverse(u32 in);
#define crc32(seed, data, length) crc32_le(seed, (unsigned char const *)data, length) #define crc32(seed, data, length) crc32_le(seed, (unsigned char const *)data, length)
/*
* Helpers for hash table generation of ethernet nics:
*
* Ethernet sends the least significant bit of a byte first, thus crc32_le
* is used. The output of crc32_le is bit reversed [most significant bit
* is in bit nr 0], thus it must be reversed before use. Except for
* nics that bit swap the result internally...
*/
#define ether_crc(length, data) bitreverse(crc32_le(~0, data, length))
#define ether_crc_le(length, data) crc32_le(~0, data, length) #define ether_crc_le(length, data) crc32_le(~0, data, length)
#define ether_crc(length, data) crc32_be(~0, data, length)
#endif /* _LINUX_CRC32_H */ #endif /* _LINUX_CRC32_H */
...@@ -265,8 +265,19 @@ u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len) ...@@ -265,8 +265,19 @@ u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len)
} }
#endif #endif
u32 bitreverse(u32 x)
{
x = (x >> 16) | (x << 16);
x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00);
x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0);
x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc);
x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa);
return x;
}
EXPORT_SYMBOL(crc32_le); EXPORT_SYMBOL(crc32_le);
EXPORT_SYMBOL(crc32_be); EXPORT_SYMBOL(crc32_be);
EXPORT_SYMBOL(bitreverse);
/* /*
* A brief CRC tutorial. * A brief CRC tutorial.
...@@ -412,16 +423,6 @@ buf_dump(char const *prefix, unsigned char const *buf, size_t len) ...@@ -412,16 +423,6 @@ buf_dump(char const *prefix, unsigned char const *buf, size_t len)
} }
#endif #endif
static u32 attribute((const)) bitreverse(u32 x)
{
x = (x >> 16) | (x << 16);
x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00);
x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0);
x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc);
x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa);
return x;
}
static void bytereverse(unsigned char *buf, size_t len) static void bytereverse(unsigned char *buf, size_t len)
{ {
while (len--) { while (len--) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment