|
@@ -154,7 +154,6 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
|
|
if (!is_valid_ether_addr(addr->sa_data))
|
|
if (!is_valid_ether_addr(addr->sa_data))
|
|
return -EADDRNOTAVAIL;
|
|
return -EADDRNOTAVAIL;
|
|
|
|
|
|
- DPRINTK(INFO, "valid ether addr\n");
|
|
|
|
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
|
|
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
|
|
|
|
|
|
if (adapter->macaddr_set)
|
|
if (adapter->macaddr_set)
|
|
@@ -163,6 +162,91 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
|
|
return 0;
|
|
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
|
|
* 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 netxen_adapter *adapter = netdev_priv(netdev);
|
|
struct dev_mc_list *mc_ptr;
|
|
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 (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);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|