aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShahed Shaikh <shahed.shaikh@qlogic.com>2015-02-11 09:45:24 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-11 22:43:22 -0500
commitfe79fabbed056d081d6130cbd83e5b2fc42c3c52 (patch)
tree113aec2bf9639a90e6f0aff83d703fc003e1615a
parentde61390cb3e03186f85997fe08a11dcb9f7a01a3 (diff)
qlcnic: Delete existing multicast MAC list before adding new
Driver keeps adding multicast addresses without deleting removed MACs and worrying about adapters filter limit. This results into actual count of programmed multicast addresses get accumulated over the time and overruns the adapter's filter limit without putting device in ACCEPT_ALL_MULTI mode. This causes newly added multicast traffic to fail after the sequence of addition - deletion in certain pattern. This issue is seen only when netdev's mcast list count is less than adapters mcast filter limit. e.g. If adapters multicast filter limit is 38 per function then following sequence would result in multicast traffic failure for newly added MACs. - add less than 38 multicast MACs - remove previously added multicast MACs - add new multicast MACs (less than 38) Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h11
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c34
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c19
3 files changed, 51 insertions, 13 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index e56c1bb36141..fa4317611fd6 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -848,10 +848,17 @@ struct qlcnic_cardrsp_tx_ctx {
848#define QLCNIC_MAC_VLAN_ADD 3 848#define QLCNIC_MAC_VLAN_ADD 3
849#define QLCNIC_MAC_VLAN_DEL 4 849#define QLCNIC_MAC_VLAN_DEL 4
850 850
851enum qlcnic_mac_type {
852 QLCNIC_UNICAST_MAC,
853 QLCNIC_MULTICAST_MAC,
854 QLCNIC_BROADCAST_MAC,
855};
856
851struct qlcnic_mac_vlan_list { 857struct qlcnic_mac_vlan_list {
852 struct list_head list; 858 struct list_head list;
853 uint8_t mac_addr[ETH_ALEN+2]; 859 uint8_t mac_addr[ETH_ALEN+2];
854 u16 vlan_id; 860 u16 vlan_id;
861 enum qlcnic_mac_type mac_type;
855}; 862};
856 863
857/* MAC Learn */ 864/* MAC Learn */
@@ -1615,7 +1622,9 @@ void qlcnic_watchdog_task(struct work_struct *work);
1615void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, 1622void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
1616 struct qlcnic_host_rds_ring *rds_ring, u8 ring_id); 1623 struct qlcnic_host_rds_ring *rds_ring, u8 ring_id);
1617void qlcnic_set_multi(struct net_device *netdev); 1624void qlcnic_set_multi(struct net_device *netdev);
1618int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *, u16); 1625void qlcnic_flush_mcast_mac(struct qlcnic_adapter *);
1626int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *, u16,
1627 enum qlcnic_mac_type);
1619int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *); 1628int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *);
1620void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter); 1629void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter);
1621int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *); 1630int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 69b46c051cc0..3e0f705a4311 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -487,7 +487,8 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr)
487 return err; 487 return err;
488} 488}
489 489
490int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan) 490int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan,
491 enum qlcnic_mac_type mac_type)
491{ 492{
492 struct qlcnic_mac_vlan_list *cur; 493 struct qlcnic_mac_vlan_list *cur;
493 struct list_head *head; 494 struct list_head *head;
@@ -513,10 +514,29 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
513 } 514 }
514 515
515 cur->vlan_id = vlan; 516 cur->vlan_id = vlan;
517 cur->mac_type = mac_type;
518
516 list_add_tail(&cur->list, &adapter->mac_list); 519 list_add_tail(&cur->list, &adapter->mac_list);
517 return 0; 520 return 0;
518} 521}
519 522
523void qlcnic_flush_mcast_mac(struct qlcnic_adapter *adapter)
524{
525 struct qlcnic_mac_vlan_list *cur;
526 struct list_head *head, *tmp;
527
528 list_for_each_safe(head, tmp, &adapter->mac_list) {
529 cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
530 if (cur->mac_type != QLCNIC_MULTICAST_MAC)
531 continue;
532
533 qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
534 cur->vlan_id, QLCNIC_MAC_DEL);
535 list_del(&cur->list);
536 kfree(cur);
537 }
538}
539
520static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) 540static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
521{ 541{
522 struct qlcnic_adapter *adapter = netdev_priv(netdev); 542 struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -530,8 +550,9 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
530 if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) 550 if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
531 return; 551 return;
532 552
533 qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan); 553 qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan,
534 qlcnic_nic_add_mac(adapter, bcast_addr, vlan); 554 QLCNIC_UNICAST_MAC);
555 qlcnic_nic_add_mac(adapter, bcast_addr, vlan, QLCNIC_BROADCAST_MAC);
535 556
536 if (netdev->flags & IFF_PROMISC) { 557 if (netdev->flags & IFF_PROMISC) {
537 if (!(adapter->flags & QLCNIC_PROMISC_DISABLED)) 558 if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
@@ -540,8 +561,10 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
540 (netdev_mc_count(netdev) > ahw->max_mc_count)) { 561 (netdev_mc_count(netdev) > ahw->max_mc_count)) {
541 mode = VPORT_MISS_MODE_ACCEPT_MULTI; 562 mode = VPORT_MISS_MODE_ACCEPT_MULTI;
542 } else if (!netdev_mc_empty(netdev)) { 563 } else if (!netdev_mc_empty(netdev)) {
564 qlcnic_flush_mcast_mac(adapter);
543 netdev_for_each_mc_addr(ha, netdev) 565 netdev_for_each_mc_addr(ha, netdev)
544 qlcnic_nic_add_mac(adapter, ha->addr, vlan); 566 qlcnic_nic_add_mac(adapter, ha->addr, vlan,
567 QLCNIC_MULTICAST_MAC);
545 } 568 }
546 569
547 /* configure unicast MAC address, if there is not sufficient space 570 /* 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)
551 mode = VPORT_MISS_MODE_ACCEPT_ALL; 574 mode = VPORT_MISS_MODE_ACCEPT_ALL;
552 } else if (!netdev_uc_empty(netdev)) { 575 } else if (!netdev_uc_empty(netdev)) {
553 netdev_for_each_uc_addr(ha, netdev) 576 netdev_for_each_uc_addr(ha, netdev)
554 qlcnic_nic_add_mac(adapter, ha->addr, vlan); 577 qlcnic_nic_add_mac(adapter, ha->addr, vlan,
578 QLCNIC_UNICAST_MAC);
555 } 579 }
556 580
557 if (mode == VPORT_MISS_MODE_ACCEPT_ALL && 581 if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
index 1659c804f1d5..e6312465fe45 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -1489,7 +1489,8 @@ out:
1489 return ret; 1489 return ret;
1490} 1490}
1491 1491
1492static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac) 1492static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac,
1493 enum qlcnic_mac_type mac_type)
1493{ 1494{
1494 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1495 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1495 struct qlcnic_sriov *sriov = adapter->ahw->sriov; 1496 struct qlcnic_sriov *sriov = adapter->ahw->sriov;
@@ -1500,17 +1501,18 @@ static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac)
1500 vf = &adapter->ahw->sriov->vf_info[0]; 1501 vf = &adapter->ahw->sriov->vf_info[0];
1501 1502
1502 if (!qlcnic_sriov_check_any_vlan(vf)) { 1503 if (!qlcnic_sriov_check_any_vlan(vf)) {
1503 qlcnic_nic_add_mac(adapter, mac, 0); 1504 qlcnic_nic_add_mac(adapter, mac, 0, mac_type);
1504 } else { 1505 } else {
1505 spin_lock(&vf->vlan_list_lock); 1506 spin_lock(&vf->vlan_list_lock);
1506 for (i = 0; i < sriov->num_allowed_vlans; i++) { 1507 for (i = 0; i < sriov->num_allowed_vlans; i++) {
1507 vlan_id = vf->sriov_vlans[i]; 1508 vlan_id = vf->sriov_vlans[i];
1508 if (vlan_id) 1509 if (vlan_id)
1509 qlcnic_nic_add_mac(adapter, mac, vlan_id); 1510 qlcnic_nic_add_mac(adapter, mac, vlan_id,
1511 mac_type);
1510 } 1512 }
1511 spin_unlock(&vf->vlan_list_lock); 1513 spin_unlock(&vf->vlan_list_lock);
1512 if (qlcnic_84xx_check(adapter)) 1514 if (qlcnic_84xx_check(adapter))
1513 qlcnic_nic_add_mac(adapter, mac, 0); 1515 qlcnic_nic_add_mac(adapter, mac, 0, mac_type);
1514 } 1516 }
1515} 1517}
1516 1518
@@ -1549,10 +1551,12 @@ void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
1549 (netdev_mc_count(netdev) > ahw->max_mc_count)) { 1551 (netdev_mc_count(netdev) > ahw->max_mc_count)) {
1550 mode = VPORT_MISS_MODE_ACCEPT_MULTI; 1552 mode = VPORT_MISS_MODE_ACCEPT_MULTI;
1551 } else { 1553 } else {
1552 qlcnic_vf_add_mc_list(netdev, bcast_addr); 1554 qlcnic_vf_add_mc_list(netdev, bcast_addr, QLCNIC_BROADCAST_MAC);
1553 if (!netdev_mc_empty(netdev)) { 1555 if (!netdev_mc_empty(netdev)) {
1556 qlcnic_flush_mcast_mac(adapter);
1554 netdev_for_each_mc_addr(ha, netdev) 1557 netdev_for_each_mc_addr(ha, netdev)
1555 qlcnic_vf_add_mc_list(netdev, ha->addr); 1558 qlcnic_vf_add_mc_list(netdev, ha->addr,
1559 QLCNIC_MULTICAST_MAC);
1556 } 1560 }
1557 } 1561 }
1558 1562
@@ -1563,7 +1567,8 @@ void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
1563 mode = VPORT_MISS_MODE_ACCEPT_ALL; 1567 mode = VPORT_MISS_MODE_ACCEPT_ALL;
1564 } else if (!netdev_uc_empty(netdev)) { 1568 } else if (!netdev_uc_empty(netdev)) {
1565 netdev_for_each_uc_addr(ha, netdev) 1569 netdev_for_each_uc_addr(ha, netdev)
1566 qlcnic_vf_add_mc_list(netdev, ha->addr); 1570 qlcnic_vf_add_mc_list(netdev, ha->addr,
1571 QLCNIC_UNICAST_MAC);
1567 } 1572 }
1568 1573
1569 if (adapter->pdev->is_virtfn) { 1574 if (adapter->pdev->is_virtfn) {