diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/qlcnic/qlcnic.h | 3 | ||||
-rw-r--r-- | drivers/net/qlcnic/qlcnic_hw.c | 17 | ||||
-rw-r--r-- | drivers/net/qlcnic/qlcnic_main.c | 16 |
3 files changed, 26 insertions, 10 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 4727204a2450..9d211529fa16 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h | |||
@@ -722,6 +722,8 @@ struct qlcnic_cardrsp_tx_ctx { | |||
722 | #define QLCNIC_MAC_NOOP 0 | 722 | #define QLCNIC_MAC_NOOP 0 |
723 | #define QLCNIC_MAC_ADD 1 | 723 | #define QLCNIC_MAC_ADD 1 |
724 | #define QLCNIC_MAC_DEL 2 | 724 | #define QLCNIC_MAC_DEL 2 |
725 | #define QLCNIC_MAC_VLAN_ADD 3 | ||
726 | #define QLCNIC_MAC_VLAN_DEL 4 | ||
725 | 727 | ||
726 | struct qlcnic_mac_list_s { | 728 | struct qlcnic_mac_list_s { |
727 | struct list_head list; | 729 | struct list_head list; |
@@ -932,6 +934,7 @@ struct qlcnic_mac_req { | |||
932 | struct qlcnic_filter { | 934 | struct qlcnic_filter { |
933 | struct hlist_node fnode; | 935 | struct hlist_node fnode; |
934 | u8 faddr[ETH_ALEN]; | 936 | u8 faddr[ETH_ALEN]; |
937 | u16 vlan_id; | ||
935 | unsigned long ftime; | 938 | unsigned long ftime; |
936 | }; | 939 | }; |
937 | 940 | ||
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 5b2bce59498d..c198df90ff3c 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c | |||
@@ -375,7 +375,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, | |||
375 | 375 | ||
376 | static int | 376 | static int |
377 | qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | 377 | qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, |
378 | unsigned op) | 378 | u16 vlan_id, unsigned op) |
379 | { | 379 | { |
380 | struct qlcnic_nic_req req; | 380 | struct qlcnic_nic_req req; |
381 | struct qlcnic_mac_req *mac_req; | 381 | struct qlcnic_mac_req *mac_req; |
@@ -391,6 +391,8 @@ qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | |||
391 | mac_req->op = op; | 391 | mac_req->op = op; |
392 | memcpy(mac_req->mac_addr, addr, 6); | 392 | memcpy(mac_req->mac_addr, addr, 6); |
393 | 393 | ||
394 | req.words[1] = cpu_to_le64(vlan_id); | ||
395 | |||
394 | return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | 396 | return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); |
395 | } | 397 | } |
396 | 398 | ||
@@ -415,7 +417,7 @@ static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, u8 *addr) | |||
415 | memcpy(cur->mac_addr, addr, ETH_ALEN); | 417 | memcpy(cur->mac_addr, addr, ETH_ALEN); |
416 | 418 | ||
417 | if (qlcnic_sre_macaddr_change(adapter, | 419 | if (qlcnic_sre_macaddr_change(adapter, |
418 | cur->mac_addr, QLCNIC_MAC_ADD)) { | 420 | cur->mac_addr, 0, QLCNIC_MAC_ADD)) { |
419 | kfree(cur); | 421 | kfree(cur); |
420 | return -EIO; | 422 | return -EIO; |
421 | } | 423 | } |
@@ -485,7 +487,7 @@ void qlcnic_free_mac_list(struct qlcnic_adapter *adapter) | |||
485 | while (!list_empty(head)) { | 487 | while (!list_empty(head)) { |
486 | cur = list_entry(head->next, struct qlcnic_mac_list_s, list); | 488 | cur = list_entry(head->next, struct qlcnic_mac_list_s, list); |
487 | qlcnic_sre_macaddr_change(adapter, | 489 | qlcnic_sre_macaddr_change(adapter, |
488 | cur->mac_addr, QLCNIC_MAC_DEL); | 490 | cur->mac_addr, 0, QLCNIC_MAC_DEL); |
489 | list_del(&cur->list); | 491 | list_del(&cur->list); |
490 | kfree(cur); | 492 | kfree(cur); |
491 | } | 493 | } |
@@ -506,7 +508,9 @@ void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter) | |||
506 | if (jiffies > | 508 | if (jiffies > |
507 | (QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) { | 509 | (QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) { |
508 | qlcnic_sre_macaddr_change(adapter, | 510 | qlcnic_sre_macaddr_change(adapter, |
509 | tmp_fil->faddr, QLCNIC_MAC_DEL); | 511 | tmp_fil->faddr, tmp_fil->vlan_id, |
512 | tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL : | ||
513 | QLCNIC_MAC_DEL); | ||
510 | spin_lock_bh(&adapter->mac_learn_lock); | 514 | spin_lock_bh(&adapter->mac_learn_lock); |
511 | adapter->fhash.fnum--; | 515 | adapter->fhash.fnum--; |
512 | hlist_del(&tmp_fil->fnode); | 516 | hlist_del(&tmp_fil->fnode); |
@@ -528,8 +532,9 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter) | |||
528 | head = &(adapter->fhash.fhead[i]); | 532 | head = &(adapter->fhash.fhead[i]); |
529 | 533 | ||
530 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { | 534 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { |
531 | qlcnic_sre_macaddr_change(adapter, | 535 | qlcnic_sre_macaddr_change(adapter, tmp_fil->faddr, |
532 | tmp_fil->faddr, QLCNIC_MAC_DEL); | 536 | tmp_fil->vlan_id, tmp_fil->vlan_id ? |
537 | QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL); | ||
533 | spin_lock_bh(&adapter->mac_learn_lock); | 538 | spin_lock_bh(&adapter->mac_learn_lock); |
534 | adapter->fhash.fnum--; | 539 | adapter->fhash.fnum--; |
535 | hlist_del(&tmp_fil->fnode); | 540 | hlist_del(&tmp_fil->fnode); |
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 0fbfb53f2594..5a6445a691b3 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c | |||
@@ -1826,7 +1826,7 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter) | |||
1826 | } | 1826 | } |
1827 | 1827 | ||
1828 | static void qlcnic_change_filter(struct qlcnic_adapter *adapter, | 1828 | static void qlcnic_change_filter(struct qlcnic_adapter *adapter, |
1829 | u64 uaddr, struct qlcnic_host_tx_ring *tx_ring) | 1829 | u64 uaddr, u16 vlan_id, struct qlcnic_host_tx_ring *tx_ring) |
1830 | { | 1830 | { |
1831 | struct cmd_desc_type0 *hwdesc; | 1831 | struct cmd_desc_type0 *hwdesc; |
1832 | struct qlcnic_nic_req *req; | 1832 | struct qlcnic_nic_req *req; |
@@ -1845,9 +1845,11 @@ static void qlcnic_change_filter(struct qlcnic_adapter *adapter, | |||
1845 | req->req_hdr = cpu_to_le64(word); | 1845 | req->req_hdr = cpu_to_le64(word); |
1846 | 1846 | ||
1847 | mac_req = (struct qlcnic_mac_req *)&(req->words[0]); | 1847 | mac_req = (struct qlcnic_mac_req *)&(req->words[0]); |
1848 | mac_req->op = QLCNIC_MAC_ADD; | 1848 | mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD; |
1849 | memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN); | 1849 | memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN); |
1850 | 1850 | ||
1851 | req->words[1] = cpu_to_le64(vlan_id); | ||
1852 | |||
1851 | tx_ring->producer = get_next_index(producer, tx_ring->num_desc); | 1853 | tx_ring->producer = get_next_index(producer, tx_ring->num_desc); |
1852 | } | 1854 | } |
1853 | 1855 | ||
@@ -1865,6 +1867,7 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter, | |||
1865 | struct hlist_node *tmp_hnode, *n; | 1867 | struct hlist_node *tmp_hnode, *n; |
1866 | struct hlist_head *head; | 1868 | struct hlist_head *head; |
1867 | u64 src_addr = 0; | 1869 | u64 src_addr = 0; |
1870 | u16 vlan_id = 0; | ||
1868 | u8 hindex; | 1871 | u8 hindex; |
1869 | 1872 | ||
1870 | if (!compare_ether_addr(phdr->h_source, adapter->mac_addr)) | 1873 | if (!compare_ether_addr(phdr->h_source, adapter->mac_addr)) |
@@ -1873,12 +1876,16 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter, | |||
1873 | if (adapter->fhash.fnum >= adapter->fhash.fmax) | 1876 | if (adapter->fhash.fnum >= adapter->fhash.fmax) |
1874 | return; | 1877 | return; |
1875 | 1878 | ||
1879 | /* Only NPAR capable devices support vlan based learning*/ | ||
1880 | if (adapter->flags & QLCNIC_ESWITCH_ENABLED) | ||
1881 | vlan_id = first_desc->vlan_TCI; | ||
1876 | memcpy(&src_addr, phdr->h_source, ETH_ALEN); | 1882 | memcpy(&src_addr, phdr->h_source, ETH_ALEN); |
1877 | hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1); | 1883 | hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1); |
1878 | head = &(adapter->fhash.fhead[hindex]); | 1884 | head = &(adapter->fhash.fhead[hindex]); |
1879 | 1885 | ||
1880 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { | 1886 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { |
1881 | if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN)) { | 1887 | if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) && |
1888 | tmp_fil->vlan_id == vlan_id) { | ||
1882 | tmp_fil->ftime = jiffies; | 1889 | tmp_fil->ftime = jiffies; |
1883 | return; | 1890 | return; |
1884 | } | 1891 | } |
@@ -1888,9 +1895,10 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter, | |||
1888 | if (!fil) | 1895 | if (!fil) |
1889 | return; | 1896 | return; |
1890 | 1897 | ||
1891 | qlcnic_change_filter(adapter, src_addr, tx_ring); | 1898 | qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring); |
1892 | 1899 | ||
1893 | fil->ftime = jiffies; | 1900 | fil->ftime = jiffies; |
1901 | fil->vlan_id = vlan_id; | ||
1894 | memcpy(fil->faddr, &src_addr, ETH_ALEN); | 1902 | memcpy(fil->faddr, &src_addr, ETH_ALEN); |
1895 | spin_lock(&adapter->mac_learn_lock); | 1903 | spin_lock(&adapter->mac_learn_lock); |
1896 | hlist_add_head(&(fil->fnode), head); | 1904 | hlist_add_head(&(fil->fnode), head); |