aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2010-08-25 00:03:03 -0400
committerDavid S. Miller <davem@davemloft.net>2010-08-25 17:15:27 -0400
commit8cf61f890ac4c2a15acb24658feba13c9c838b52 (patch)
tree35a476615af3563c56b7ca3022b44fb194010944 /drivers
parente9a47700cb35bc84d4954f762a193b150722612e (diff)
qlcnic: support port vlan id
On NIC Partition capable adapter, Administrator can configure to tag packet with particular vlan id. Packet will be tagged and strip with that vlan id. Also if 'Tagging' flag is disable, other packet will be drop. Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/qlcnic/qlcnic.h4
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c39
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c89
3 files changed, 111 insertions, 21 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 508d531a55e5..d15de63ed0bb 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -175,7 +175,7 @@
175 ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)) 175 ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
176 176
177#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \ 177#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
178 ((_desc)->flags_opcode = \ 178 ((_desc)->flags_opcode |= \
179 cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))) 179 cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
180 180
181#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \ 181#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
@@ -902,6 +902,7 @@ struct qlcnic_mac_req {
902#define QLCNIC_BRIDGE_ENABLED 0X10 902#define QLCNIC_BRIDGE_ENABLED 0X10
903#define QLCNIC_DIAG_ENABLED 0x20 903#define QLCNIC_DIAG_ENABLED 0x20
904#define QLCNIC_ESWITCH_ENABLED 0x40 904#define QLCNIC_ESWITCH_ENABLED 0x40
905#define QLCNIC_TAGGING_ENABLED 0x100
905#define QLCNIC_MACSPOOF 0x200 906#define QLCNIC_MACSPOOF 0x200
906#define QLCNIC_IS_MSI_FAMILY(adapter) \ 907#define QLCNIC_IS_MSI_FAMILY(adapter) \
907 ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) 908 ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
@@ -967,6 +968,7 @@ struct qlcnic_adapter {
967 u16 max_tx_ques; 968 u16 max_tx_ques;
968 u16 max_rx_ques; 969 u16 max_rx_ques;
969 u16 max_mtu; 970 u16 max_mtu;
971 u16 pvid;
970 972
971 u32 fw_hal_version; 973 u32 fw_hal_version;
972 u32 capabilities; 974 u32 capabilities;
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index a174521daa63..df91b754bb70 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -25,6 +25,7 @@
25#include <linux/netdevice.h> 25#include <linux/netdevice.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/if_vlan.h>
28#include "qlcnic.h" 29#include "qlcnic.h"
29 30
30struct crb_addr_pair { 31struct crb_addr_pair {
@@ -1302,6 +1303,27 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
1302 return skb; 1303 return skb;
1303} 1304}
1304 1305
1306static int
1307qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb)
1308{
1309 u16 vlan_tag;
1310 struct ethhdr *eth_hdr;
1311
1312 if (!__vlan_get_tag(skb, &vlan_tag)) {
1313 if (vlan_tag == adapter->pvid) {
1314 /* strip the tag from the packet and send it up */
1315 eth_hdr = (struct ethhdr *) skb->data;
1316 memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
1317 skb_pull(skb, VLAN_HLEN);
1318 return 0;
1319 }
1320 }
1321 if (adapter->flags & QLCNIC_TAGGING_ENABLED)
1322 return 0;
1323
1324 return -EIO;
1325}
1326
1305static struct qlcnic_rx_buffer * 1327static struct qlcnic_rx_buffer *
1306qlcnic_process_rcv(struct qlcnic_adapter *adapter, 1328qlcnic_process_rcv(struct qlcnic_adapter *adapter,
1307 struct qlcnic_host_sds_ring *sds_ring, 1329 struct qlcnic_host_sds_ring *sds_ring,
@@ -1342,6 +1364,15 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter,
1342 skb_pull(skb, pkt_offset); 1364 skb_pull(skb, pkt_offset);
1343 1365
1344 skb->truesize = skb->len + sizeof(struct sk_buff); 1366 skb->truesize = skb->len + sizeof(struct sk_buff);
1367
1368 if (unlikely(adapter->pvid)) {
1369 if (qlcnic_check_rx_tagging(adapter, skb)) {
1370 adapter->stats.rxdropped++;
1371 dev_kfree_skb_any(skb);
1372 return buffer;
1373 }
1374 }
1375
1345 skb->protocol = eth_type_trans(skb, netdev); 1376 skb->protocol = eth_type_trans(skb, netdev);
1346 1377
1347 napi_gro_receive(&sds_ring->napi, skb); 1378 napi_gro_receive(&sds_ring->napi, skb);
@@ -1406,6 +1437,14 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
1406 skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); 1437 skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb);
1407 1438
1408 skb_pull(skb, l2_hdr_offset); 1439 skb_pull(skb, l2_hdr_offset);
1440
1441 if (unlikely(adapter->pvid)) {
1442 if (qlcnic_check_rx_tagging(adapter, skb)) {
1443 adapter->stats.rxdropped++;
1444 dev_kfree_skb_any(skb);
1445 return buffer;
1446 }
1447 }
1409 skb->protocol = eth_type_trans(skb, netdev); 1448 skb->protocol = eth_type_trans(skb, netdev);
1410 1449
1411 iph = (struct iphdr *)skb->data; 1450 iph = (struct iphdr *)skb->data;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 5d93b464681a..089212214ad4 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -759,6 +759,21 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
759} 759}
760 760
761static void 761static void
762qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
763 struct qlcnic_esw_func_cfg *esw_cfg)
764{
765 if (esw_cfg->discard_tagged)
766 adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
767 else
768 adapter->flags |= QLCNIC_TAGGING_ENABLED;
769
770 if (esw_cfg->vlan_id)
771 adapter->pvid = esw_cfg->vlan_id;
772 else
773 adapter->pvid = 0;
774}
775
776static void
762qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, 777qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
763 struct qlcnic_esw_func_cfg *esw_cfg) 778 struct qlcnic_esw_func_cfg *esw_cfg)
764{ 779{
@@ -781,6 +796,7 @@ qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
781 esw_cfg.pci_func = adapter->ahw.pci_func; 796 esw_cfg.pci_func = adapter->ahw.pci_func;
782 if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg)) 797 if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg))
783 return -EIO; 798 return -EIO;
799 qlcnic_set_vlan_config(adapter, &esw_cfg);
784 qlcnic_set_eswitch_port_features(adapter, &esw_cfg); 800 qlcnic_set_eswitch_port_features(adapter, &esw_cfg);
785 801
786 return 0; 802 return 0;
@@ -1728,26 +1744,13 @@ qlcnic_tso_check(struct net_device *netdev,
1728{ 1744{
1729 u8 opcode = TX_ETHER_PKT; 1745 u8 opcode = TX_ETHER_PKT;
1730 __be16 protocol = skb->protocol; 1746 __be16 protocol = skb->protocol;
1731 u16 flags = 0, vid = 0; 1747 u16 flags = 0;
1732 int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; 1748 int copied, offset, copy_len, hdr_len = 0, tso = 0;
1733 struct cmd_desc_type0 *hwdesc; 1749 struct cmd_desc_type0 *hwdesc;
1734 struct vlan_ethhdr *vh; 1750 struct vlan_ethhdr *vh;
1735 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1751 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1736 u32 producer = tx_ring->producer; 1752 u32 producer = tx_ring->producer;
1737 1753 int vlan_oob = first_desc->flags_opcode & cpu_to_le16(FLAGS_VLAN_OOB);
1738 if (protocol == cpu_to_be16(ETH_P_8021Q)) {
1739
1740 vh = (struct vlan_ethhdr *)skb->data;
1741 protocol = vh->h_vlan_encapsulated_proto;
1742 flags = FLAGS_VLAN_TAGGED;
1743
1744 } else if (vlan_tx_tag_present(skb)) {
1745
1746 flags = FLAGS_VLAN_OOB;
1747 vid = vlan_tx_tag_get(skb);
1748 qlcnic_set_tx_vlan_tci(first_desc, vid);
1749 vlan_oob = 1;
1750 }
1751 1754
1752 if (*(skb->data) & BIT_0) { 1755 if (*(skb->data) & BIT_0) {
1753 flags |= BIT_0; 1756 flags |= BIT_0;
@@ -1818,7 +1821,7 @@ qlcnic_tso_check(struct net_device *netdev,
1818 vh = (struct vlan_ethhdr *)((char *)hwdesc + 2); 1821 vh = (struct vlan_ethhdr *)((char *)hwdesc + 2);
1819 skb_copy_from_linear_data(skb, vh, 12); 1822 skb_copy_from_linear_data(skb, vh, 12);
1820 vh->h_vlan_proto = htons(ETH_P_8021Q); 1823 vh->h_vlan_proto = htons(ETH_P_8021Q);
1821 vh->h_vlan_TCI = htons(vid); 1824 vh->h_vlan_TCI = htons(first_desc->vlan_TCI);
1822 skb_copy_from_linear_data_offset(skb, 12, 1825 skb_copy_from_linear_data_offset(skb, 12,
1823 (char *)vh + 16, copy_len - 16); 1826 (char *)vh + 16, copy_len - 16);
1824 1827
@@ -1898,11 +1901,47 @@ out_err:
1898 return -ENOMEM; 1901 return -ENOMEM;
1899} 1902}
1900 1903
1904static int
1905qlcnic_check_tx_tagging(struct qlcnic_adapter *adapter,
1906 struct sk_buff *skb,
1907 struct cmd_desc_type0 *first_desc)
1908{
1909 u8 opcode = 0;
1910 u16 flags = 0;
1911 __be16 protocol = skb->protocol;
1912 struct vlan_ethhdr *vh;
1913
1914 if (protocol == cpu_to_be16(ETH_P_8021Q)) {
1915 vh = (struct vlan_ethhdr *)skb->data;
1916 protocol = vh->h_vlan_encapsulated_proto;
1917 flags = FLAGS_VLAN_TAGGED;
1918 qlcnic_set_tx_vlan_tci(first_desc, ntohs(vh->h_vlan_TCI));
1919 } else if (vlan_tx_tag_present(skb)) {
1920 flags = FLAGS_VLAN_OOB;
1921 qlcnic_set_tx_vlan_tci(first_desc, vlan_tx_tag_get(skb));
1922 }
1923 if (unlikely(adapter->pvid)) {
1924 if (first_desc->vlan_TCI &&
1925 !(adapter->flags & QLCNIC_TAGGING_ENABLED))
1926 return -EIO;
1927 if (first_desc->vlan_TCI &&
1928 (adapter->flags & QLCNIC_TAGGING_ENABLED))
1929 goto set_flags;
1930
1931 flags = FLAGS_VLAN_OOB;
1932 qlcnic_set_tx_vlan_tci(first_desc, adapter->pvid);
1933 }
1934set_flags:
1935 qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
1936 return 0;
1937}
1938
1901static inline void 1939static inline void
1902qlcnic_clear_cmddesc(u64 *desc) 1940qlcnic_clear_cmddesc(u64 *desc)
1903{ 1941{
1904 desc[0] = 0ULL; 1942 desc[0] = 0ULL;
1905 desc[2] = 0ULL; 1943 desc[2] = 0ULL;
1944 desc[7] = 0ULL;
1906} 1945}
1907 1946
1908netdev_tx_t 1947netdev_tx_t
@@ -1952,6 +1991,12 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1952 1991
1953 pdev = adapter->pdev; 1992 pdev = adapter->pdev;
1954 1993
1994 first_desc = hwdesc = &tx_ring->desc_head[producer];
1995 qlcnic_clear_cmddesc((u64 *)hwdesc);
1996
1997 if (qlcnic_check_tx_tagging(adapter, skb, first_desc))
1998 goto drop_packet;
1999
1955 if (qlcnic_map_tx_skb(pdev, skb, pbuf)) { 2000 if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
1956 adapter->stats.tx_dma_map_error++; 2001 adapter->stats.tx_dma_map_error++;
1957 goto drop_packet; 2002 goto drop_packet;
@@ -1960,9 +2005,6 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1960 pbuf->skb = skb; 2005 pbuf->skb = skb;
1961 pbuf->frag_count = frag_count; 2006 pbuf->frag_count = frag_count;
1962 2007
1963 first_desc = hwdesc = &tx_ring->desc_head[producer];
1964 qlcnic_clear_cmddesc((u64 *)hwdesc);
1965
1966 qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len); 2008 qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
1967 qlcnic_set_tx_port(first_desc, adapter->portnum); 2009 qlcnic_set_tx_port(first_desc, adapter->portnum);
1968 2010
@@ -3349,6 +3391,13 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
3349 case QLCNIC_PORT_DEFAULTS: 3391 case QLCNIC_PORT_DEFAULTS:
3350 qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); 3392 qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
3351 break; 3393 break;
3394 case QLCNIC_ADD_VLAN:
3395 qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
3396 break;
3397 case QLCNIC_DEL_VLAN:
3398 esw_cfg[i].vlan_id = 0;
3399 qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
3400 break;
3352 } 3401 }
3353 } 3402 }
3354 3403