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 (GMT)
committerDavid S. Miller <davem@davemloft.net>2010-08-25 21:15:27 (GMT)
commit8cf61f890ac4c2a15acb24658feba13c9c838b52 (patch)
tree35a476615af3563c56b7ca3022b44fb194010944 /drivers/net/qlcnic/qlcnic_init.c
parente9a47700cb35bc84d4954f762a193b150722612e (diff)
downloadlinux-fsl-qoriq-8cf61f890ac4c2a15acb24658feba13c9c838b52.tar.xz
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 a174521..df91b75 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;