forked from Minki/linux
net/at91_ether: share macb_set_rx_mode with macb
Signed-off-by: Joachim Eastwood <manabian@gmail.com>
This commit is contained in:
parent
5e32353d31
commit
e0da1f144a
@ -140,111 +140,6 @@ static int set_mac_address(struct net_device *dev, void* addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inline hash_bit_value(int bitnr, __u8 *addr)
|
||||
{
|
||||
if (addr[bitnr / 8] & (1 << (bitnr % 8)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The hash address register is 64 bits long and takes up two locations in the memory map.
|
||||
* The least significant bits are stored in EMAC_HSL and the most significant
|
||||
* bits in EMAC_HSH.
|
||||
*
|
||||
* The unicast hash enable and the multicast hash enable bits in the network configuration
|
||||
* register enable the reception of hash matched frames. The destination address is
|
||||
* reduced to a 6 bit index into the 64 bit hash register using the following hash function.
|
||||
* The hash function is an exclusive or of every sixth bit of the destination address.
|
||||
* hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
|
||||
* hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
|
||||
* hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
|
||||
* hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
|
||||
* hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
|
||||
* hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
|
||||
* da[0] represents the least significant bit of the first byte received, that is, the multicast/
|
||||
* unicast indicator, and da[47] represents the most significant bit of the last byte
|
||||
* received.
|
||||
* If the hash index points to a bit that is set in the hash register then the frame will be
|
||||
* matched according to whether the frame is multicast or unicast.
|
||||
* A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and
|
||||
* the hash index points to a bit set in the hash register.
|
||||
* A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the
|
||||
* hash index points to a bit set in the hash register.
|
||||
* To receive all multicast frames, the hash register should be set with all ones and the
|
||||
* multicast hash enable bit should be set in the network configuration register.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return the hash index value for the specified address.
|
||||
*/
|
||||
static int hash_get_index(__u8 *addr)
|
||||
{
|
||||
int i, j, bitval;
|
||||
int hash_index = 0;
|
||||
|
||||
for (j = 0; j < 6; j++) {
|
||||
for (i = 0, bitval = 0; i < 8; i++)
|
||||
bitval ^= hash_bit_value(i*6 + j, addr);
|
||||
|
||||
hash_index |= (bitval << j);
|
||||
}
|
||||
|
||||
return hash_index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add multicast addresses to the internal multicast-hash table.
|
||||
*/
|
||||
static void at91ether_sethashtable(struct net_device *dev)
|
||||
{
|
||||
struct macb *lp = netdev_priv(dev);
|
||||
struct netdev_hw_addr *ha;
|
||||
unsigned long mc_filter[2];
|
||||
unsigned int bitnr;
|
||||
|
||||
mc_filter[0] = mc_filter[1] = 0;
|
||||
|
||||
netdev_for_each_mc_addr(ha, dev) {
|
||||
bitnr = hash_get_index(ha->addr);
|
||||
mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
|
||||
}
|
||||
|
||||
macb_writel(lp, HRB, mc_filter[0]);
|
||||
macb_writel(lp, HRT, mc_filter[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable/Disable promiscuous and multicast modes.
|
||||
*/
|
||||
static void at91ether_set_multicast_list(struct net_device *dev)
|
||||
{
|
||||
struct macb *lp = netdev_priv(dev);
|
||||
unsigned long cfg;
|
||||
|
||||
cfg = macb_readl(lp, NCFGR);
|
||||
|
||||
if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */
|
||||
cfg |= MACB_BIT(CAF);
|
||||
else if (dev->flags & (~IFF_PROMISC)) /* Disable promiscuous mode */
|
||||
cfg &= ~MACB_BIT(CAF);
|
||||
|
||||
if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
|
||||
macb_writel(lp, HRT, -1);
|
||||
macb_writel(lp, HRB, -1);
|
||||
cfg |= MACB_BIT(NCFGR_MTI);
|
||||
} else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
|
||||
at91ether_sethashtable(dev);
|
||||
cfg |= MACB_BIT(NCFGR_MTI);
|
||||
} else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
|
||||
macb_writel(lp, HRT, 0);
|
||||
macb_writel(lp, HRB, 0);
|
||||
cfg &= ~MACB_BIT(NCFGR_MTI);
|
||||
}
|
||||
|
||||
macb_writel(lp, NCFGR, cfg);
|
||||
}
|
||||
|
||||
/* ................................ MAC ................................ */
|
||||
|
||||
/*
|
||||
@ -500,7 +395,7 @@ static const struct net_device_ops at91ether_netdev_ops = {
|
||||
.ndo_stop = at91ether_close,
|
||||
.ndo_start_xmit = at91ether_start_xmit,
|
||||
.ndo_get_stats = at91ether_stats,
|
||||
.ndo_set_rx_mode = at91ether_set_multicast_list,
|
||||
.ndo_set_rx_mode = macb_set_rx_mode,
|
||||
.ndo_set_mac_address = set_mac_address,
|
||||
.ndo_do_ioctl = macb_ioctl,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
|
@ -997,7 +997,7 @@ static void macb_sethashtable(struct net_device *dev)
|
||||
/*
|
||||
* Enable/Disable promiscuous and multicast modes.
|
||||
*/
|
||||
static void macb_set_rx_mode(struct net_device *dev)
|
||||
void macb_set_rx_mode(struct net_device *dev)
|
||||
{
|
||||
unsigned long cfg;
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
@ -1029,6 +1029,7 @@ static void macb_set_rx_mode(struct net_device *dev)
|
||||
|
||||
macb_writel(bp, NCFGR, cfg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(macb_set_rx_mode);
|
||||
|
||||
static int macb_open(struct net_device *dev)
|
||||
{
|
||||
|
@ -574,6 +574,7 @@ extern const struct ethtool_ops macb_ethtool_ops;
|
||||
|
||||
int macb_mii_init(struct macb *bp);
|
||||
int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
|
||||
void macb_set_rx_mode(struct net_device *dev);
|
||||
|
||||
static inline bool macb_is_gem(struct macb *bp)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user