aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c78
1 files changed, 76 insertions, 2 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index d712d0ddd719..54e0427a9ee6 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -251,6 +251,9 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
bnx2x_add_tlv(bp, req, req->first_tlv.tl.length,
CHANNEL_TLV_PHYS_PORT_ID, sizeof(struct channel_tlv));
+ /* Bulletin support for bulletin board with length > legacy length */
+ req->vfdev_info.caps |= VF_CAP_SUPPORT_EXT_BULLETIN;
+
/* add list termination tlv */
bnx2x_add_tlv(bp, req,
req->first_tlv.tl.length + sizeof(struct channel_tlv),
@@ -1232,6 +1235,41 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
bnx2x_vf_mbx_resp_send_msg(bp, vf, vfop_status);
}
+static bool bnx2x_vf_mbx_is_windows_vm(struct bnx2x *bp,
+ struct vfpf_acquire_tlv *acquire)
+{
+ /* Windows driver does one of three things:
+ * 1. Old driver doesn't have bulletin board address set.
+ * 2. 'Middle' driver sends mc_num == 32.
+ * 3. New driver sets the OS field.
+ */
+ if (!acquire->bulletin_addr ||
+ acquire->resc_request.num_mc_filters == 32 ||
+ ((acquire->vfdev_info.vf_os & VF_OS_MASK) ==
+ VF_OS_WINDOWS))
+ return true;
+
+ return false;
+}
+
+static int bnx2x_vf_mbx_acquire_chk_dorq(struct bnx2x *bp,
+ struct bnx2x_virtf *vf,
+ struct bnx2x_vf_mbx *mbx)
+{
+ /* Linux drivers which correctly set the doorbell size also
+ * send a physical port request
+ */
+ if (bnx2x_search_tlv_list(bp, &mbx->msg->req,
+ CHANNEL_TLV_PHYS_PORT_ID))
+ return 0;
+
+ /* Issue does not exist in windows VMs */
+ if (bnx2x_vf_mbx_is_windows_vm(bp, &mbx->msg->req.acquire))
+ return 0;
+
+ return -EOPNOTSUPP;
+}
+
static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
struct bnx2x_vf_mbx *mbx)
{
@@ -1247,12 +1285,32 @@ static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
acquire->resc_request.num_vlan_filters,
acquire->resc_request.num_mc_filters);
+ /* Prevent VFs with old drivers from loading, since they calculate
+ * CIDs incorrectly requiring a VF-flr [VM reboot] in order to recover
+ * while being upgraded.
+ */
+ rc = bnx2x_vf_mbx_acquire_chk_dorq(bp, vf, mbx);
+ if (rc) {
+ DP(BNX2X_MSG_IOV,
+ "VF [%d] - Can't support acquire request due to doorbell mismatch. Please update VM driver\n",
+ vf->abs_vfid);
+ goto out;
+ }
+
/* acquire the resources */
rc = bnx2x_vf_acquire(bp, vf, &acquire->resc_request);
/* store address of vf's bulletin board */
vf->bulletin_map = acquire->bulletin_addr;
+ if (acquire->vfdev_info.caps & VF_CAP_SUPPORT_EXT_BULLETIN) {
+ DP(BNX2X_MSG_IOV, "VF[%d] supports long bulletin boards\n",
+ vf->abs_vfid);
+ vf->cfg_flags |= VF_CFG_EXT_BULLETIN;
+ } else {
+ vf->cfg_flags &= ~VF_CFG_EXT_BULLETIN;
+ }
+out:
/* response */
bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc);
}
@@ -1273,6 +1331,10 @@ static void bnx2x_vf_mbx_init_vf(struct bnx2x *bp, struct bnx2x_virtf *vf,
if (init->flags & VFPF_INIT_FLG_STATS_COALESCE)
vf->cfg_flags |= VF_CFG_STATS_COALESCE;
+ /* Update VF's view of link state */
+ if (vf->cfg_flags & VF_CFG_EXT_BULLETIN)
+ bnx2x_iov_link_update_vf(bp, vf->index);
+
/* response */
bnx2x_vf_mbx_resp(bp, vf, rc);
}
@@ -2007,6 +2069,17 @@ void bnx2x_vf_mbx(struct bnx2x *bp)
}
}
+void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
+ bool support_long)
+{
+ /* Older VFs contain a bug where they can't check CRC for bulletin
+ * boards of length greater than legacy size.
+ */
+ bulletin->length = support_long ? BULLETIN_CONTENT_SIZE :
+ BULLETIN_CONTENT_LEGACY_SIZE;
+ bulletin->crc = bnx2x_crc_vf_bulletin(bulletin);
+}
+
/* propagate local bulletin board to vf */
int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf)
{
@@ -2023,8 +2096,9 @@ int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf)
/* increment bulletin board version and compute crc */
bulletin->version++;
- bulletin->length = BULLETIN_CONTENT_SIZE;
- bulletin->crc = bnx2x_crc_vf_bulletin(bp, bulletin);
+ bnx2x_vf_bulletin_finalize(bulletin,
+ (bnx2x_vf(bp, vf, cfg_flags) &
+ VF_CFG_EXT_BULLETIN) ? true : false);
/* propagate bulletin board via dmae to vm memory */
rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr,