All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/3] bnx2x: Enhancement patch series
@ 2014-06-26 11:31 Yuval Mintz
  2014-06-26 11:31 ` [PATCH net-next 1/3] bnx2x: VF can report link speed Yuval Mintz
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Yuval Mintz @ 2014-06-26 11:31 UTC (permalink / raw)
  To: davem, netdev; +Cc: Ariel.Elior

Hi Dave,

This patch series introduces the ability to propagate link parameters
to VFs as well as control the VF link via hypervisor.

In addition, it contains 2 small improvements [one IOV-related and the
other improves performance on machines with short cache lines].

Please consider applying these patches to `net-next'.

Thanks,
Yuval Mintz

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH net-next 1/3] bnx2x: VF can report link speed
  2014-06-26 11:31 [PATCH net-next 0/3] bnx2x: Enhancement patch series Yuval Mintz
@ 2014-06-26 11:31 ` Yuval Mintz
  2014-06-26 11:31 ` [PATCH net-next 2/3] bnx2x: enlarge minimal alignemnt of data offset Yuval Mintz
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Yuval Mintz @ 2014-06-26 11:31 UTC (permalink / raw)
  To: davem, netdev; +Cc: Ariel.Elior, Dmitry Kravkov, Yuval Mintz

From: Dmitry Kravkov <Dmitry.Kravkov@qlogic.com>

Until now VFs were oblvious to the actual configured link parameters.
This patch does 2 things:

  1. It enables a PF to inform its VF using the bulletin board of the link
     configured, and allows the VF to present that information.

  2. It adds support of `ndo_set_vf_link_state', allowing the hypervisor
     to set the VF link state.

Signed-off-by: Dmitry Kravkov <Dmitry.Kravkov@qlogic.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h        |   3 +
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c    |  55 +++--
 .../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c    |  44 +++-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   |   9 +
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c  | 261 ++++++++++++++++-----
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h  |  35 ++-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c   |  30 ++-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h   |  17 +-
 8 files changed, 366 insertions(+), 88 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 4cab09d..faf262a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1482,6 +1482,7 @@ struct bnx2x {
 	union pf_vf_bulletin   *pf2vf_bulletin;
 	dma_addr_t		pf2vf_bulletin_mapping;
 
+	union pf_vf_bulletin		shadow_bulletin;
 	struct pf_vf_bulletin_content	old_bulletin;
 
 	u16 requested_nr_virtfn;
@@ -1928,6 +1929,8 @@ struct bnx2x {
 	struct semaphore			stats_sema;
 
 	u8					phys_port_id[ETH_ALEN];
+
+	struct bnx2x_link_report_data		vf_link_vars;
 };
 
 /* Tx queues may be less or equal to Rx queues */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 47c5814..cb15e3a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1185,29 +1185,38 @@ u16 bnx2x_get_mf_speed(struct bnx2x *bp)
 static void bnx2x_fill_report_data(struct bnx2x *bp,
 				   struct bnx2x_link_report_data *data)
 {
-	u16 line_speed = bnx2x_get_mf_speed(bp);
-
 	memset(data, 0, sizeof(*data));
 
-	/* Fill the report data: effective line speed */
-	data->line_speed = line_speed;
-
-	/* Link is down */
-	if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS))
-		__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
-			  &data->link_report_flags);
-
-	/* Full DUPLEX */
-	if (bp->link_vars.duplex == DUPLEX_FULL)
-		__set_bit(BNX2X_LINK_REPORT_FD, &data->link_report_flags);
-
-	/* Rx Flow Control is ON */
-	if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX)
-		__set_bit(BNX2X_LINK_REPORT_RX_FC_ON, &data->link_report_flags);
-
-	/* Tx Flow Control is ON */
-	if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
-		__set_bit(BNX2X_LINK_REPORT_TX_FC_ON, &data->link_report_flags);
+	if (IS_PF(bp)) {
+		/* Fill the report data: effective line speed */
+		data->line_speed = bnx2x_get_mf_speed(bp);
+
+		/* Link is down */
+		if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS))
+			__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+				  &data->link_report_flags);
+
+		if (!BNX2X_NUM_ETH_QUEUES(bp))
+			__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+				  &data->link_report_flags);
+
+		/* Full DUPLEX */
+		if (bp->link_vars.duplex == DUPLEX_FULL)
+			__set_bit(BNX2X_LINK_REPORT_FD,
+				  &data->link_report_flags);
+
+		/* Rx Flow Control is ON */
+		if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX)
+			__set_bit(BNX2X_LINK_REPORT_RX_FC_ON,
+				  &data->link_report_flags);
+
+		/* Tx Flow Control is ON */
+		if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
+			__set_bit(BNX2X_LINK_REPORT_TX_FC_ON,
+				  &data->link_report_flags);
+	} else { /* VF */
+		*data = bp->vf_link_vars;
+	}
 }
 
 /**
@@ -1261,6 +1270,10 @@ void __bnx2x_link_report(struct bnx2x *bp)
 	 */
 	memcpy(&bp->last_reported_link, &cur_data, sizeof(cur_data));
 
+	/* propagate status to VFs */
+	if (IS_PF(bp))
+		bnx2x_iov_link_update(bp);
+
 	if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
 		     &cur_data.link_report_flags)) {
 		netif_carrier_off(bp->dev);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index bd0600c..08ea91c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -216,6 +216,43 @@ static int bnx2x_get_port_type(struct bnx2x *bp)
 	return port_type;
 }
 
+static int bnx2x_get_vf_settings(struct net_device *dev,
+				 struct ethtool_cmd *cmd)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+
+	if (bp->state == BNX2X_STATE_OPEN) {
+		if (test_bit(BNX2X_LINK_REPORT_FD,
+			     &bp->vf_link_vars.link_report_flags))
+			cmd->duplex = DUPLEX_FULL;
+		else
+			cmd->duplex = DUPLEX_HALF;
+
+		ethtool_cmd_speed_set(cmd, bp->vf_link_vars.line_speed);
+	} else {
+		cmd->duplex = DUPLEX_UNKNOWN;
+		ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+	}
+
+	cmd->port		= PORT_OTHER;
+	cmd->phy_address	= 0;
+	cmd->transceiver	= XCVR_INTERNAL;
+	cmd->autoneg		= AUTONEG_DISABLE;
+	cmd->maxtxpkt		= 0;
+	cmd->maxrxpkt		= 0;
+
+	DP(BNX2X_MSG_ETHTOOL, "ethtool_cmd: cmd %d\n"
+	   "  supported 0x%x  advertising 0x%x  speed %u\n"
+	   "  duplex %d  port %d  phy_address %d  transceiver %d\n"
+	   "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
+	   cmd->cmd, cmd->supported, cmd->advertising,
+	   ethtool_cmd_speed(cmd),
+	   cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
+	   cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
+
+	return 0;
+}
+
 static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct bnx2x *bp = netdev_priv(dev);
@@ -1110,6 +1147,10 @@ static u32 bnx2x_get_link(struct net_device *dev)
 	if (bp->flags & MF_FUNC_DIS || (bp->state != BNX2X_STATE_OPEN))
 		return 0;
 
+	if (IS_VF(bp))
+		return !test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+				 &bp->vf_link_vars.link_report_flags);
+
 	return bp->link_vars.link_up;
 }
 
@@ -3484,8 +3525,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
 };
 
 static const struct ethtool_ops bnx2x_vf_ethtool_ops = {
-	.get_settings		= bnx2x_get_settings,
-	.set_settings		= bnx2x_set_settings,
+	.get_settings		= bnx2x_get_vf_settings,
 	.get_drvinfo		= bnx2x_get_drvinfo,
 	.get_msglevel		= bnx2x_get_msglevel,
 	.set_msglevel		= bnx2x_set_msglevel,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 2887034..6af9e3c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -2698,6 +2698,14 @@ void bnx2x__link_status_update(struct bnx2x *bp)
 		bp->link_vars.duplex = DUPLEX_FULL;
 		bp->link_vars.flow_ctrl = BNX2X_FLOW_CTRL_NONE;
 		__bnx2x_link_report(bp);
+
+		bnx2x_sample_bulletin(bp);
+
+		/* if bulletin board did not have an update for link status
+		 * __bnx2x_link_report will report current status
+		 * but it will NOT duplicate report in case of already reported
+		 * during sampling bulletin board.
+		 */
 		bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
 	}
 }
@@ -12424,6 +12432,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
 	.ndo_busy_poll		= bnx2x_low_latency_recv,
 #endif
 	.ndo_get_phys_port_id	= bnx2x_get_phys_port_id,
+	.ndo_set_vf_link_state	= bnx2x_set_vf_link_state,
 };
 
 static int bnx2x_set_coherency_mask(struct bnx2x *bp)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index c9988e3..662310c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -24,6 +24,11 @@
 #include <linux/crc32.h>
 #include <linux/if_vlan.h>
 
+static int bnx2x_vf_op_prep(struct bnx2x *bp, int vfidx,
+			    struct bnx2x_virtf **vf,
+			    struct pf_vf_bulletin_content **bulletin,
+			    bool test_queue);
+
 /* General service functions */
 static void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
 					 u16 pf_id)
@@ -1327,6 +1332,8 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
 	/* Prepare the VFs event synchronization mechanism */
 	mutex_init(&bp->vfdb->event_mutex);
 
+	mutex_init(&bp->vfdb->bulletin_mutex);
+
 	return 0;
 failed:
 	DP(BNX2X_MSG_IOV, "Failed err=%d\n", err);
@@ -1472,6 +1479,107 @@ static void bnx2x_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
 	   vf->abs_vfid, q->sp_obj.func_id, q->cid);
 }
 
+static int bnx2x_max_speed_cap(struct bnx2x *bp)
+{
+	u32 supported = bp->port.supported[bnx2x_get_link_cfg_idx(bp)];
+
+	if (supported &
+	    (SUPPORTED_20000baseMLD2_Full | SUPPORTED_20000baseKR2_Full))
+		return 20000;
+
+	return 10000; /* assume lowest supported speed is 10G */
+}
+
+int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx)
+{
+	struct bnx2x_link_report_data *state = &bp->last_reported_link;
+	struct pf_vf_bulletin_content *bulletin;
+	struct bnx2x_virtf *vf;
+	bool update = true;
+	int rc = 0;
+
+	/* sanity and init */
+	rc = bnx2x_vf_op_prep(bp, idx, &vf, &bulletin, false);
+	if (rc)
+		return rc;
+
+	mutex_lock(&bp->vfdb->bulletin_mutex);
+
+	if (vf->link_cfg == IFLA_VF_LINK_STATE_AUTO) {
+		bulletin->valid_bitmap |= 1 << LINK_VALID;
+
+		bulletin->link_speed = state->line_speed;
+		bulletin->link_flags = 0;
+		if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+			     &state->link_report_flags))
+			bulletin->link_flags |= VFPF_LINK_REPORT_LINK_DOWN;
+		if (test_bit(BNX2X_LINK_REPORT_FD,
+			     &state->link_report_flags))
+			bulletin->link_flags |= VFPF_LINK_REPORT_FULL_DUPLEX;
+		if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON,
+			     &state->link_report_flags))
+			bulletin->link_flags |= VFPF_LINK_REPORT_RX_FC_ON;
+		if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON,
+			     &state->link_report_flags))
+			bulletin->link_flags |= VFPF_LINK_REPORT_TX_FC_ON;
+	} else if (vf->link_cfg == IFLA_VF_LINK_STATE_DISABLE &&
+		   !(bulletin->link_flags & VFPF_LINK_REPORT_LINK_DOWN)) {
+		bulletin->valid_bitmap |= 1 << LINK_VALID;
+		bulletin->link_flags |= VFPF_LINK_REPORT_LINK_DOWN;
+	} else if (vf->link_cfg == IFLA_VF_LINK_STATE_ENABLE &&
+		   (bulletin->link_flags & VFPF_LINK_REPORT_LINK_DOWN)) {
+		bulletin->valid_bitmap |= 1 << LINK_VALID;
+		bulletin->link_speed = bnx2x_max_speed_cap(bp);
+		bulletin->link_flags &= ~VFPF_LINK_REPORT_LINK_DOWN;
+	} else {
+		update = false;
+	}
+
+	if (update) {
+		DP(NETIF_MSG_LINK | BNX2X_MSG_IOV,
+		   "vf %d mode %u speed %d flags %x\n", idx,
+		   vf->link_cfg, bulletin->link_speed, bulletin->link_flags);
+
+		/* Post update on VF's bulletin board */
+		rc = bnx2x_post_vf_bulletin(bp, idx);
+		if (rc) {
+			BNX2X_ERR("failed to update VF[%d] bulletin\n", idx);
+			goto out;
+		}
+	}
+
+out:
+	mutex_unlock(&bp->vfdb->bulletin_mutex);
+	return rc;
+}
+
+int bnx2x_set_vf_link_state(struct net_device *dev, int idx, int link_state)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	struct bnx2x_virtf *vf = BP_VF(bp, idx);
+
+	if (!vf)
+		return -EINVAL;
+
+	if (vf->link_cfg == link_state)
+		return 0; /* nothing todo */
+
+	vf->link_cfg = link_state;
+
+	return bnx2x_iov_link_update_vf(bp, idx);
+}
+
+void bnx2x_iov_link_update(struct bnx2x *bp)
+{
+	int vfid;
+
+	if (!IS_SRIOV(bp))
+		return;
+
+	for_each_vf(bp, vfid)
+		bnx2x_iov_link_update_vf(bp, vfid);
+}
+
 /* called by bnx2x_nic_load */
 int bnx2x_iov_nic_init(struct bnx2x *bp)
 {
@@ -2509,22 +2617,23 @@ void bnx2x_disable_sriov(struct bnx2x *bp)
 	pci_disable_sriov(bp->pdev);
 }
 
-static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
-			     struct bnx2x_virtf **vf,
-			     struct pf_vf_bulletin_content **bulletin)
+static int bnx2x_vf_op_prep(struct bnx2x *bp, int vfidx,
+			    struct bnx2x_virtf **vf,
+			    struct pf_vf_bulletin_content **bulletin,
+			    bool test_queue)
 {
 	if (bp->state != BNX2X_STATE_OPEN) {
-		BNX2X_ERR("vf ndo called though PF is down\n");
+		BNX2X_ERR("PF is down - can't utilize iov-related functionality\n");
 		return -EINVAL;
 	}
 
 	if (!IS_SRIOV(bp)) {
-		BNX2X_ERR("vf ndo called though sriov is disabled\n");
+		BNX2X_ERR("sriov is disabled - can't utilize iov-realted functionality\n");
 		return -EINVAL;
 	}
 
 	if (vfidx >= BNX2X_NR_VIRTFN(bp)) {
-		BNX2X_ERR("vf ndo called for uninitialized VF. vfidx was %d BNX2X_NR_VIRTFN was %d\n",
+		BNX2X_ERR("VF is uninitialized - can't utilize iov-related functionality. vfidx was %d BNX2X_NR_VIRTFN was %d\n",
 			  vfidx, BNX2X_NR_VIRTFN(bp));
 		return -EINVAL;
 	}
@@ -2534,19 +2643,18 @@ static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
 	*bulletin = BP_VF_BULLETIN(bp, vfidx);
 
 	if (!*vf) {
-		BNX2X_ERR("vf ndo called but vf struct is null. vfidx was %d\n",
-			  vfidx);
+		BNX2X_ERR("Unable to get VF structure for vfidx %d\n", vfidx);
 		return -EINVAL;
 	}
 
-	if (!(*vf)->vfqs) {
-		BNX2X_ERR("vf ndo called but vfqs struct is null. Was ndo invoked before dynamically enabling SR-IOV? vfidx was %d\n",
+	if (test_queue && !(*vf)->vfqs) {
+		BNX2X_ERR("vfqs struct is null. Was this invoked before dynamically enabling SR-IOV? vfidx was %d\n",
 			  vfidx);
 		return -EINVAL;
 	}
 
 	if (!*bulletin) {
-		BNX2X_ERR("vf ndo called but Bulletin Board struct is null. vfidx was %d\n",
+		BNX2X_ERR("Bulletin Board struct is null for vfidx %d\n",
 			  vfidx);
 		return -EINVAL;
 	}
@@ -2565,9 +2673,10 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
 	int rc;
 
 	/* sanity and init */
-	rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
+	rc = bnx2x_vf_op_prep(bp, vfidx, &vf, &bulletin, true);
 	if (rc)
 		return rc;
+
 	mac_obj = &bnx2x_leading_vfq(vf, mac_obj);
 	vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
 	if (!mac_obj || !vlan_obj) {
@@ -2590,6 +2699,7 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
 						 VLAN_HLEN);
 		}
 	} else {
+		mutex_lock(&bp->vfdb->bulletin_mutex);
 		/* mac */
 		if (bulletin->valid_bitmap & (1 << MAC_ADDR_VALID))
 			/* mac configured by ndo so its in bulletin board */
@@ -2605,6 +2715,8 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
 		else
 			/* function has not been loaded yet. Show vlans as 0s */
 			memset(&ivi->vlan, 0, VLAN_HLEN);
+
+		mutex_unlock(&bp->vfdb->bulletin_mutex);
 	}
 
 	return 0;
@@ -2634,15 +2746,18 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
 	struct bnx2x_virtf *vf = NULL;
 	struct pf_vf_bulletin_content *bulletin = NULL;
 
-	/* sanity and init */
-	rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
-	if (rc)
-		return rc;
 	if (!is_valid_ether_addr(mac)) {
 		BNX2X_ERR("mac address invalid\n");
 		return -EINVAL;
 	}
 
+	/* sanity and init */
+	rc = bnx2x_vf_op_prep(bp, vfidx, &vf, &bulletin, true);
+	if (rc)
+		return rc;
+
+	mutex_lock(&bp->vfdb->bulletin_mutex);
+
 	/* update PF's copy of the VF's bulletin. Will no longer accept mac
 	 * configuration requests from vf unless match this mac
 	 */
@@ -2651,6 +2766,10 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
 
 	/* Post update on VF's bulletin board */
 	rc = bnx2x_post_vf_bulletin(bp, vfidx);
+
+	/* release lock before checking return code */
+	mutex_unlock(&bp->vfdb->bulletin_mutex);
+
 	if (rc) {
 		BNX2X_ERR("failed to update VF[%d] bulletin\n", vfidx);
 		return rc;
@@ -2715,11 +2834,6 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 	unsigned long accept_flags;
 	int rc;
 
-	/* sanity and init */
-	rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
-	if (rc)
-		return rc;
-
 	if (vlan > 4095) {
 		BNX2X_ERR("illegal vlan value %d\n", vlan);
 		return -EINVAL;
@@ -2728,18 +2842,27 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 	DP(BNX2X_MSG_IOV, "configuring VF %d with VLAN %d qos %d\n",
 	   vfidx, vlan, 0);
 
+	/* sanity and init */
+	rc = bnx2x_vf_op_prep(bp, vfidx, &vf, &bulletin, true);
+	if (rc)
+		return rc;
+
 	/* update PF's copy of the VF's bulletin. No point in posting the vlan
 	 * to the VF since it doesn't have anything to do with it. But it useful
 	 * to store it here in case the VF is not up yet and we can only
 	 * configure the vlan later when it does. Treat vlan id 0 as remove the
 	 * Host tag.
 	 */
+	mutex_lock(&bp->vfdb->bulletin_mutex);
+
 	if (vlan > 0)
 		bulletin->valid_bitmap |= 1 << VLAN_VALID;
 	else
 		bulletin->valid_bitmap &= ~(1 << VLAN_VALID);
 	bulletin->vlan = vlan;
 
+	mutex_unlock(&bp->vfdb->bulletin_mutex);
+
 	/* is vf initialized and queue set up? */
 	if (vf->state != VF_ENABLED ||
 	    bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj)) !=
@@ -2849,10 +2972,9 @@ out:
  * entire bulletin board excluding the crc field itself. Use the length field
  * as the Bulletin Board was posted by a PF with possibly a different version
  * from the vf which will sample it. Therefore, the length is computed by the
- * PF and the used blindly by the VF.
+ * PF and then used blindly by the VF.
  */
-u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
-			  struct pf_vf_bulletin_content *bulletin)
+u32 bnx2x_crc_vf_bulletin(struct pf_vf_bulletin_content *bulletin)
 {
 	return crc32(BULLETIN_CRC_SEED,
 		 ((u8 *)bulletin) + sizeof(bulletin->crc),
@@ -2862,47 +2984,74 @@ u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
 /* Check for new posts on the bulletin board */
 enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
 {
-	struct pf_vf_bulletin_content bulletin = bp->pf2vf_bulletin->content;
+	struct pf_vf_bulletin_content *bulletin;
 	int attempts;
 
-	/* bulletin board hasn't changed since last sample */
-	if (bp->old_bulletin.version == bulletin.version)
-		return PFVF_BULLETIN_UNCHANGED;
+	/* sampling structure in mid post may result with corrupted data
+	 * validate crc to ensure coherency.
+	 */
+	for (attempts = 0; attempts < BULLETIN_ATTEMPTS; attempts++) {
+		u32 crc;
 
-	/* validate crc of new bulletin board */
-	if (bp->old_bulletin.version != bp->pf2vf_bulletin->content.version) {
-		/* sampling structure in mid post may result with corrupted data
-		 * validate crc to ensure coherency.
-		 */
-		for (attempts = 0; attempts < BULLETIN_ATTEMPTS; attempts++) {
-			bulletin = bp->pf2vf_bulletin->content;
-			if (bulletin.crc == bnx2x_crc_vf_bulletin(bp,
-								  &bulletin))
-				break;
-			BNX2X_ERR("bad crc on bulletin board. Contained %x computed %x\n",
-				  bulletin.crc,
-				  bnx2x_crc_vf_bulletin(bp, &bulletin));
-		}
-		if (attempts >= BULLETIN_ATTEMPTS) {
-			BNX2X_ERR("pf to vf bulletin board crc was wrong %d consecutive times. Aborting\n",
-				  attempts);
-			return PFVF_BULLETIN_CRC_ERR;
-		}
+		/* sample the bulletin board */
+		memcpy(&bp->shadow_bulletin, bp->pf2vf_bulletin,
+		       sizeof(union pf_vf_bulletin));
+
+		crc = bnx2x_crc_vf_bulletin(&bp->shadow_bulletin.content);
+
+		if (bp->shadow_bulletin.content.crc == crc)
+			break;
+
+		BNX2X_ERR("bad crc on bulletin board. Contained %x computed %x\n",
+			  bp->shadow_bulletin.content.crc, crc);
+	}
+
+	if (attempts >= BULLETIN_ATTEMPTS) {
+		BNX2X_ERR("pf to vf bulletin board crc was wrong %d consecutive times. Aborting\n",
+			  attempts);
+		return PFVF_BULLETIN_CRC_ERR;
 	}
+	bulletin = &bp->shadow_bulletin.content;
+
+	/* bulletin board hasn't changed since last sample */
+	if (bp->old_bulletin.version == bulletin->version)
+		return PFVF_BULLETIN_UNCHANGED;
 
 	/* the mac address in bulletin board is valid and is new */
-	if (bulletin.valid_bitmap & 1 << MAC_ADDR_VALID &&
-	    !ether_addr_equal(bulletin.mac, bp->old_bulletin.mac)) {
+	if (bulletin->valid_bitmap & 1 << MAC_ADDR_VALID &&
+	    !ether_addr_equal(bulletin->mac, bp->old_bulletin.mac)) {
 		/* update new mac to net device */
-		memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN);
+		memcpy(bp->dev->dev_addr, bulletin->mac, ETH_ALEN);
+	}
+
+	if (bulletin->valid_bitmap & (1 << LINK_VALID)) {
+		DP(BNX2X_MSG_IOV, "link update speed %d flags %x\n",
+		   bulletin->link_speed, bulletin->link_flags);
+
+		bp->vf_link_vars.line_speed = bulletin->link_speed;
+		bp->vf_link_vars.link_report_flags = 0;
+		/* Link is down */
+		if (bulletin->link_flags & VFPF_LINK_REPORT_LINK_DOWN)
+			__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+				  &bp->vf_link_vars.link_report_flags);
+		/* Full DUPLEX */
+		if (bulletin->link_flags & VFPF_LINK_REPORT_FULL_DUPLEX)
+			__set_bit(BNX2X_LINK_REPORT_FD,
+				  &bp->vf_link_vars.link_report_flags);
+		/* Rx Flow Control is ON */
+		if (bulletin->link_flags & VFPF_LINK_REPORT_RX_FC_ON)
+			__set_bit(BNX2X_LINK_REPORT_RX_FC_ON,
+				  &bp->vf_link_vars.link_report_flags);
+		/* Tx Flow Control is ON */
+		if (bulletin->link_flags & VFPF_LINK_REPORT_TX_FC_ON)
+			__set_bit(BNX2X_LINK_REPORT_TX_FC_ON,
+				  &bp->vf_link_vars.link_report_flags);
+		__bnx2x_link_report(bp);
 	}
 
-	/* the vlan in bulletin board is valid and is new */
-	if (bulletin.valid_bitmap & 1 << VLAN_VALID)
-		memcpy(&bulletin.vlan, &bp->old_bulletin.vlan, VLAN_HLEN);
-
 	/* copy new bulletin board to bp */
-	bp->old_bulletin = bulletin;
+	memcpy(&bp->old_bulletin, bulletin,
+	       sizeof(struct pf_vf_bulletin_content));
 
 	return PFVF_BULLETIN_UPDATED;
 }
@@ -2947,6 +3096,8 @@ int bnx2x_vf_pci_alloc(struct bnx2x *bp)
 	if (!bp->pf2vf_bulletin)
 		goto alloc_mem_err;
 
+	bnx2x_vf_bulletin_finalize(&bp->pf2vf_bulletin->content, true);
+
 	return 0;
 
 alloc_mem_err:
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index 96c575e..ca1055f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -126,7 +126,11 @@ struct bnx2x_virtf {
 #define VF_CACHE_LINE		0x0010
 #define VF_CFG_VLAN		0x0020
 #define VF_CFG_STATS_COALESCE	0x0040
-
+#define VF_CFG_EXT_BULLETIN	0x0080
+	u8 link_cfg;		/* IFLA_VF_LINK_STATE_AUTO
+				 * IFLA_VF_LINK_STATE_ENABLE
+				 * IFLA_VF_LINK_STATE_DISABLE
+				 */
 	u8 state;
 #define VF_FREE		0	/* VF ready to be acquired holds no resc */
 #define VF_ACQUIRED	1	/* VF acquired, but not initialized */
@@ -295,22 +299,22 @@ struct bnx2x_vfdb {
 #define BP_VFDB(bp)		((bp)->vfdb)
 	/* vf array */
 	struct bnx2x_virtf	*vfs;
-#define BP_VF(bp, idx)		(&((bp)->vfdb->vfs[(idx)]))
-#define bnx2x_vf(bp, idx, var)	((bp)->vfdb->vfs[(idx)].var)
+#define BP_VF(bp, idx)		(&((bp)->vfdb->vfs[idx]))
+#define bnx2x_vf(bp, idx, var)	((bp)->vfdb->vfs[idx].var)
 
 	/* queue array - for all vfs */
 	struct bnx2x_vf_queue *vfqs;
 
 	/* vf HW contexts */
 	struct hw_dma		context[BNX2X_VF_CIDS/ILT_PAGE_CIDS];
-#define	BP_VF_CXT_PAGE(bp, i)	(&(bp)->vfdb->context[(i)])
+#define	BP_VF_CXT_PAGE(bp, i)	(&(bp)->vfdb->context[i])
 
 	/* SR-IOV information */
 	struct bnx2x_sriov	sriov;
 	struct hw_dma		mbx_dma;
 #define BP_VF_MBX_DMA(bp)	(&((bp)->vfdb->mbx_dma))
 	struct bnx2x_vf_mbx	mbxs[BNX2X_MAX_NUM_OF_VFS];
-#define BP_VF_MBX(bp, vfid)	(&((bp)->vfdb->mbxs[(vfid)]))
+#define BP_VF_MBX(bp, vfid)	(&((bp)->vfdb->mbxs[vfid]))
 
 	struct hw_dma		bulletin_dma;
 #define BP_VF_BULLETIN_DMA(bp)	(&((bp)->vfdb->bulletin_dma))
@@ -336,6 +340,9 @@ struct bnx2x_vfdb {
 	/* sp_rtnl synchronization */
 	struct mutex			event_mutex;
 	u64				event_occur;
+
+	/* bulletin board update synchronization */
+	struct mutex			bulletin_mutex;
 };
 
 /* queue access */
@@ -467,9 +474,10 @@ void bnx2x_vf_handle_flr_event(struct bnx2x *bp);
 
 bool bnx2x_tlv_supported(u16 tlvtype);
 
-u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
-			  struct pf_vf_bulletin_content *bulletin);
+u32 bnx2x_crc_vf_bulletin(struct pf_vf_bulletin_content *bulletin);
 int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf);
+void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
+				bool support_long);
 
 enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp);
 
@@ -520,6 +528,11 @@ void bnx2x_iov_task(struct work_struct *work);
 
 void bnx2x_schedule_iov_task(struct bnx2x *bp, enum bnx2x_iov_flag flag);
 
+void bnx2x_iov_link_update(struct bnx2x *bp);
+int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx);
+
+int bnx2x_set_vf_link_state(struct net_device *dev, int vf, int link_state);
+
 #else /* CONFIG_BNX2X_SRIOV */
 
 static inline void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid,
@@ -579,6 +592,14 @@ static inline void bnx2x_iov_channel_down(struct bnx2x *bp) {}
 
 static inline void bnx2x_iov_task(struct work_struct *work) {}
 static inline void bnx2x_schedule_iov_task(struct bnx2x *bp, enum bnx2x_iov_flag flag) {}
+static inline void bnx2x_iov_link_update(struct bnx2x *bp) {}
+static inline int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx) {return 0; }
+
+static inline int bnx2x_set_vf_link_state(struct net_device *dev, int vf,
+					  int link_state) {return 0; }
+struct pf_vf_bulletin_content;
+static inline void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
+					      bool support_long) {}
 
 #endif /* CONFIG_BNX2X_SRIOV */
 #endif /* bnx2x_sriov.h */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index d712d0d..f350773 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),
@@ -1252,6 +1255,13 @@ static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
 
 	/* 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;
+	}
 
 	/* response */
 	bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc);
@@ -1273,6 +1283,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 +2021,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 +2048,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,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index e21e706..ace4d7b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
@@ -65,6 +65,7 @@ struct hw_sb_info {
 #define VFPF_RX_MASK_ACCEPT_ALL_MULTICAST	0x00000008
 #define VFPF_RX_MASK_ACCEPT_BROADCAST		0x00000010
 #define BULLETIN_CONTENT_SIZE		(sizeof(struct pf_vf_bulletin_content))
+#define BULLETIN_CONTENT_LEGACY_SIZE	(32)
 #define BULLETIN_ATTEMPTS	5 /* crc failures before throwing towel */
 #define BULLETIN_CRC_SEED	0
 
@@ -117,7 +118,9 @@ struct vfpf_acquire_tlv {
 		/* the following fields are for debug purposes */
 		u8  vf_id;		/* ME register value */
 		u8  vf_os;		/* e.g. Linux, W2K8 */
-		u8 padding[2];
+		u8 padding;
+		u8 caps;
+#define VF_CAP_SUPPORT_EXT_BULLETIN	(1 << 0)
 	} vfdev_info;
 
 	struct vf_pf_resc_request resc_request;
@@ -393,11 +396,23 @@ struct pf_vf_bulletin_content {
 					 * to attempt to send messages on the
 					 * channel after this bit is set
 					 */
+#define LINK_VALID		3	/* alert the VF thet a new link status
+					 * update is available for it
+					 */
 	u8 mac[ETH_ALEN];
 	u8 mac_padding[2];
 
 	u16 vlan;
 	u8 vlan_padding[6];
+
+	u16 link_speed;			 /* Effective line speed */
+	u8 link_speed_padding[6];
+	u32 link_flags;			 /* VFPF_LINK_REPORT_XXX flags */
+#define VFPF_LINK_REPORT_LINK_DOWN	 (1 << 0)
+#define VFPF_LINK_REPORT_FULL_DUPLEX	 (1 << 1)
+#define VFPF_LINK_REPORT_RX_FC_ON	 (1 << 2)
+#define VFPF_LINK_REPORT_TX_FC_ON	 (1 << 3)
+	u8 link_flags_padding[4];
 };
 
 union pf_vf_bulletin {
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next 2/3] bnx2x: enlarge minimal alignemnt of data offset
  2014-06-26 11:31 [PATCH net-next 0/3] bnx2x: Enhancement patch series Yuval Mintz
  2014-06-26 11:31 ` [PATCH net-next 1/3] bnx2x: VF can report link speed Yuval Mintz
@ 2014-06-26 11:31 ` Yuval Mintz
  2014-06-26 18:47   ` Eric Dumazet
  2014-06-26 11:31 ` [PATCH net-next 3/3] bnx2x: Fail probe of VFs using an old incompatible driver Yuval Mintz
  2014-07-01 22:52 ` [PATCH net-next 0/3] bnx2x: Enhancement patch series David Miller
  3 siblings, 1 reply; 6+ messages in thread
From: Yuval Mintz @ 2014-06-26 11:31 UTC (permalink / raw)
  To: davem, netdev; +Cc: Ariel.Elior, Dmitry Kravkov, Yuval Mintz

From: Dmitry Kravkov <Dmitry.Kravkov@qlogic.com>

This improves the performance of driver on machine with L1_CACHE_SHIFT of at
most 32 bytes [HW was planned for 64-byte aligned fastpath data].

Signed-off-by: Dmitry Kravkov <Dmitry.Kravkov@qlogic.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index faf262a..ce8f869 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1508,8 +1508,10 @@ struct bnx2x {
 /* TCP with Timestamp Option (32) + IPv6 (40) */
 #define ETH_MAX_TPA_HEADER_SIZE		72
 
-	/* Max supported alignment is 256 (8 shift) */
-#define BNX2X_RX_ALIGN_SHIFT		min(8, L1_CACHE_SHIFT)
+	/* Max supported alignment is 256 (8 shift)
+	 * minimal alignment shift 6 is optimal for 57xxx HW performance
+	 */
+#define BNX2X_RX_ALIGN_SHIFT		max(6, min(8, L1_CACHE_SHIFT))
 
 	/* FW uses 2 Cache lines Alignment for start packet and size
 	 *
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next 3/3] bnx2x: Fail probe of VFs using an old incompatible driver
  2014-06-26 11:31 [PATCH net-next 0/3] bnx2x: Enhancement patch series Yuval Mintz
  2014-06-26 11:31 ` [PATCH net-next 1/3] bnx2x: VF can report link speed Yuval Mintz
  2014-06-26 11:31 ` [PATCH net-next 2/3] bnx2x: enlarge minimal alignemnt of data offset Yuval Mintz
@ 2014-06-26 11:31 ` Yuval Mintz
  2014-07-01 22:52 ` [PATCH net-next 0/3] bnx2x: Enhancement patch series David Miller
  3 siblings, 0 replies; 6+ messages in thread
From: Yuval Mintz @ 2014-06-26 11:31 UTC (permalink / raw)
  To: davem, netdev; +Cc: Ariel.Elior, Yuval Mintz

There are linux distributions where the inbox bnx2x driver contains SRIOV
support but doesn't contain the changes introduced in b9871bcf
"bnx2x: VF RSS support - PF side".

A VF in a VM running that distribution over a new hypervisor will access
incorrect addresses when trying to transmit packets, causing an attention
in the hypervisor and making that VF inactive until FLRed.

The driver in the VM has to ne upgraded [no real way to overcome this], but
due to the HW attention currently arising upgrading the driver in the VM
would not suffice [since the VF needs also be FLRed if the previous driver
was already loaded].

This patch causes the PF to fail the acquire message from a VF running an
old problematic driver; The VF will then gracefully fail it's probe preventing
the HW attention [and allow clean upgrade of driver in VM].

Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 48 ++++++++++++++++++++++++
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h |  6 +++
 2 files changed, 54 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index f350773..54e0427 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -1235,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)
 {
@@ -1250,6 +1285,18 @@ 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);
 
@@ -1263,6 +1310,7 @@ static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
 		vf->cfg_flags &= ~VF_CFG_EXT_BULLETIN;
 	}
 
+out:
 	/* response */
 	bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc);
 }
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index ace4d7b..15670c4 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
@@ -118,6 +118,12 @@ struct vfpf_acquire_tlv {
 		/* the following fields are for debug purposes */
 		u8  vf_id;		/* ME register value */
 		u8  vf_os;		/* e.g. Linux, W2K8 */
+#define VF_OS_SUBVERSION_MASK	(0x1f)
+#define VF_OS_MASK		(0xe0)
+#define VF_OS_SHIFT		(5)
+#define VF_OS_UNDEFINED		(0 << VF_OS_SHIFT)
+#define VF_OS_WINDOWS		(1 << VF_OS_SHIFT)
+
 		u8 padding;
 		u8 caps;
 #define VF_CAP_SUPPORT_EXT_BULLETIN	(1 << 0)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next 2/3] bnx2x: enlarge minimal alignemnt of data offset
  2014-06-26 11:31 ` [PATCH net-next 2/3] bnx2x: enlarge minimal alignemnt of data offset Yuval Mintz
@ 2014-06-26 18:47   ` Eric Dumazet
  0 siblings, 0 replies; 6+ messages in thread
From: Eric Dumazet @ 2014-06-26 18:47 UTC (permalink / raw)
  To: Yuval Mintz; +Cc: davem, netdev, Ariel.Elior, Dmitry Kravkov

On Thu, 2014-06-26 at 14:31 +0300, Yuval Mintz wrote:
> From: Dmitry Kravkov <Dmitry.Kravkov@qlogic.com>
> 
> This improves the performance of driver on machine with L1_CACHE_SHIFT of at
> most 32 bytes [HW was planned for 64-byte aligned fastpath data].
> 

>  
> -	/* Max supported alignment is 256 (8 shift) */
> -#define BNX2X_RX_ALIGN_SHIFT		min(8, L1_CACHE_SHIFT)
> +	/* Max supported alignment is 256 (8 shift)
> +	 * minimal alignment shift 6 is optimal for 57xxx HW performance
> +	 */
> +#define BNX2X_RX_ALIGN_SHIFT		max(6, min(8, L1_CACHE_SHIFT))
>  
>  	/* FW uses 2 Cache lines Alignment for start packet and size
>  	 *

I would personally use clamp(L1_CACHE_SHIFT, 6, 8)

But thats probably a matter of taste...

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next 0/3] bnx2x: Enhancement patch series
  2014-06-26 11:31 [PATCH net-next 0/3] bnx2x: Enhancement patch series Yuval Mintz
                   ` (2 preceding siblings ...)
  2014-06-26 11:31 ` [PATCH net-next 3/3] bnx2x: Fail probe of VFs using an old incompatible driver Yuval Mintz
@ 2014-07-01 22:52 ` David Miller
  3 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2014-07-01 22:52 UTC (permalink / raw)
  To: Yuval.Mintz; +Cc: netdev, Ariel.Elior

From: Yuval Mintz <Yuval.Mintz@qlogic.com>
Date: Thu, 26 Jun 2014 14:31:03 +0300

> This patch series introduces the ability to propagate link parameters
> to VFs as well as control the VF link via hypervisor.
> 
> In addition, it contains 2 small improvements [one IOV-related and the
> other improves performance on machines with short cache lines].
> 
> Please consider applying these patches to `net-next'.

Applied, thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-07-01 22:52 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-26 11:31 [PATCH net-next 0/3] bnx2x: Enhancement patch series Yuval Mintz
2014-06-26 11:31 ` [PATCH net-next 1/3] bnx2x: VF can report link speed Yuval Mintz
2014-06-26 11:31 ` [PATCH net-next 2/3] bnx2x: enlarge minimal alignemnt of data offset Yuval Mintz
2014-06-26 18:47   ` Eric Dumazet
2014-06-26 11:31 ` [PATCH net-next 3/3] bnx2x: Fail probe of VFs using an old incompatible driver Yuval Mintz
2014-07-01 22:52 ` [PATCH net-next 0/3] bnx2x: Enhancement patch series David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.