net/mlx5e: Wake On LAN support
Implement set/get WOL by ethtool and added the needed device commands and structures to mlx5_ifc. Signed-off-by: Tariq Toukan <tariqt@mellanox.com> Signed-off-by: Rana Shahout <ranas@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
d8880795da
Коммит
928cfe8745
|
@ -560,6 +560,12 @@ const char *mlx5_command_str(int command)
|
|||
case MLX5_CMD_OP_ACCESS_REG:
|
||||
return "MLX5_CMD_OP_ACCESS_REG";
|
||||
|
||||
case MLX5_CMD_OP_SET_WOL_ROL:
|
||||
return "SET_WOL_ROL";
|
||||
|
||||
case MLX5_CMD_OP_QUERY_WOL_ROL:
|
||||
return "QUERY_WOL_ROL";
|
||||
|
||||
default: return "unknown command opcode";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -884,6 +884,129 @@ static int mlx5e_get_ts_info(struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static __u32 mlx5e_get_wol_supported(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
__u32 ret = 0;
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, wol_g))
|
||||
ret |= WAKE_MAGIC;
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, wol_s))
|
||||
ret |= WAKE_MAGICSECURE;
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, wol_a))
|
||||
ret |= WAKE_ARP;
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, wol_b))
|
||||
ret |= WAKE_BCAST;
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, wol_m))
|
||||
ret |= WAKE_MCAST;
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, wol_u))
|
||||
ret |= WAKE_UCAST;
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, wol_p))
|
||||
ret |= WAKE_PHY;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __u32 mlx5e_refomrat_wol_mode_mlx5_to_linux(u8 mode)
|
||||
{
|
||||
__u32 ret = 0;
|
||||
|
||||
if (mode & MLX5_WOL_MAGIC)
|
||||
ret |= WAKE_MAGIC;
|
||||
|
||||
if (mode & MLX5_WOL_SECURED_MAGIC)
|
||||
ret |= WAKE_MAGICSECURE;
|
||||
|
||||
if (mode & MLX5_WOL_ARP)
|
||||
ret |= WAKE_ARP;
|
||||
|
||||
if (mode & MLX5_WOL_BROADCAST)
|
||||
ret |= WAKE_BCAST;
|
||||
|
||||
if (mode & MLX5_WOL_MULTICAST)
|
||||
ret |= WAKE_MCAST;
|
||||
|
||||
if (mode & MLX5_WOL_UNICAST)
|
||||
ret |= WAKE_UCAST;
|
||||
|
||||
if (mode & MLX5_WOL_PHY_ACTIVITY)
|
||||
ret |= WAKE_PHY;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 mlx5e_refomrat_wol_mode_linux_to_mlx5(__u32 mode)
|
||||
{
|
||||
u8 ret = 0;
|
||||
|
||||
if (mode & WAKE_MAGIC)
|
||||
ret |= MLX5_WOL_MAGIC;
|
||||
|
||||
if (mode & WAKE_MAGICSECURE)
|
||||
ret |= MLX5_WOL_SECURED_MAGIC;
|
||||
|
||||
if (mode & WAKE_ARP)
|
||||
ret |= MLX5_WOL_ARP;
|
||||
|
||||
if (mode & WAKE_BCAST)
|
||||
ret |= MLX5_WOL_BROADCAST;
|
||||
|
||||
if (mode & WAKE_MCAST)
|
||||
ret |= MLX5_WOL_MULTICAST;
|
||||
|
||||
if (mode & WAKE_UCAST)
|
||||
ret |= MLX5_WOL_UNICAST;
|
||||
|
||||
if (mode & WAKE_PHY)
|
||||
ret |= MLX5_WOL_PHY_ACTIVITY;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mlx5e_get_wol(struct net_device *netdev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u8 mlx5_wol_mode;
|
||||
int err;
|
||||
|
||||
memset(wol, 0, sizeof(*wol));
|
||||
|
||||
wol->supported = mlx5e_get_wol_supported(mdev);
|
||||
if (!wol->supported)
|
||||
return;
|
||||
|
||||
err = mlx5_query_port_wol(mdev, &mlx5_wol_mode);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
wol->wolopts = mlx5e_refomrat_wol_mode_mlx5_to_linux(mlx5_wol_mode);
|
||||
}
|
||||
|
||||
static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
__u32 wol_supported = mlx5e_get_wol_supported(mdev);
|
||||
u32 mlx5_wol_mode;
|
||||
|
||||
if (!wol_supported)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (wol->wolopts & ~wol_supported)
|
||||
return -EINVAL;
|
||||
|
||||
mlx5_wol_mode = mlx5e_refomrat_wol_mode_linux_to_mlx5(wol->wolopts);
|
||||
|
||||
return mlx5_set_port_wol(mdev, mlx5_wol_mode);
|
||||
}
|
||||
|
||||
const struct ethtool_ops mlx5e_ethtool_ops = {
|
||||
.get_drvinfo = mlx5e_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
|
@ -908,4 +1031,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
|
|||
.get_pauseparam = mlx5e_get_pauseparam,
|
||||
.set_pauseparam = mlx5e_set_pauseparam,
|
||||
.get_ts_info = mlx5e_get_ts_info,
|
||||
.get_wol = mlx5e_get_wol,
|
||||
.set_wol = mlx5e_set_wol,
|
||||
};
|
||||
|
|
|
@ -546,3 +546,41 @@ int mlx5_query_port_ets_rate_limit(struct mlx5_core_dev *mdev,
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_query_port_ets_rate_limit);
|
||||
|
||||
int mlx5_set_port_wol(struct mlx5_core_dev *mdev, u8 wol_mode)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)];
|
||||
u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)];
|
||||
|
||||
memset(in, 0, sizeof(in));
|
||||
memset(out, 0, sizeof(out));
|
||||
|
||||
MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
|
||||
MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
|
||||
MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
|
||||
|
||||
return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
|
||||
out, sizeof(out));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_set_port_wol);
|
||||
|
||||
int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)];
|
||||
u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)];
|
||||
int err;
|
||||
|
||||
memset(in, 0, sizeof(in));
|
||||
memset(out, 0, sizeof(out));
|
||||
|
||||
MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
|
||||
|
||||
err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
|
||||
out, sizeof(out));
|
||||
|
||||
if (!err)
|
||||
*wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_query_port_wol);
|
||||
|
|
|
@ -1183,6 +1183,17 @@ enum {
|
|||
MLX5_RQC_RQ_TYPE_MEMORY_RQ_RPM = 0x1,
|
||||
};
|
||||
|
||||
enum mlx5_wol_mode {
|
||||
MLX5_WOL_DISABLE = 0,
|
||||
MLX5_WOL_SECURED_MAGIC = 1 << 1,
|
||||
MLX5_WOL_MAGIC = 1 << 2,
|
||||
MLX5_WOL_ARP = 1 << 3,
|
||||
MLX5_WOL_BROADCAST = 1 << 4,
|
||||
MLX5_WOL_MULTICAST = 1 << 5,
|
||||
MLX5_WOL_UNICAST = 1 << 6,
|
||||
MLX5_WOL_PHY_ACTIVITY = 1 << 7,
|
||||
};
|
||||
|
||||
/* MLX5 DEV CAPs */
|
||||
|
||||
/* TODO: EAT.ME */
|
||||
|
|
|
@ -166,6 +166,8 @@ enum {
|
|||
MLX5_CMD_OP_SET_L2_TABLE_ENTRY = 0x829,
|
||||
MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY = 0x82a,
|
||||
MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY = 0x82b,
|
||||
MLX5_CMD_OP_SET_WOL_ROL = 0x830,
|
||||
MLX5_CMD_OP_QUERY_WOL_ROL = 0x831,
|
||||
MLX5_CMD_OP_CREATE_TIR = 0x900,
|
||||
MLX5_CMD_OP_MODIFY_TIR = 0x901,
|
||||
MLX5_CMD_OP_DESTROY_TIR = 0x902,
|
||||
|
@ -731,7 +733,17 @@ struct mlx5_ifc_cmd_hca_cap_bits {
|
|||
u8 log_max_msg[0x5];
|
||||
u8 reserved_at_1c7[0x4];
|
||||
u8 max_tc[0x4];
|
||||
u8 reserved_at_1cf[0x10];
|
||||
u8 reserved_at_1cf[0x6];
|
||||
u8 rol_s[0x1];
|
||||
u8 rol_g[0x1];
|
||||
u8 reserved_at_1d7[0x1];
|
||||
u8 wol_s[0x1];
|
||||
u8 wol_g[0x1];
|
||||
u8 wol_a[0x1];
|
||||
u8 wol_b[0x1];
|
||||
u8 wol_m[0x1];
|
||||
u8 wol_u[0x1];
|
||||
u8 wol_p[0x1];
|
||||
|
||||
u8 stat_rate_support[0x10];
|
||||
u8 reserved_at_1ef[0xc];
|
||||
|
@ -6873,6 +6885,54 @@ struct mlx5_ifc_mtt_bits {
|
|||
u8 rd_en[0x1];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_query_wol_rol_out_bits {
|
||||
u8 status[0x8];
|
||||
u8 reserved_at_8[0x18];
|
||||
|
||||
u8 syndrome[0x20];
|
||||
|
||||
u8 reserved_at_40[0x10];
|
||||
u8 rol_mode[0x8];
|
||||
u8 wol_mode[0x8];
|
||||
|
||||
u8 reserved_at_60[0x20];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_query_wol_rol_in_bits {
|
||||
u8 opcode[0x10];
|
||||
u8 reserved_at_10[0x10];
|
||||
|
||||
u8 reserved_at_20[0x10];
|
||||
u8 op_mod[0x10];
|
||||
|
||||
u8 reserved_at_40[0x40];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_set_wol_rol_out_bits {
|
||||
u8 status[0x8];
|
||||
u8 reserved_at_8[0x18];
|
||||
|
||||
u8 syndrome[0x20];
|
||||
|
||||
u8 reserved_at_40[0x40];
|
||||
};
|
||||
|
||||
struct mlx5_ifc_set_wol_rol_in_bits {
|
||||
u8 opcode[0x10];
|
||||
u8 reserved_at_10[0x10];
|
||||
|
||||
u8 reserved_at_20[0x10];
|
||||
u8 op_mod[0x10];
|
||||
|
||||
u8 rol_mode_valid[0x1];
|
||||
u8 wol_mode_valid[0x1];
|
||||
u8 reserved_at_42[0xe];
|
||||
u8 rol_mode[0x8];
|
||||
u8 wol_mode[0x8];
|
||||
|
||||
u8 reserved_at_60[0x20];
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_INITIAL_SEG_NIC_INTERFACE_FULL_DRIVER = 0x0,
|
||||
MLX5_INITIAL_SEG_NIC_INTERFACE_DISABLED = 0x1,
|
||||
|
|
|
@ -81,5 +81,7 @@ int mlx5_modify_port_ets_rate_limit(struct mlx5_core_dev *mdev,
|
|||
int mlx5_query_port_ets_rate_limit(struct mlx5_core_dev *mdev,
|
||||
u8 *max_bw_value,
|
||||
u8 *max_bw_unit);
|
||||
int mlx5_set_port_wol(struct mlx5_core_dev *mdev, u8 wol_mode);
|
||||
int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode);
|
||||
|
||||
#endif /* __MLX5_PORT_H__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче