aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/qlcnic/qlcnic.h3
-rw-r--r--drivers/net/qlcnic/qlcnic_hw.c17
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c16
3 files changed, 26 insertions, 10 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 4727204a245..9d211529fa1 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
726struct qlcnic_mac_list_s { 728struct qlcnic_mac_list_s {
727 struct list_head list; 729 struct list_head list;
@@ -932,6 +934,7 @@ struct qlcnic_mac_req {
932struct qlcnic_filter { 934struct 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 5b2bce59498..c198df90ff3 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
376static int 376static int
377qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, 377qlcnic_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 0fbfb53f259..5a6445a691b 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
1828static void qlcnic_change_filter(struct qlcnic_adapter *adapter, 1828static 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);