aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2010-08-31 13:17:52 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-01 13:41:57 -0400
commit03c5d770c24cd673d105fbf1a9706ae838272091 (patch)
tree420344c7cd203c648c4747293f1a41ae3b3d8ee1 /drivers/net/qlcnic
parentb5e5492c0d49e2fd6f51961d03b8533435e5e7f5 (diff)
qlcnic: mac vlan learning support
Hypervisor allows, two VM's interfaces to have same mac address. These VM's interfaces get differentiate with Vlan tag. This patch add support to learn and configure mac+vlan filter on device. Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic')
-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);