qlcnic: Secondary unicast MAC address support.
[linux-2.6-block.git] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_hw.c
index 218978db29630f45862da1b3954c11cdae764af8..e7f305d5bb5fc4136b618c18ecc32f29d4c6df66 100644 (file)
@@ -499,6 +499,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
 void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct netdev_hw_addr *ha;
        static const u8 bcast_addr[ETH_ALEN] = {
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff
@@ -515,25 +516,30 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
        if (netdev->flags & IFF_PROMISC) {
                if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
                        mode = VPORT_MISS_MODE_ACCEPT_ALL;
-               goto send_fw_cmd;
-       }
-
-       if ((netdev->flags & IFF_ALLMULTI) ||
-           (netdev_mc_count(netdev) > adapter->ahw->max_mc_count)) {
-               mode = VPORT_MISS_MODE_ACCEPT_MULTI;
-               goto send_fw_cmd;
+       } else if (netdev->flags & IFF_ALLMULTI) {
+               if (netdev_mc_count(netdev) > ahw->max_mc_count) {
+                       mode = VPORT_MISS_MODE_ACCEPT_MULTI;
+               } else if (!netdev_mc_empty(netdev) &&
+                          !qlcnic_sriov_vf_check(adapter)) {
+                               netdev_for_each_mc_addr(ha, netdev)
+                                       qlcnic_nic_add_mac(adapter, ha->addr,
+                                                          vlan);
+               }
+               if (mode != VPORT_MISS_MODE_ACCEPT_MULTI &&
+                   qlcnic_sriov_vf_check(adapter))
+                       qlcnic_vf_add_mc_list(netdev, vlan);
        }
 
-       if (!netdev_mc_empty(netdev) && !qlcnic_sriov_vf_check(adapter)) {
-               netdev_for_each_mc_addr(ha, netdev) {
+       /* configure unicast MAC address, if there is not sufficient space
+        * to store all the unicast addresses then enable promiscuous mode
+        */
+       if (netdev_uc_count(netdev) > ahw->max_uc_count) {
+               mode = VPORT_MISS_MODE_ACCEPT_ALL;
+       } else if (!netdev_uc_empty(netdev)) {
+               netdev_for_each_uc_addr(ha, netdev)
                        qlcnic_nic_add_mac(adapter, ha->addr, vlan);
-               }
        }
 
-       if (qlcnic_sriov_vf_check(adapter))
-               qlcnic_vf_add_mc_list(netdev, vlan);
-
-send_fw_cmd:
        if (!qlcnic_sriov_vf_check(adapter)) {
                if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&
                    !adapter->fdb_mac_learn) {