bnx2x: Use correct fastpath version for VFs.
authorYuval Mintz <Yuval.Mintz@qlogic.com>
Thu, 4 Dec 2014 10:52:06 +0000 (12:52 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 9 Dec 2014 19:29:10 +0000 (14:29 -0500)
Our FW can support several fastpath HSI [for backward compatibility] but up
until now VFs were always configured to use latest fastpath HSI [although VF
driver might be older and use an older fastpath HSI].

For linux drivers, the differences are insignificant since driver never
utilized features that were overridden by the HSI change. But for VMs running
other operating systems this might be a problem.
In addition, eventually FW might change fastpath HSI in such a manner that
backward compatibility WILL break unless configured with proper version.

This patch fixes the issue for other operating system VMs, as well as lays
the ground work for forward compatibility in regard to the fastpath HSI.

Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h

index 336ef3cf5773daa938cea79c92e6aa737f0a753b..07c6368151279dfc66e09f91a5f46ab2babfbad1 100644 (file)
@@ -3163,6 +3163,8 @@ static void bnx2x_pf_q_prep_general(struct bnx2x *bp,
                gen_init->mtu = bp->dev->mtu;
 
        gen_init->cos = cos;
+
+       gen_init->fp_hsi = ETH_FP_HSI_VERSION;
 }
 
 static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
index 7bc2924a7e24f071d6f39adfed574dff7c2af71a..07cdf9bbffef2ee85ff3d589f33c1a10aea405d5 100644 (file)
@@ -4336,7 +4336,7 @@ static void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
                test_bit(BNX2X_Q_FLG_FCOE, flags) ?
                LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
 
-       gen_data->fp_hsi_ver = ETH_FP_HSI_VERSION;
+       gen_data->fp_hsi_ver = params->fp_hsi;
 
        DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d\n",
           gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
index e97275f456c0ae789ab3e628482d73ccf2dd949c..86baecb7c60c41a3cf096ad884efe674fb9221b3 100644 (file)
@@ -937,6 +937,8 @@ struct bnx2x_general_setup_params {
        u8              spcl_id;
        u16             mtu;
        u8              cos;
+
+       u8              fp_hsi;
 };
 
 struct bnx2x_rxq_setup_params {
index c88b20af87dff2e6613215520eeff5920b438b0f..e5aca2de1871350f3e47a788c4360b461c02a039 100644 (file)
@@ -193,6 +193,7 @@ void bnx2x_vfop_qctor_prep(struct bnx2x *bp,
        /* Setup-op general parameters */
        setup_p->gen_params.spcl_id = vf->sp_cl_id;
        setup_p->gen_params.stat_id = vfq_stat_id(vf, q);
+       setup_p->gen_params.fp_hsi = vf->fp_hsi;
 
        /* Setup-op pause params:
         * Nothing to do, the pause thresholds are set by default to 0 which
index 01bafa4ac04589364ef092e2bd5a31231e42a5f7..66ee62a0401a86c9e44db1afdb9ebac0b7ebf49e 100644 (file)
@@ -205,6 +205,8 @@ struct bnx2x_virtf {
        /* slow-path operations */
        struct mutex                    op_mutex; /* one vfop at a time mutex */
        enum channel_tlvs               op_current;
+
+       u8 fp_hsi;
 };
 
 #define BNX2X_NR_VIRTFN(bp)    ((bp)->vfdb->sriov.nr_virtfn)
index b1d9c44aa56c919732721207d88163cda8080a53..be40eabc5304dad9e1ded4451b65b4dae6a03ae8 100644 (file)
@@ -224,6 +224,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
        struct vfpf_acquire_tlv *req = &bp->vf2pf_mbox->req.acquire;
        struct pfvf_acquire_resp_tlv *resp = &bp->vf2pf_mbox->resp.acquire_resp;
        struct vfpf_port_phys_id_resp_tlv *phys_port_resp;
+       struct vfpf_fp_hsi_resp_tlv *fp_hsi_resp;
        u32 vf_id;
        bool resources_acquired = false;
 
@@ -237,6 +238,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
 
        req->vfdev_info.vf_id = vf_id;
        req->vfdev_info.vf_os = 0;
+       req->vfdev_info.fp_hsi_ver = ETH_FP_HSI_VERSION;
 
        req->resc_request.num_rxqs = rx_count;
        req->resc_request.num_txqs = tx_count;
@@ -316,9 +318,14 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
                        memset(&bp->vf2pf_mbox->resp, 0,
                               sizeof(union pfvf_tlvs));
                } else {
-                       /* PF reports error */
-                       BNX2X_ERR("Failed to get the requested amount of resources: %d. Breaking...\n",
-                                 bp->acquire_resp.hdr.status);
+                       /* Determine reason of PF failure of acquire process */
+                       fp_hsi_resp = bnx2x_search_tlv_list(bp, resp,
+                                                           CHANNEL_TLV_FP_HSI_SUPPORT);
+                       if (fp_hsi_resp && !fp_hsi_resp->is_supported)
+                               BNX2X_ERR("Old hypervisor - doesn't support current fastpath HSI version; Need to downgrade VF driver [or upgrade hypervisor]\n");
+                       else
+                               BNX2X_ERR("Failed to get the requested amount of resources: %d. Breaking...\n",
+                                         bp->acquire_resp.hdr.status);
                        rc = -EAGAIN;
                        goto out;
                }
@@ -333,6 +340,25 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
                bp->flags |= HAS_PHYS_PORT_ID;
        }
 
+       /* Old Hypevisors might not even support the FP_HSI_SUPPORT TLV.
+        * If that's the case, we need to make certain required FW was
+        * supported by such a hypervisor [i.e., v0-v2].
+        */
+       fp_hsi_resp = bnx2x_search_tlv_list(bp, resp,
+                                           CHANNEL_TLV_FP_HSI_SUPPORT);
+       if (!fp_hsi_resp && (ETH_FP_HSI_VERSION > ETH_FP_HSI_VER_2)) {
+               BNX2X_ERR("Old hypervisor - need to downgrade VF's driver\n");
+
+               /* Since acquire succeeded on the PF side, we need to send a
+                * release message in order to allow future probes.
+                */
+               bnx2x_vfpf_finalize(bp, &req->first_tlv);
+               bnx2x_vfpf_release(bp);
+
+               rc = -EINVAL;
+               goto out;
+       }
+
        /* get HW info */
        bp->common.chip_id |= (bp->acquire_resp.pfdev_info.chip_num & 0xffff);
        bp->link_params.chip_id = bp->common.chip_id;
@@ -1125,6 +1151,26 @@ static void bnx2x_vf_mbx_resp_phys_port(struct bnx2x *bp,
        *offset += sizeof(struct vfpf_port_phys_id_resp_tlv);
 }
 
+static void bnx2x_vf_mbx_resp_fp_hsi_ver(struct bnx2x *bp,
+                                        struct bnx2x_virtf *vf,
+                                        void *buffer,
+                                        u16 *offset)
+{
+       struct vfpf_fp_hsi_resp_tlv *fp_hsi;
+
+       bnx2x_add_tlv(bp, buffer, *offset, CHANNEL_TLV_FP_HSI_SUPPORT,
+                     sizeof(struct vfpf_fp_hsi_resp_tlv));
+
+       fp_hsi = (struct vfpf_fp_hsi_resp_tlv *)
+                (((u8 *)buffer) + *offset);
+       fp_hsi->is_supported = (vf->fp_hsi > ETH_FP_HSI_VERSION) ? 0 : 1;
+
+       /* Offset should continue representing the offset to the tail
+        * of TLV data (outside this function scope)
+        */
+       *offset += sizeof(struct vfpf_fp_hsi_resp_tlv);
+}
+
 static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
                                      struct bnx2x_vf_mbx *mbx, int vfop_status)
 {
@@ -1219,6 +1265,12 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
                                  CHANNEL_TLV_PHYS_PORT_ID))
                bnx2x_vf_mbx_resp_phys_port(bp, vf, &mbx->msg->resp, &length);
 
+       /* `New' vfs will want to know if fastpath HSI is supported, since
+        * if that's not the case they could print into system log the fact
+        * the driver version must be updated.
+        */
+       bnx2x_vf_mbx_resp_fp_hsi_ver(bp, vf, &mbx->msg->resp, &length);
+
        bnx2x_add_tlv(bp, &mbx->msg->resp, length, CHANNEL_TLV_LIST_END,
                      sizeof(struct channel_list_end_tlv));
 
@@ -1288,6 +1340,23 @@ static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
                goto out;
        }
 
+       /* Verify the VF fastpath HSI can be supported by the loaded FW.
+        * Linux vfs should be oblivious to changes between v0 and v2.
+        */
+       if (bnx2x_vf_mbx_is_windows_vm(bp, &mbx->msg->req.acquire))
+               vf->fp_hsi = acquire->vfdev_info.fp_hsi_ver;
+       else
+               vf->fp_hsi = max_t(u8, acquire->vfdev_info.fp_hsi_ver,
+                                  ETH_FP_HSI_VER_2);
+       if (vf->fp_hsi > ETH_FP_HSI_VERSION) {
+               DP(BNX2X_MSG_IOV,
+                  "VF [%d] - Can't support acquire request since VF requests a FW version which is too new [%02x > %02x]\n",
+                  vf->abs_vfid, acquire->vfdev_info.fp_hsi_ver,
+                  ETH_FP_HSI_VERSION);
+               rc = -EINVAL;
+               goto out;
+       }
+
        /* acquire the resources */
        rc = bnx2x_vf_acquire(bp, vf, &acquire->resc_request);
 
index 15670c499a206bc8c7954e95eed1d37fb29f55d1..b86479fc0d2f80adc9a066da4e26ee9b50d80bc9 100644 (file)
@@ -124,7 +124,7 @@ struct vfpf_acquire_tlv {
 #define VF_OS_UNDEFINED                (0 << VF_OS_SHIFT)
 #define VF_OS_WINDOWS          (1 << VF_OS_SHIFT)
 
-               u8 padding;
+               u8 fp_hsi_ver;
                u8 caps;
 #define VF_CAP_SUPPORT_EXT_BULLETIN    (1 << 0)
        } vfdev_info;
@@ -204,6 +204,12 @@ struct vfpf_port_phys_id_resp_tlv {
        u8 padding[2];
 };
 
+struct vfpf_fp_hsi_resp_tlv {
+       struct channel_tlv tl;
+       u8 is_supported;
+       u8 padding[3];
+};
+
 #define VFPF_INIT_FLG_STATS_COALESCE   (1 << 0) /* when set the VFs queues
                                                  * stats will be coalesced on
                                                  * the leading RSS queue
@@ -448,6 +454,7 @@ enum channel_tlvs {
        CHANNEL_TLV_UPDATE_RSS,
        CHANNEL_TLV_PHYS_PORT_ID,
        CHANNEL_TLV_UPDATE_TPA,
+       CHANNEL_TLV_FP_HSI_SUPPORT,
        CHANNEL_TLV_MAX
 };