Commit f8e48fca authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'nfp-flower-feature-bit-updates'



Simon Horman says:

====================
nfp: flower: feature bit updates

this short series has two parts.

* The first patch cleans up the treatment of existing feature bits.
  There are two distinct methods used and the code now reflects this
  more clearly.
* The second patch informs firmware of flower features. This allows
  the firmware to disable certain features in the absence of of host support.

Changes since v1
- Add now-first patch to clean up existing implementation
- Address Jakub's feedback
====================

Acked-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 85bac6a5 465957c2
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -209,7 +209,7 @@ nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output,
					    NFP_FL_OUT_FLAGS_USE_TUN);
		output->port = cpu_to_be32(NFP_FL_PORT_TYPE_TUN | tun_type);
	} else if (netif_is_lag_master(out_dev) &&
		   priv->flower_ext_feats & NFP_FL_FEATS_LAG) {
		   priv->flower_en_feats & NFP_FL_ENABLE_LAG) {
		int gid;

		output->flags = cpu_to_be16(tmp_flags);
@@ -956,7 +956,7 @@ nfp_flower_output_action(struct nfp_app *app,

	*a_len += sizeof(struct nfp_fl_output);

	if (priv->flower_ext_feats & NFP_FL_FEATS_LAG) {
	if (priv->flower_en_feats & NFP_FL_ENABLE_LAG) {
		/* nfp_fl_pre_lag returns -err or size of prelag action added.
		 * This will be 0 if it is not egressing to a lag dev.
		 */
+2 −2
Original line number Diff line number Diff line
@@ -264,7 +264,7 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)
		nfp_flower_cmsg_portmod_rx(app, skb);
		break;
	case NFP_FLOWER_CMSG_TYPE_MERGE_HINT:
		if (app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MERGE) {
		if (app_priv->flower_en_feats & NFP_FL_ENABLE_FLOW_MERGE) {
			nfp_flower_cmsg_merge_hint_rx(app, skb);
			break;
		}
@@ -285,7 +285,7 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)
		nfp_flower_stats_rlim_reply(app, skb);
		break;
	case NFP_FLOWER_CMSG_TYPE_LAG_CONFIG:
		if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) {
		if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG) {
			skb_stored = nfp_flower_lag_unprocessed_msg(app, skb);
			break;
		}
+81 −35
Original line number Diff line number Diff line
@@ -665,6 +665,77 @@ err_clear_nn:
	return err;
}

static void nfp_flower_wait_host_bit(struct nfp_app *app)
{
	unsigned long err_at;
	u64 feat;
	int err;

	/* Wait for HOST_ACK flag bit to propagate */
	err_at = jiffies + msecs_to_jiffies(100);
	do {
		feat = nfp_rtsym_read_le(app->pf->rtbl,
					 "_abi_flower_combined_features_global",
					 &err);
		if (time_is_before_eq_jiffies(err_at)) {
			nfp_warn(app->cpp,
				 "HOST_ACK bit not propagated in FW.\n");
			break;
		}
		usleep_range(1000, 2000);
	} while (!err && !(feat & NFP_FL_FEATS_HOST_ACK));

	if (err)
		nfp_warn(app->cpp,
			 "Could not read global features entry from FW\n");
}

static int nfp_flower_sync_feature_bits(struct nfp_app *app)
{
	struct nfp_flower_priv *app_priv = app->priv;
	int err;

	/* Tell the firmware of the host supported features. */
	err = nfp_rtsym_write_le(app->pf->rtbl, "_abi_flower_host_mask",
				 app_priv->flower_ext_feats |
				 NFP_FL_FEATS_HOST_ACK);
	if (!err)
		nfp_flower_wait_host_bit(app);
	else if (err != -ENOENT)
		return err;

	/* Tell the firmware that the driver supports lag. */
	err = nfp_rtsym_write_le(app->pf->rtbl,
				 "_abi_flower_balance_sync_enable", 1);
	if (!err) {
		app_priv->flower_ext_feats |= NFP_FL_ENABLE_LAG;
		nfp_flower_lag_init(&app_priv->nfp_lag);
	} else if (err == -ENOENT) {
		nfp_warn(app->cpp, "LAG not supported by FW.\n");
	} else {
		return err;
	}

	if (app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MOD) {
		/* Tell the firmware that the driver supports flow merging. */
		err = nfp_rtsym_write_le(app->pf->rtbl,
					 "_abi_flower_merge_hint_enable", 1);
		if (!err) {
			app_priv->flower_ext_feats |= NFP_FL_ENABLE_FLOW_MERGE;
			nfp_flower_internal_port_init(app_priv);
		} else if (err == -ENOENT) {
			nfp_warn(app->cpp,
				 "Flow merge not supported by FW.\n");
		} else {
			return err;
		}
	} else {
		nfp_warn(app->cpp, "Flow mod/merge not supported by FW.\n");
	}

	return 0;
}

static int nfp_flower_init(struct nfp_app *app)
{
	u64 version, features, ctx_count, num_mems;
@@ -753,35 +824,11 @@ static int nfp_flower_init(struct nfp_app *app)
	if (err)
		app_priv->flower_ext_feats = 0;
	else
		app_priv->flower_ext_feats = features;
		app_priv->flower_ext_feats = features & NFP_FL_FEATS_HOST;

	/* Tell the firmware that the driver supports lag. */
	err = nfp_rtsym_write_le(app->pf->rtbl,
				 "_abi_flower_balance_sync_enable", 1);
	if (!err) {
		app_priv->flower_ext_feats |= NFP_FL_FEATS_LAG;
		nfp_flower_lag_init(&app_priv->nfp_lag);
	} else if (err == -ENOENT) {
		nfp_warn(app->cpp, "LAG not supported by FW.\n");
	} else {
		goto err_cleanup_metadata;
	}

	if (app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MOD) {
		/* Tell the firmware that the driver supports flow merging. */
		err = nfp_rtsym_write_le(app->pf->rtbl,
					 "_abi_flower_merge_hint_enable", 1);
		if (!err) {
			app_priv->flower_ext_feats |= NFP_FL_FEATS_FLOW_MERGE;
			nfp_flower_internal_port_init(app_priv);
		} else if (err == -ENOENT) {
			nfp_warn(app->cpp, "Flow merge not supported by FW.\n");
		} else {
			goto err_lag_clean;
		}
	} else {
		nfp_warn(app->cpp, "Flow mod/merge not supported by FW.\n");
	}
	err = nfp_flower_sync_feature_bits(app);
	if (err)
		goto err_cleanup;

	if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)
		nfp_flower_qos_init(app);
@@ -792,10 +839,9 @@ static int nfp_flower_init(struct nfp_app *app)

	return 0;

err_lag_clean:
	if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG)
err_cleanup:
	if (app_priv->flower_ext_feats & NFP_FL_ENABLE_LAG)
		nfp_flower_lag_cleanup(&app_priv->nfp_lag);
err_cleanup_metadata:
	nfp_flower_metadata_cleanup(app);
err_free_app_priv:
	vfree(app->priv);
@@ -813,10 +859,10 @@ static void nfp_flower_clean(struct nfp_app *app)
	if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)
		nfp_flower_qos_cleanup(app);

	if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG)
	if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG)
		nfp_flower_lag_cleanup(&app_priv->nfp_lag);

	if (app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MERGE)
	if (app_priv->flower_en_feats & NFP_FL_ENABLE_FLOW_MERGE)
		nfp_flower_internal_port_cleanup(app_priv);

	nfp_flower_metadata_cleanup(app);
@@ -886,7 +932,7 @@ static int nfp_flower_start(struct nfp_app *app)
	struct nfp_flower_priv *app_priv = app->priv;
	int err;

	if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) {
	if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG) {
		err = nfp_flower_lag_reset(&app_priv->nfp_lag);
		if (err)
			return err;
@@ -907,7 +953,7 @@ nfp_flower_netdev_event(struct nfp_app *app, struct net_device *netdev,
	struct nfp_flower_priv *app_priv = app->priv;
	int ret;

	if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) {
	if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG) {
		ret = nfp_flower_lag_netdev_event(app_priv, netdev, event, ptr);
		if (ret & NOTIFY_STOP_MASK)
			return ret;
+17 −3
Original line number Diff line number Diff line
@@ -44,8 +44,20 @@ struct nfp_app;
#define NFP_FL_FEATS_FLOW_MOD		BIT(5)
#define NFP_FL_FEATS_PRE_TUN_RULES	BIT(6)
#define NFP_FL_FEATS_IPV6_TUN		BIT(7)
#define NFP_FL_FEATS_FLOW_MERGE		BIT(30)
#define NFP_FL_FEATS_LAG		BIT(31)
#define NFP_FL_FEATS_HOST_ACK		BIT(31)

#define NFP_FL_ENABLE_FLOW_MERGE	BIT(0)
#define NFP_FL_ENABLE_LAG		BIT(1)

#define NFP_FL_FEATS_HOST \
	(NFP_FL_FEATS_GENEVE | \
	NFP_FL_NBI_MTU_SETTING | \
	NFP_FL_FEATS_GENEVE_OPT | \
	NFP_FL_FEATS_VLAN_PCP | \
	NFP_FL_FEATS_VF_RLIM | \
	NFP_FL_FEATS_FLOW_MOD | \
	NFP_FL_FEATS_PRE_TUN_RULES | \
	NFP_FL_FEATS_IPV6_TUN)

struct nfp_fl_mask_id {
	struct circ_buf mask_id_free_list;
@@ -145,6 +157,7 @@ struct nfp_fl_internal_ports {
 * @mask_id_seed:	Seed used for mask hash table
 * @flower_version:	HW version of flower
 * @flower_ext_feats:	Bitmap of extra features the HW supports
 * @flower_en_feats:	Bitmap of features enabled by HW
 * @stats_ids:		List of free stats ids
 * @mask_ids:		List of free mask ids
 * @mask_table:		Hash table used to store masks
@@ -180,6 +193,7 @@ struct nfp_flower_priv {
	u32 mask_id_seed;
	u64 flower_version;
	u64 flower_ext_feats;
	u8 flower_en_feats;
	struct nfp_fl_stats_id stats_ids;
	struct nfp_fl_mask_id mask_ids;
	DECLARE_HASHTABLE(mask_table, NFP_FLOWER_MASK_HASH_BITS);
@@ -346,7 +360,7 @@ nfp_flower_internal_port_can_offload(struct nfp_app *app,
{
	struct nfp_flower_priv *app_priv = app->priv;

	if (!(app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MERGE))
	if (!(app_priv->flower_en_feats & NFP_FL_ENABLE_FLOW_MERGE))
		return false;
	if (!netdev->rtnl_link_ops)
		return false;