summaryrefslogtreecommitdiff
path: root/drivers/net/qlcnic/qlcnic_init.c
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2010-08-25 04:03:03 +0000
committerDavid S. Miller <davem@davemloft.net>2010-08-25 14:15:27 -0700
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 @@
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/if_vlan.h>
#include "qlcnic.h"
struct crb_addr_pair {
@@ -1302,6 +1303,27 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
return skb;
}
+static int
+qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb)
+{
+ u16 vlan_tag;
+ struct ethhdr *eth_hdr;
+
+ if (!__vlan_get_tag(skb, &vlan_tag)) {
+ if (vlan_tag == adapter->pvid) {
+ /* strip the tag from the packet and send it up */
+ eth_hdr = (struct ethhdr *) skb->data;
+ memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
+ skb_pull(skb, VLAN_HLEN);
+ return 0;
+ }
+ }
+ if (adapter->flags & QLCNIC_TAGGING_ENABLED)
+ return 0;
+
+ return -EIO;
+}
+
static struct qlcnic_rx_buffer *
qlcnic_process_rcv(struct qlcnic_adapter *adapter,
struct qlcnic_host_sds_ring *sds_ring,
@@ -1342,6 +1364,15 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter,
skb_pull(skb, pkt_offset);
skb->truesize = skb->len + sizeof(struct sk_buff);
+
+ if (unlikely(adapter->pvid)) {
+ if (qlcnic_check_rx_tagging(adapter, skb)) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb_any(skb);
+ return buffer;
+ }
+ }
+
skb->protocol = eth_type_trans(skb, netdev);
napi_gro_receive(&sds_ring->napi, skb);
@@ -1406,6 +1437,14 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb);
skb_pull(skb, l2_hdr_offset);
+
+ if (unlikely(adapter->pvid)) {
+ if (qlcnic_check_rx_tagging(adapter, skb)) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb_any(skb);
+ return buffer;
+ }
+ }
skb->protocol = eth_type_trans(skb, netdev);
iph = (struct iphdr *)skb->data;