be2net: refactor multi-channel config code for Skyhawk-R chip
authorVasundhara Volam <vasundhara.volam@emulex.com>
Wed, 12 Feb 2014 10:39:25 +0000 (16:09 +0530)
committerDavid S. Miller <davem@davemloft.net>
Thu, 13 Feb 2014 23:19:22 +0000 (18:19 -0500)
Currently multi-channel configuration is read via the QUERY_FW_CONFIG cmd.
This method has been deprecated by the Skyhawk-R FW. Instead,
GET_PROFILE_CONFIG::port-desc must be used to query this configuration.

This patch also:
a) introduces a few macros to identify certain categories of multi-channel
configs
2) re-factors the be_cmd_set_profile_config() code to be able to read any kind
of desc (and not just the nic-desc.)

Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c

index 6c05f57eca2f2433b5f633b13e0e802768794fc8..a150401a6cb3c6240c932135c1fc8aa855489cbb 100644 (file)
@@ -88,7 +88,6 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE_MIN_MTU             256
 
 #define BE_NUM_VLANS_SUPPORTED 64
-#define BE_UMC_NUM_VLANS_SUPPORTED     15
 #define BE_MAX_EQD             128u
 #define        BE_MAX_TX_FRAG_COUNT    30
 
@@ -293,7 +292,7 @@ struct be_rx_compl_info {
        u8 ip_csum;
        u8 l4_csum;
        u8 ipv6;
-       u8 vtm;
+       u8 qnq;
        u8 pkt_type;
        u8 ip_frag;
 };
@@ -465,6 +464,7 @@ struct be_adapter {
 
        u32 port_num;
        bool promiscuous;
+       u8 mc_type;
        u32 function_mode;
        u32 function_caps;
        u32 rx_fc;              /* Rx flow control */
@@ -534,6 +534,14 @@ static inline u16 be_max_qs(struct be_adapter *adapter)
        return min_t(u16, num, num_online_cpus());
 }
 
+/* Is BE in pvid_tagging mode */
+#define be_pvid_tagging_enabled(adapter)       (adapter->pvid)
+
+/* Is BE in QNQ multi-channel mode */
+#define be_is_qnq_mode(adapter)                (adapter->mc_type == FLEX10 ||  \
+                                        adapter->mc_type == vNIC1 ||   \
+                                        adapter->mc_type == UFP)
+
 #define lancer_chip(adapter)   (adapter->pdev->device == OC_DEVICE_ID3 || \
                                 adapter->pdev->device == OC_DEVICE_ID4)
 
index a8106b3644dd1f51f50045c59f57bba664f9e156..72bde5d1c3581c83b8f010a43af0b3cd539db353 100644 (file)
@@ -3296,6 +3296,21 @@ static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf,
        return NULL;
 }
 
+static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
+{
+       struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
+       int i;
+
+       for (i = 0; i < desc_count; i++) {
+               if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
+                       return (struct be_port_res_desc *)hdr;
+
+               hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
+               hdr = (void *)hdr + hdr->desc_len;
+       }
+       return NULL;
+}
+
 static void be_copy_nic_desc(struct be_resources *res,
                             struct be_nic_res_desc *desc)
 {
@@ -3439,6 +3454,7 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
 {
        struct be_cmd_resp_get_profile_config *resp;
        struct be_pcie_res_desc *pcie;
+       struct be_port_res_desc *port;
        struct be_nic_res_desc *nic;
        struct be_queue_info *mccq = &adapter->mcc_obj.q;
        struct be_dma_mem cmd;
@@ -3466,6 +3482,10 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
        if (pcie)
                res->max_vfs = le16_to_cpu(pcie->num_vfs);
 
+       port = be_get_port_desc(resp->func_param, desc_count);
+       if (port)
+               adapter->mc_type = port->mc_type;
+
        nic = be_get_nic_desc(resp->func_param, desc_count);
        if (nic)
                be_copy_nic_desc(res, nic);
index 39595667598b904434f9ecd921c6107138607ded..d0ab980f77ead8e0cb34ab2f04ba76648db4c00b 100644 (file)
@@ -1098,14 +1098,6 @@ struct be_cmd_resp_query_fw_cfg {
        u32 function_caps;
 };
 
-/* Is BE in a multi-channel mode */
-static inline bool be_is_mc(struct be_adapter *adapter)
-{
-       return adapter->function_mode & FLEX10_MODE ||
-               adapter->function_mode & VNIC_MODE ||
-               adapter->function_mode & UMC_ENABLED;
-}
-
 /******************** RSS Config ****************************************/
 /* RSS type            Input parameters used to compute RX hash
  * RSS_ENABLE_IPV4     SRC IPv4, DST IPv4
@@ -1828,6 +1820,7 @@ struct be_cmd_req_set_ext_fat_caps {
 #define NIC_RESOURCE_DESC_TYPE_V0              0x41
 #define PCIE_RESOURCE_DESC_TYPE_V1             0x50
 #define NIC_RESOURCE_DESC_TYPE_V1              0x51
+#define PORT_RESOURCE_DESC_TYPE_V1             0x55
 #define MAX_RESOURCE_DESC                      264
 
 /* QOS unit number */
@@ -1891,6 +1884,33 @@ struct be_nic_res_desc {
        u32 rsvd8[7];
 } __packed;
 
+/************ Multi-Channel type ***********/
+enum mc_type {
+       MC_NONE = 0x01,
+       UMC = 0x02,
+       FLEX10 = 0x03,
+       vNIC1 = 0x04,
+       nPAR = 0x05,
+       UFP = 0x06,
+       vNIC2 = 0x07
+};
+
+struct be_port_res_desc {
+       struct be_res_desc_hdr hdr;
+       u8 rsvd0;
+       u8 flags;
+       u8 rsvd1;
+       u8 mc_type;
+       u16 rsvd2;
+       u32 rsvd3[20];
+} __packed;
+
+/* Is BE in a multi-channel mode */
+static inline bool be_is_mc(struct be_adapter *adapter)
+{
+       return adapter->mc_type > MC_NONE;
+}
+
 struct be_cmd_req_get_func_config {
        struct be_cmd_req_hdr hdr;
 };
index effa272a62c787e5b2913e9404783af0e85758b9..28ac8dd0beaab35b178b9e6c911c823d421b8613 100644 (file)
@@ -368,7 +368,7 @@ struct amap_eth_rx_compl_v0 {
        u8 numfrags[3];         /* dword 1 */
        u8 rss_flush;           /* dword 2 */
        u8 cast_enc[2];         /* dword 2 */
-       u8 vtm;                 /* dword 2 */
+       u8 qnq;                 /* dword 2 */
        u8 rss_bank;            /* dword 2 */
        u8 rsvd1[23];           /* dword 2 */
        u8 lro_pkt;             /* dword 2 */
@@ -401,7 +401,7 @@ struct amap_eth_rx_compl_v1 {
        u8 numfrags[3];         /* dword 1 */
        u8 rss_flush;           /* dword 2 */
        u8 cast_enc[2];         /* dword 2 */
-       u8 vtm;                 /* dword 2 */
+       u8 qnq;                 /* dword 2 */
        u8 rss_bank;            /* dword 2 */
        u8 port[2];             /* dword 2 */
        u8 vntagp;              /* dword 2 */
index 816d67b203c0c12cd2fdd7ee316396ea3539dd23..a8cf03ed2de6e6e977a2f4de91e979073c019c17 100644 (file)
@@ -945,9 +945,9 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
        }
 
        /* If vlan tag is already inlined in the packet, skip HW VLAN
-        * tagging in UMC mode
+        * tagging in pvid-tagging mode
         */
-       if ((adapter->function_mode & UMC_ENABLED) &&
+       if (be_pvid_tagging_enabled(adapter) &&
            veh->h_vlan_proto == htons(ETH_P_8021Q))
                        *skip_hw_vlan = true;
 
@@ -1660,7 +1660,7 @@ static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl,
        rxcp->rss_hash =
                AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, compl);
        if (rxcp->vlanf) {
-               rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm,
+               rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, qnq,
                                          compl);
                rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag,
                                               compl);
@@ -1690,7 +1690,7 @@ static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl,
        rxcp->rss_hash =
                AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, compl);
        if (rxcp->vlanf) {
-               rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm,
+               rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, qnq,
                                          compl);
                rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag,
                                               compl);
@@ -1723,9 +1723,11 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
                rxcp->l4_csum = 0;
 
        if (rxcp->vlanf) {
-               /* vlanf could be wrongly set in some cards.
-                * ignore if vtm is not set */
-               if ((adapter->function_mode & FLEX10_MODE) && !rxcp->vtm)
+               /* In QNQ modes, if qnq bit is not set, then the packet was
+                * tagged only with the transparent outer vlan-tag and must
+                * not be treated as a vlan packet by host
+                */
+               if (be_is_qnq_mode(adapter) && !rxcp->qnq)
                        rxcp->vlanf = 0;
 
                if (!lancer_chip(adapter))
@@ -3109,6 +3111,22 @@ err:
        return status;
 }
 
+/* Converting function_mode bits on BE3 to SH mc_type enums */
+
+static u8 be_convert_mc_type(u32 function_mode)
+{
+       if (function_mode & VNIC_MODE && function_mode & FLEX10_MODE)
+               return vNIC1;
+       else if (function_mode & FLEX10_MODE)
+               return FLEX10;
+       else if (function_mode & VNIC_MODE)
+               return vNIC2;
+       else if (function_mode & UMC_ENABLED)
+               return UMC;
+       else
+               return MC_NONE;
+}
+
 /* On BE2/BE3 FW does not suggest the supported limits */
 static void BEx_get_resources(struct be_adapter *adapter,
                              struct be_resources *res)
@@ -3129,12 +3147,23 @@ static void BEx_get_resources(struct be_adapter *adapter,
        else
                res->max_uc_mac = BE_VF_UC_PMAC_COUNT;
 
-       if (adapter->function_mode & FLEX10_MODE)
-               res->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
-       else if (adapter->function_mode & UMC_ENABLED)
-               res->max_vlans = BE_UMC_NUM_VLANS_SUPPORTED;
-       else
+       adapter->mc_type = be_convert_mc_type(adapter->function_mode);
+
+       if (be_is_mc(adapter)) {
+               /* Assuming that there are 4 channels per port,
+                * when multi-channel is enabled
+                */
+               if (be_is_qnq_mode(adapter))
+                       res->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
+               else
+                       /* In a non-qnq multichannel mode, the pvid
+                        * takes up one vlan entry
+                        */
+                       res->max_vlans = (BE_NUM_VLANS_SUPPORTED / 4) - 1;
+       } else {
                res->max_vlans = BE_NUM_VLANS_SUPPORTED;
+       }
+
        res->max_mcast_mac = BE_MAX_MC;
 
        /* For BE3 1Gb ports, F/W does not properly support multiple TXQs */
@@ -4417,14 +4446,32 @@ static bool be_reset_required(struct be_adapter *adapter)
 
 static char *mc_name(struct be_adapter *adapter)
 {
-       if (adapter->function_mode & FLEX10_MODE)
-               return "FLEX10";
-       else if (adapter->function_mode & VNIC_MODE)
-               return "vNIC";
-       else if (adapter->function_mode & UMC_ENABLED)
-               return "UMC";
-       else
-               return "";
+       char *str = ""; /* default */
+
+       switch (adapter->mc_type) {
+       case UMC:
+               str = "UMC";
+               break;
+       case FLEX10:
+               str = "FLEX10";
+               break;
+       case vNIC1:
+               str = "vNIC-1";
+               break;
+       case nPAR:
+               str = "nPAR";
+               break;
+       case UFP:
+               str = "UFP";
+               break;
+       case vNIC2:
+               str = "vNIC-2";
+               break;
+       default:
+               str = "";
+       }
+
+       return str;
 }
 
 static inline char *func_name(struct be_adapter *adapter)