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

Merge tag 'mlx5-fixes-2019-03-29' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux



Saeed Mahameed says:

====================
Mellanox, mlx5 fixes 2019-03-29

This series introduces some fixes to mlx5 driver.

Please pull and let me know if there is any problem.

For -stable v4.11
('net/mlx5: Decrease default mr cache size')

For -stable v4.12
('net/mlx5e: Add a lock on tir list')

For -stable v4.13
('net/mlx5e: Fix error handling when refreshing TIRs')

For -stable v4.18
('net/mlx5e: Update xon formula')

For -stable v4.19
('net: mlx5: Add a missing check on idr_find, free buf')
('net/mlx5e: Update xoff formula')

net-next merge Note:
When merged with net-next the following simple conflict will appear,

drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c

++<<<<<<< HEAD (net)
 + *   max_mtu: netdev's max_mtu
++=======
+  *    @mtu: device's MTU
++>>>>>>> net-next

To resolve: just replace the line in net-next
*    @mtu: device's MTU
to
*    @max_mtu: netdev's max_mtu
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ec915f47 7f1a546e
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -96,9 +96,6 @@ int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
	if (!eproto)
		return -EINVAL;

	if (ext !=  MLX5_CAP_PCAM_FEATURE(dev, ptys_extended_ethernet))
		return -EOPNOTSUPP;

	err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
	if (err)
		return err;
+22 −17
Original line number Diff line number Diff line
@@ -122,7 +122,9 @@ out:
	return err;
}

/* xoff = ((301+2.16 * len [m]) * speed [Gbps] + 2.72 MTU [B]) */
/* xoff = ((301+2.16 * len [m]) * speed [Gbps] + 2.72 MTU [B])
 * minimum speed value is 40Gbps
 */
static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)
{
	u32 speed;
@@ -130,10 +132,9 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)
	int err;

	err = mlx5e_port_linkspeed(priv->mdev, &speed);
	if (err) {
		mlx5_core_warn(priv->mdev, "cannot get port speed\n");
		return 0;
	}
	if (err)
		speed = SPEED_40000;
	speed = max_t(u32, speed, SPEED_40000);

	xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100;

@@ -142,7 +143,7 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)
}

static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
				 u32 xoff, unsigned int mtu)
				 u32 xoff, unsigned int max_mtu)
{
	int i;

@@ -154,11 +155,12 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
		}

		if (port_buffer->buffer[i].size <
		    (xoff + mtu + (1 << MLX5E_BUFFER_CELL_SHIFT)))
		    (xoff + max_mtu + (1 << MLX5E_BUFFER_CELL_SHIFT)))
			return -ENOMEM;

		port_buffer->buffer[i].xoff = port_buffer->buffer[i].size - xoff;
		port_buffer->buffer[i].xon  = port_buffer->buffer[i].xoff - mtu;
		port_buffer->buffer[i].xon  =
			port_buffer->buffer[i].xoff - max_mtu;
	}

	return 0;
@@ -166,7 +168,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,

/**
 * update_buffer_lossy()
 *   mtu: device's MTU
 *   max_mtu: netdev's max_mtu
 *   pfc_en: <input> current pfc configuration
 *   buffer: <input> current prio to buffer mapping
 *   xoff:   <input> xoff value
@@ -183,7 +185,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
 *     Return 0 if no error.
 *     Set change to true if buffer configuration is modified.
 */
static int update_buffer_lossy(unsigned int mtu,
static int update_buffer_lossy(unsigned int max_mtu,
			       u8 pfc_en, u8 *buffer, u32 xoff,
			       struct mlx5e_port_buffer *port_buffer,
			       bool *change)
@@ -220,7 +222,7 @@ static int update_buffer_lossy(unsigned int mtu,
	}

	if (changed) {
		err = update_xoff_threshold(port_buffer, xoff, mtu);
		err = update_xoff_threshold(port_buffer, xoff, max_mtu);
		if (err)
			return err;

@@ -230,6 +232,7 @@ static int update_buffer_lossy(unsigned int mtu,
	return 0;
}

#define MINIMUM_MAX_MTU 9216
int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
				    u32 change, unsigned int mtu,
				    struct ieee_pfc *pfc,
@@ -241,12 +244,14 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
	bool update_prio2buffer = false;
	u8 buffer[MLX5E_MAX_PRIORITY];
	bool update_buffer = false;
	unsigned int max_mtu;
	u32 total_used = 0;
	u8 curr_pfc_en;
	int err;
	int i;

	mlx5e_dbg(HW, priv, "%s: change=%x\n", __func__, change);
	max_mtu = max_t(unsigned int, priv->netdev->max_mtu, MINIMUM_MAX_MTU);

	err = mlx5e_port_query_buffer(priv, &port_buffer);
	if (err)
@@ -254,7 +259,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,

	if (change & MLX5E_PORT_BUFFER_CABLE_LEN) {
		update_buffer = true;
		err = update_xoff_threshold(&port_buffer, xoff, mtu);
		err = update_xoff_threshold(&port_buffer, xoff, max_mtu);
		if (err)
			return err;
	}
@@ -264,7 +269,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
		if (err)
			return err;

		err = update_buffer_lossy(mtu, pfc->pfc_en, buffer, xoff,
		err = update_buffer_lossy(max_mtu, pfc->pfc_en, buffer, xoff,
					  &port_buffer, &update_buffer);
		if (err)
			return err;
@@ -276,8 +281,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
		if (err)
			return err;

		err = update_buffer_lossy(mtu, curr_pfc_en, prio2buffer, xoff,
					  &port_buffer, &update_buffer);
		err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer,
					  xoff, &port_buffer, &update_buffer);
		if (err)
			return err;
	}
@@ -301,7 +306,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
			return -EINVAL;

		update_buffer = true;
		err = update_xoff_threshold(&port_buffer, xoff, mtu);
		err = update_xoff_threshold(&port_buffer, xoff, max_mtu);
		if (err)
			return err;
	}
@@ -309,7 +314,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
	/* Need to update buffer configuration if xoff value is changed */
	if (!update_buffer && xoff != priv->dcbx.xoff) {
		update_buffer = true;
		err = update_xoff_threshold(&port_buffer, xoff, mtu);
		err = update_xoff_threshold(&port_buffer, xoff, max_mtu);
		if (err)
			return err;
	}
+11 −2
Original line number Diff line number Diff line
@@ -45,7 +45,9 @@ int mlx5e_create_tir(struct mlx5_core_dev *mdev,
	if (err)
		return err;

	mutex_lock(&mdev->mlx5e_res.td.list_lock);
	list_add(&tir->list, &mdev->mlx5e_res.td.tirs_list);
	mutex_unlock(&mdev->mlx5e_res.td.list_lock);

	return 0;
}
@@ -53,8 +55,10 @@ int mlx5e_create_tir(struct mlx5_core_dev *mdev,
void mlx5e_destroy_tir(struct mlx5_core_dev *mdev,
		       struct mlx5e_tir *tir)
{
	mutex_lock(&mdev->mlx5e_res.td.list_lock);
	mlx5_core_destroy_tir(mdev, tir->tirn);
	list_del(&tir->list);
	mutex_unlock(&mdev->mlx5e_res.td.list_lock);
}

static int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn,
@@ -114,6 +118,7 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev)
	}

	INIT_LIST_HEAD(&mdev->mlx5e_res.td.tirs_list);
	mutex_init(&mdev->mlx5e_res.td.list_lock);

	return 0;

@@ -141,15 +146,17 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb)
{
	struct mlx5_core_dev *mdev = priv->mdev;
	struct mlx5e_tir *tir;
	int err  = -ENOMEM;
	int err  = 0;
	u32 tirn = 0;
	int inlen;
	void *in;

	inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
	in = kvzalloc(inlen, GFP_KERNEL);
	if (!in)
	if (!in) {
		err = -ENOMEM;
		goto out;
	}

	if (enable_uc_lb)
		MLX5_SET(modify_tir_in, in, ctx.self_lb_block,
@@ -157,6 +164,7 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb)

	MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1);

	mutex_lock(&mdev->mlx5e_res.td.list_lock);
	list_for_each_entry(tir, &mdev->mlx5e_res.td.tirs_list, list) {
		tirn = tir->tirn;
		err = mlx5_core_modify_tir(mdev, tirn, in, inlen);
@@ -168,6 +176,7 @@ out:
	kvfree(in);
	if (err)
		netdev_err(priv->netdev, "refresh tir(0x%x) failed, %d\n", tirn, err);
	mutex_unlock(&mdev->mlx5e_res.td.list_lock);

	return err;
}
+34 −18
Original line number Diff line number Diff line
@@ -603,16 +603,18 @@ static void ptys2ethtool_supported_link(struct mlx5_core_dev *mdev,
			  __ETHTOOL_LINK_MODE_MASK_NBITS);
}

static void ptys2ethtool_adver_link(struct mlx5_core_dev *mdev,
				    unsigned long *advertising_modes,
				    u32 eth_proto_cap)
static void ptys2ethtool_adver_link(unsigned long *advertising_modes,
				    u32 eth_proto_cap, bool ext)
{
	unsigned long proto_cap = eth_proto_cap;
	struct ptys2ethtool_config *table;
	u32 max_size;
	int proto;

	mlx5e_ethtool_get_speed_arr(mdev, &table, &max_size);
	table = ext ? ptys2ext_ethtool_table : ptys2legacy_ethtool_table;
	max_size = ext ? ARRAY_SIZE(ptys2ext_ethtool_table) :
			 ARRAY_SIZE(ptys2legacy_ethtool_table);

	for_each_set_bit(proto, &proto_cap, max_size)
		bitmap_or(advertising_modes, advertising_modes,
			  table[proto].advertised,
@@ -794,12 +796,12 @@ static void get_supported(struct mlx5_core_dev *mdev, u32 eth_proto_cap,
	ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
}

static void get_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_cap,
			    u8 tx_pause, u8 rx_pause,
			    struct ethtool_link_ksettings *link_ksettings)
static void get_advertising(u32 eth_proto_cap, u8 tx_pause, u8 rx_pause,
			    struct ethtool_link_ksettings *link_ksettings,
			    bool ext)
{
	unsigned long *advertising = link_ksettings->link_modes.advertising;
	ptys2ethtool_adver_link(mdev, advertising, eth_proto_cap);
	ptys2ethtool_adver_link(advertising, eth_proto_cap, ext);

	if (rx_pause)
		ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
@@ -854,8 +856,9 @@ static void get_lp_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_lp,
			       struct ethtool_link_ksettings *link_ksettings)
{
	unsigned long *lp_advertising = link_ksettings->link_modes.lp_advertising;
	bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);

	ptys2ethtool_adver_link(mdev, lp_advertising, eth_proto_lp);
	ptys2ethtool_adver_link(lp_advertising, eth_proto_lp, ext);
}

int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
@@ -872,6 +875,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
	u8 an_disable_admin;
	u8 an_status;
	u8 connector_type;
	bool admin_ext;
	bool ext;
	int err;

@@ -886,6 +890,19 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
					      eth_proto_capability);
	eth_proto_admin  = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
					      eth_proto_admin);
	/* Fields: eth_proto_admin and ext_eth_proto_admin  are
	 * mutually exclusive. Hence try reading legacy advertising
	 * when extended advertising is zero.
	 * admin_ext indicates how eth_proto_admin should be
	 * interpreted
	 */
	admin_ext = ext;
	if (ext && !eth_proto_admin) {
		eth_proto_admin  = MLX5_GET_ETH_PROTO(ptys_reg, out, false,
						      eth_proto_admin);
		admin_ext = false;
	}

	eth_proto_oper   = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
					      eth_proto_oper);
	eth_proto_lp	    = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
@@ -899,7 +916,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
	ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);

	get_supported(mdev, eth_proto_cap, link_ksettings);
	get_advertising(mdev, eth_proto_admin, tx_pause, rx_pause, link_ksettings);
	get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings,
			admin_ext);
	get_speed_duplex(priv->netdev, eth_proto_oper, link_ksettings);

	eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
@@ -997,19 +1015,17 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,

#define MLX5E_PTYS_EXT ((1ULL << ETHTOOL_LINK_MODE_50000baseKR_Full_BIT) - 1)

	ext_requested = (link_ksettings->link_modes.advertising[0] >
			MLX5E_PTYS_EXT);
	ext_requested = !!(link_ksettings->link_modes.advertising[0] >
			MLX5E_PTYS_EXT ||
			link_ksettings->link_modes.advertising[1]);
	ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);

	/*when ptys_extended_ethernet is set legacy link modes are deprecated */
	if (ext_requested != ext_supported)
		return -EPROTONOSUPPORT;
	ext_requested &= ext_supported;

	speed = link_ksettings->base.speed;
	ethtool2ptys_adver_func = ext_requested ?
				  mlx5e_ethtool2ptys_ext_adver_link :
				  mlx5e_ethtool2ptys_adver_link;
	err = mlx5_port_query_eth_proto(mdev, 1, ext_supported, &eproto);
	err = mlx5_port_query_eth_proto(mdev, 1, ext_requested, &eproto);
	if (err) {
		netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
			   __func__, err);
@@ -1037,7 +1053,7 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
	if (!an_changes && link_modes == eproto.admin)
		goto out;

	mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_supported);
	mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_requested);
	mlx5_toggle_port_link(mdev);

out:
+68 −14
Original line number Diff line number Diff line
@@ -2158,6 +2158,52 @@ static bool csum_offload_supported(struct mlx5e_priv *priv,
	return true;
}

struct ip_ttl_word {
	__u8	ttl;
	__u8	protocol;
	__sum16	check;
};

struct ipv6_hoplimit_word {
	__be16	payload_len;
	__u8	nexthdr;
	__u8	hop_limit;
};

static bool is_action_keys_supported(const struct flow_action_entry *act)
{
	u32 mask, offset;
	u8 htype;

	htype = act->mangle.htype;
	offset = act->mangle.offset;
	mask = ~act->mangle.mask;
	/* For IPv4 & IPv6 header check 4 byte word,
	 * to determine that modified fields
	 * are NOT ttl & hop_limit only.
	 */
	if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP4) {
		struct ip_ttl_word *ttl_word =
			(struct ip_ttl_word *)&mask;

		if (offset != offsetof(struct iphdr, ttl) ||
		    ttl_word->protocol ||
		    ttl_word->check) {
			return true;
		}
	} else if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP6) {
		struct ipv6_hoplimit_word *hoplimit_word =
			(struct ipv6_hoplimit_word *)&mask;

		if (offset != offsetof(struct ipv6hdr, payload_len) ||
		    hoplimit_word->payload_len ||
		    hoplimit_word->nexthdr) {
			return true;
		}
	}
	return false;
}

static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
					  struct flow_action *flow_action,
					  u32 actions,
@@ -2165,9 +2211,9 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
{
	const struct flow_action_entry *act;
	bool modify_ip_header;
	u8 htype, ip_proto;
	void *headers_v;
	u16 ethertype;
	u8 ip_proto;
	int i;

	if (actions & MLX5_FLOW_CONTEXT_ACTION_DECAP)
@@ -2187,9 +2233,7 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
		    act->id != FLOW_ACTION_ADD)
			continue;

		htype = act->mangle.htype;
		if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP4 ||
		    htype == FLOW_ACT_MANGLE_HDR_TYPE_IP6) {
		if (is_action_keys_supported(act)) {
			modify_ip_header = true;
			break;
		}
@@ -2340,15 +2384,22 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv,
	return 0;
}

static inline int cmp_encap_info(struct ip_tunnel_key *a,
				 struct ip_tunnel_key *b)
struct encap_key {
	struct ip_tunnel_key *ip_tun_key;
	int tunnel_type;
};

static inline int cmp_encap_info(struct encap_key *a,
				 struct encap_key *b)
{
	return memcmp(a, b, sizeof(*a));
	return memcmp(a->ip_tun_key, b->ip_tun_key, sizeof(*a->ip_tun_key)) ||
	       a->tunnel_type != b->tunnel_type;
}

static inline int hash_encap_info(struct ip_tunnel_key *key)
static inline int hash_encap_info(struct encap_key *key)
{
	return jhash(key, sizeof(*key), 0);
	return jhash(key->ip_tun_key, sizeof(*key->ip_tun_key),
		     key->tunnel_type);
}


@@ -2379,7 +2430,7 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
	struct mlx5_esw_flow_attr *attr = flow->esw_attr;
	struct mlx5e_tc_flow_parse_attr *parse_attr;
	struct ip_tunnel_info *tun_info;
	struct ip_tunnel_key *key;
	struct encap_key key, e_key;
	struct mlx5e_encap_entry *e;
	unsigned short family;
	uintptr_t hash_key;
@@ -2389,13 +2440,16 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
	parse_attr = attr->parse_attr;
	tun_info = &parse_attr->tun_info[out_index];
	family = ip_tunnel_info_af(tun_info);
	key = &tun_info->key;
	key.ip_tun_key = &tun_info->key;
	key.tunnel_type = mlx5e_tc_tun_get_type(mirred_dev);

	hash_key = hash_encap_info(key);
	hash_key = hash_encap_info(&key);

	hash_for_each_possible_rcu(esw->offloads.encap_tbl, e,
				   encap_hlist, hash_key) {
		if (!cmp_encap_info(&e->tun_info.key, key)) {
		e_key.ip_tun_key = &e->tun_info.key;
		e_key.tunnel_type = e->tunnel_type;
		if (!cmp_encap_info(&e_key, &key)) {
			found = true;
			break;
		}
@@ -2657,7 +2711,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,

	if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits ||
	    hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) {
		err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL,
		err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_FDB,
					    parse_attr, hdrs, extack);
		if (err)
			return err;
Loading