ibmvnic: Insert header on VLAN tagged received frame
authorMurilo Fossa Vicentini <muvic@linux.vnet.ibm.com>
Fri, 21 Apr 2017 19:38:46 +0000 (15:38 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 24 Apr 2017 16:52:12 +0000 (12:52 -0400)
This patch addresses a modification in the PAPR+ specification which now
defines a previously reserved value for vNIC capabilities. It indicates
whether the system firmware performs a VLAN header stripping on all VLAN
tagged received frames, in case it does, the behavior expected is for
the ibmvnic driver to be responsible for inserting the VLAN header.

Reported-by: Manvanthara B. Puttashankar <mputtash@in.ibm.com>
Signed-off-by: Murilo Fossa Vicentini <muvic@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h

index 7f4cecbb4b5af18c71aab545d0f9348ffa7cf410..0f3595439293853512d6a946cc69f37e858d9889 100644 (file)
@@ -74,6 +74,7 @@
 #include <linux/uaccess.h>
 #include <asm/firmware.h>
 #include <linux/workqueue.h>
+#include <linux/if_vlan.h>
 
 #include "ibmvnic.h"
 
@@ -1105,7 +1106,15 @@ restart_poll:
                skb = rx_buff->skb;
                skb_copy_to_linear_data(skb, rx_buff->data + offset,
                                        length);
-               skb->vlan_tci = be16_to_cpu(next->rx_comp.vlan_tci);
+
+               /* VLAN Header has been stripped by the system firmware and
+                * needs to be inserted by the driver
+                */
+               if (adapter->rx_vlan_header_insertion &&
+                   (flags & IBMVNIC_VLAN_STRIPPED))
+                       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+                                              ntohs(next->rx_comp.vlan_tci));
+
                /* free the entry */
                next->rx_comp.first = 0;
                remove_buff_from_pool(adapter, rx_buff);
@@ -2170,6 +2179,10 @@ static void send_cap_queries(struct ibmvnic_adapter *adapter)
        atomic_inc(&adapter->running_cap_crqs);
        ibmvnic_send_crq(adapter, &crq);
 
+       crq.query_capability.capability = cpu_to_be16(RX_VLAN_HEADER_INSERTION);
+       atomic_inc(&adapter->running_cap_crqs);
+       ibmvnic_send_crq(adapter, &crq);
+
        crq.query_capability.capability = cpu_to_be16(MAX_TX_SG_ENTRIES);
        atomic_inc(&adapter->running_cap_crqs);
        ibmvnic_send_crq(adapter, &crq);
@@ -2719,6 +2732,12 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq,
                netdev_dbg(netdev, "vlan_header_insertion = %lld\n",
                           adapter->vlan_header_insertion);
                break;
+       case RX_VLAN_HEADER_INSERTION:
+               adapter->rx_vlan_header_insertion =
+                   be64_to_cpu(crq->query_capability.number);
+               netdev_dbg(netdev, "rx_vlan_header_insertion = %lld\n",
+                          adapter->rx_vlan_header_insertion);
+               break;
        case MAX_TX_SG_ENTRIES:
                adapter->max_tx_sg_entries =
                    be64_to_cpu(crq->query_capability.number);
index 355225cf6d30be20727dbb5e8ad8c3ac63511ff9..387c84303b7fda9432e17b7ee02d18bc8ce2a58c 100644 (file)
@@ -733,6 +733,7 @@ enum ibmvnic_capabilities {
        REQ_MTU = 21,
        MAX_MULTICAST_FILTERS = 22,
        VLAN_HEADER_INSERTION = 23,
+       RX_VLAN_HEADER_INSERTION = 24,
        MAX_TX_SG_ENTRIES = 25,
        RX_SG_SUPPORTED = 26,
        RX_SG_REQUESTED = 27,
@@ -993,6 +994,7 @@ struct ibmvnic_adapter {
        u64 req_mtu;
        u64 max_multicast_filters;
        u64 vlan_header_insertion;
+       u64 rx_vlan_header_insertion;
        u64 max_tx_sg_entries;
        u64 rx_sg_supported;
        u64 rx_sg_requested;