aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_init.c
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/net/qlcnic/qlcnic_init.c
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/net/qlcnic/qlcnic_init.c')
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c39
1 files changed, 39 insertions, 0 deletions
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;