Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[cascardo/linux.git] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_hw.c
index a5a4829..75ee9e4 100644 (file)
@@ -487,7 +487,8 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr)
        return err;
 }
 
-int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
+int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan,
+                      enum qlcnic_mac_type mac_type)
 {
        struct qlcnic_mac_vlan_list *cur;
        struct list_head *head;
@@ -513,10 +514,29 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
        }
 
        cur->vlan_id = vlan;
+       cur->mac_type = mac_type;
+
        list_add_tail(&cur->list, &adapter->mac_list);
        return 0;
 }
 
+void qlcnic_flush_mcast_mac(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_mac_vlan_list *cur;
+       struct list_head *head, *tmp;
+
+       list_for_each_safe(head, tmp, &adapter->mac_list) {
+               cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
+               if (cur->mac_type != QLCNIC_MULTICAST_MAC)
+                       continue;
+
+               qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
+                                         cur->vlan_id, QLCNIC_MAC_DEL);
+               list_del(&cur->list);
+               kfree(cur);
+       }
+}
+
 static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -530,8 +550,9 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
        if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
                return;
 
-       qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan);
-       qlcnic_nic_add_mac(adapter, bcast_addr, vlan);
+       qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan,
+                          QLCNIC_UNICAST_MAC);
+       qlcnic_nic_add_mac(adapter, bcast_addr, vlan, QLCNIC_BROADCAST_MAC);
 
        if (netdev->flags & IFF_PROMISC) {
                if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
@@ -540,8 +561,10 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
                   (netdev_mc_count(netdev) > ahw->max_mc_count)) {
                mode = VPORT_MISS_MODE_ACCEPT_MULTI;
        } else if (!netdev_mc_empty(netdev)) {
+               qlcnic_flush_mcast_mac(adapter);
                netdev_for_each_mc_addr(ha, netdev)
-                       qlcnic_nic_add_mac(adapter, ha->addr, vlan);
+                       qlcnic_nic_add_mac(adapter, ha->addr, vlan,
+                                          QLCNIC_MULTICAST_MAC);
        }
 
        /* configure unicast MAC address, if there is not sufficient space
@@ -551,7 +574,8 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
                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);
+                       qlcnic_nic_add_mac(adapter, ha->addr, vlan,
+                                          QLCNIC_UNICAST_MAC);
        }
 
        if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&