Commit be599603 authored by Moshe Shemesh's avatar Moshe Shemesh Committed by David S. Miller

net/mlx4: Add user mac FW update support

Adding support for updating the FW on new port mac, when port mac change
is requested by the user. This info is required by the FW as OEM
management tools require this info directly from the NIC FW.
Check device capability bit to verify the FW supports user mac.
If the FW does support it, use set_port command to notify the FW on the
new mac.
The feature is relevant only to PF port mac.
Signed-off-by: default avatarMoshe Shemesh <moshe@mellanox.com>
Signed-off-by: default avatarTariq Toukan <tariqt@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a434f1fd
...@@ -732,6 +732,21 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn, ...@@ -732,6 +732,21 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn,
return __mlx4_replace_mac(dev, priv->port, qpn, new_mac_u64); return __mlx4_replace_mac(dev, priv->port, qpn, new_mac_u64);
} }
static void mlx4_en_update_user_mac(struct mlx4_en_priv *priv,
unsigned char new_mac[ETH_ALEN + 2])
{
struct mlx4_en_dev *mdev = priv->mdev;
int err;
if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_USER_MAC_EN))
return;
err = mlx4_SET_PORT_user_mac(mdev->dev, priv->port, new_mac);
if (err)
en_err(priv, "Failed to pass user MAC(%pM) to Firmware for port %d, with error %d\n",
new_mac, priv->port, err);
}
static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv, static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv,
unsigned char new_mac[ETH_ALEN + 2]) unsigned char new_mac[ETH_ALEN + 2])
{ {
...@@ -766,8 +781,12 @@ static int mlx4_en_set_mac(struct net_device *dev, void *addr) ...@@ -766,8 +781,12 @@ static int mlx4_en_set_mac(struct net_device *dev, void *addr)
mutex_lock(&mdev->state_lock); mutex_lock(&mdev->state_lock);
memcpy(new_mac, saddr->sa_data, ETH_ALEN); memcpy(new_mac, saddr->sa_data, ETH_ALEN);
err = mlx4_en_do_set_mac(priv, new_mac); err = mlx4_en_do_set_mac(priv, new_mac);
if (!err) if (err)
goto out;
memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN); memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
mlx4_en_update_user_mac(priv, new_mac);
out:
mutex_unlock(&mdev->state_lock); mutex_unlock(&mdev->state_lock);
return err; return err;
......
...@@ -162,6 +162,7 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) ...@@ -162,6 +162,7 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
[35] = "Diag counters per port", [35] = "Diag counters per port",
[36] = "QinQ VST mode support", [36] = "QinQ VST mode support",
[37] = "sl to vl mapping table change event support", [37] = "sl to vl mapping table change event support",
[38] = "user MAC support",
}; };
int i; int i;
...@@ -778,6 +779,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -778,6 +779,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET 0x52 #define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET 0x52
#define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET 0x55 #define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET 0x55
#define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET 0x56 #define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET 0x56
#define QUERY_DEV_CAP_USER_MAC_EN_OFFSET 0x5C
#define QUERY_DEV_CAP_SVLAN_BY_QP_OFFSET 0x5D #define QUERY_DEV_CAP_SVLAN_BY_QP_OFFSET 0x5D
#define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET 0x61 #define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET 0x61
#define QUERY_DEV_CAP_RSVD_MCG_OFFSET 0x62 #define QUERY_DEV_CAP_RSVD_MCG_OFFSET 0x62
...@@ -949,6 +951,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -949,6 +951,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET); MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET);
dev_cap->max_sq_desc_sz = size; dev_cap->max_sq_desc_sz = size;
MLX4_GET(field, outbox, QUERY_DEV_CAP_USER_MAC_EN_OFFSET);
if (field & (1 << 2))
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_USER_MAC_EN;
MLX4_GET(field, outbox, QUERY_DEV_CAP_SVLAN_BY_QP_OFFSET); MLX4_GET(field, outbox, QUERY_DEV_CAP_SVLAN_BY_QP_OFFSET);
if (field & 0x1) if (field & 0x1)
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SVLAN_BY_QP; dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_SVLAN_BY_QP;
......
...@@ -1029,6 +1029,9 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) ...@@ -1029,6 +1029,9 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS; dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
mlx4_warn(dev, "Timestamping is not supported in slave mode\n"); mlx4_warn(dev, "Timestamping is not supported in slave mode\n");
dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_USER_MAC_EN;
mlx4_dbg(dev, "User MAC FW update is not supported in slave mode\n");
slave_adjust_steering_mode(dev, dev_cap, hca_param); slave_adjust_steering_mode(dev, dev_cap, hca_param);
mlx4_dbg(dev, "RSS support for IP fragments is %s\n", mlx4_dbg(dev, "RSS support for IP fragments is %s\n",
hca_param->rss_ip_frags ? "on" : "off"); hca_param->rss_ip_frags ? "on" : "off");
......
...@@ -807,6 +807,8 @@ struct mlx4_set_port_general_context { ...@@ -807,6 +807,8 @@ struct mlx4_set_port_general_context {
u8 phv_en; u8 phv_en;
u8 reserved6[5]; u8 reserved6[5];
__be16 user_mtu; __be16 user_mtu;
u16 reserved7;
u8 user_mac[6];
}; };
struct mlx4_set_port_rqp_calc_context { struct mlx4_set_port_rqp_calc_context {
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#define MLX4_FLAG2_V_IGNORE_FCS_MASK BIT(1) #define MLX4_FLAG2_V_IGNORE_FCS_MASK BIT(1)
#define MLX4_FLAG2_V_USER_MTU_MASK BIT(5) #define MLX4_FLAG2_V_USER_MTU_MASK BIT(5)
#define MLX4_FLAG2_V_USER_MAC_MASK BIT(6)
#define MLX4_FLAG_V_MTU_MASK BIT(0) #define MLX4_FLAG_V_MTU_MASK BIT(0)
#define MLX4_FLAG_V_PPRX_MASK BIT(1) #define MLX4_FLAG_V_PPRX_MASK BIT(1)
#define MLX4_FLAG_V_PPTX_MASK BIT(2) #define MLX4_FLAG_V_PPTX_MASK BIT(2)
...@@ -1700,6 +1701,30 @@ int mlx4_SET_PORT_user_mtu(struct mlx4_dev *dev, u8 port, u16 user_mtu) ...@@ -1700,6 +1701,30 @@ int mlx4_SET_PORT_user_mtu(struct mlx4_dev *dev, u8 port, u16 user_mtu)
} }
EXPORT_SYMBOL(mlx4_SET_PORT_user_mtu); EXPORT_SYMBOL(mlx4_SET_PORT_user_mtu);
int mlx4_SET_PORT_user_mac(struct mlx4_dev *dev, u8 port, u8 *user_mac)
{
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_set_port_general_context *context;
u32 in_mod;
int err;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
context = mailbox->buf;
context->flags2 |= MLX4_FLAG2_V_USER_MAC_MASK;
memcpy(context->user_mac, user_mac, sizeof(context->user_mac));
in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
err = mlx4_cmd(dev, mailbox->dma, in_mod, MLX4_SET_PORT_ETH_OPCODE,
MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_NATIVE);
mlx4_free_cmd_mailbox(dev, mailbox);
return err;
}
EXPORT_SYMBOL(mlx4_SET_PORT_user_mac);
int mlx4_SET_PORT_fcs_check(struct mlx4_dev *dev, u8 port, u8 ignore_fcs_value) int mlx4_SET_PORT_fcs_check(struct mlx4_dev *dev, u8 port, u8 ignore_fcs_value)
{ {
struct mlx4_cmd_mailbox *mailbox; struct mlx4_cmd_mailbox *mailbox;
......
...@@ -224,6 +224,7 @@ enum { ...@@ -224,6 +224,7 @@ enum {
MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT = 1ULL << 35, MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT = 1ULL << 35,
MLX4_DEV_CAP_FLAG2_SVLAN_BY_QP = 1ULL << 36, MLX4_DEV_CAP_FLAG2_SVLAN_BY_QP = 1ULL << 36,
MLX4_DEV_CAP_FLAG2_SL_TO_VL_CHANGE_EVENT = 1ULL << 37, MLX4_DEV_CAP_FLAG2_SL_TO_VL_CHANGE_EVENT = 1ULL << 37,
MLX4_DEV_CAP_FLAG2_USER_MAC_EN = 1ULL << 38,
}; };
enum { enum {
...@@ -1377,6 +1378,7 @@ int mlx4_get_base_qpn(struct mlx4_dev *dev, u8 port); ...@@ -1377,6 +1378,7 @@ int mlx4_get_base_qpn(struct mlx4_dev *dev, u8 port);
int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac); int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac);
int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx); u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
int mlx4_SET_PORT_user_mac(struct mlx4_dev *dev, u8 port, u8 *user_mac);
int mlx4_SET_PORT_user_mtu(struct mlx4_dev *dev, u8 port, u16 user_mtu); int mlx4_SET_PORT_user_mtu(struct mlx4_dev *dev, u8 port, u16 user_mtu);
int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
u8 promisc); u8 promisc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment