netxen: hw multicast filtering
Enable multicast address filtering capabilities in the hardware. Upto 16 multicast addresses can be programmed for each physical port. Support "allmulti" mode, if enabled. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:

committed by
Jeff Garzik

parent
7830b22cbc
commit
623621b07e
@@ -154,7 +154,6 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
|
||||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
DPRINTK(INFO, "valid ether addr\n");
|
||||
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
|
||||
|
||||
if (adapter->macaddr_set)
|
||||
@@ -163,6 +162,91 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NETXEN_UNICAST_ADDR(port, index) \
|
||||
(NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
|
||||
#define NETXEN_MCAST_ADDR(port, index) \
|
||||
(NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))
|
||||
#define MAC_HI(addr) \
|
||||
((addr[2] << 16) | (addr[1] << 8) | (addr[0]))
|
||||
#define MAC_LO(addr) \
|
||||
((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
|
||||
|
||||
static int
|
||||
netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
|
||||
{
|
||||
u32 val = 0;
|
||||
u16 port = adapter->physical_port;
|
||||
u8 *addr = adapter->netdev->dev_addr;
|
||||
|
||||
if (adapter->mc_enabled)
|
||||
return 0;
|
||||
|
||||
netxen_nic_hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
|
||||
val |= (1UL << (28+port));
|
||||
netxen_nic_hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
|
||||
|
||||
/* add broadcast addr to filter */
|
||||
val = 0xffffff;
|
||||
netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
|
||||
netxen_crb_writelit_adapter(adapter,
|
||||
NETXEN_UNICAST_ADDR(port, 0)+4, val);
|
||||
|
||||
/* add station addr to filter */
|
||||
val = MAC_HI(addr);
|
||||
netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
|
||||
val = MAC_LO(addr);
|
||||
netxen_crb_writelit_adapter(adapter,
|
||||
NETXEN_UNICAST_ADDR(port, 1)+4, val);
|
||||
|
||||
adapter->mc_enabled = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
|
||||
{
|
||||
u32 val = 0;
|
||||
u16 port = adapter->physical_port;
|
||||
u8 *addr = adapter->netdev->dev_addr;
|
||||
|
||||
if (!adapter->mc_enabled)
|
||||
return 0;
|
||||
|
||||
netxen_nic_hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
|
||||
val &= ~(1UL << (28+port));
|
||||
netxen_nic_hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
|
||||
|
||||
val = MAC_HI(addr);
|
||||
netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
|
||||
val = MAC_LO(addr);
|
||||
netxen_crb_writelit_adapter(adapter,
|
||||
NETXEN_UNICAST_ADDR(port, 0)+4, val);
|
||||
|
||||
netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
|
||||
netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
|
||||
|
||||
adapter->mc_enabled = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
|
||||
int index, u8 *addr)
|
||||
{
|
||||
u32 hi = 0, lo = 0;
|
||||
u16 port = adapter->physical_port;
|
||||
|
||||
lo = MAC_LO(addr);
|
||||
hi = MAC_HI(addr);
|
||||
|
||||
netxen_crb_writelit_adapter(adapter,
|
||||
NETXEN_MCAST_ADDR(port, index), hi);
|
||||
netxen_crb_writelit_adapter(adapter,
|
||||
NETXEN_MCAST_ADDR(port, index)+4, lo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* netxen_nic_set_multi - Multicast
|
||||
*/
|
||||
@@ -170,17 +254,48 @@ void netxen_nic_set_multi(struct net_device *netdev)
|
||||
{
|
||||
struct netxen_adapter *adapter = netdev_priv(netdev);
|
||||
struct dev_mc_list *mc_ptr;
|
||||
u8 null_addr[6];
|
||||
int index = 0;
|
||||
|
||||
memset(null_addr, 0, 6);
|
||||
|
||||
mc_ptr = netdev->mc_list;
|
||||
if (netdev->flags & IFF_PROMISC) {
|
||||
if (adapter->set_promisc)
|
||||
adapter->set_promisc(adapter,
|
||||
NETXEN_NIU_PROMISC_MODE);
|
||||
} else {
|
||||
if (adapter->unset_promisc)
|
||||
adapter->unset_promisc(adapter,
|
||||
NETXEN_NIU_NON_PROMISC_MODE);
|
||||
|
||||
adapter->set_promisc(adapter,
|
||||
NETXEN_NIU_PROMISC_MODE);
|
||||
|
||||
/* Full promiscuous mode */
|
||||
netxen_nic_disable_mcast_filter(adapter);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (netdev->mc_count == 0) {
|
||||
adapter->set_promisc(adapter,
|
||||
NETXEN_NIU_NON_PROMISC_MODE);
|
||||
netxen_nic_disable_mcast_filter(adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE);
|
||||
if (netdev->flags & IFF_ALLMULTI ||
|
||||
netdev->mc_count > adapter->max_mc_count) {
|
||||
netxen_nic_disable_mcast_filter(adapter);
|
||||
return;
|
||||
}
|
||||
|
||||
netxen_nic_enable_mcast_filter(adapter);
|
||||
|
||||
for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++)
|
||||
netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr);
|
||||
|
||||
if (index != netdev->mc_count)
|
||||
printk(KERN_WARNING "%s: %s multicast address count mismatch\n",
|
||||
netxen_nic_driver_name, netdev->name);
|
||||
|
||||
/* Clear out remaining addresses */
|
||||
for (; index < adapter->max_mc_count; index++)
|
||||
netxen_nic_set_mcast_addr(adapter, index, null_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user