Skip to content

Commit 928cfe8

Browse files
Tariq Toukandavem330
authored andcommitted
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>
1 parent d888079 commit 928cfe8

File tree

6 files changed

+243
-1
lines changed

6 files changed

+243
-1
lines changed

drivers/net/ethernet/mellanox/mlx5/core/cmd.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,12 @@ const char *mlx5_command_str(int command)
560560
case MLX5_CMD_OP_ACCESS_REG:
561561
return "MLX5_CMD_OP_ACCESS_REG";
562562

563+
case MLX5_CMD_OP_SET_WOL_ROL:
564+
return "SET_WOL_ROL";
565+
566+
case MLX5_CMD_OP_QUERY_WOL_ROL:
567+
return "QUERY_WOL_ROL";
568+
563569
default: return "unknown command opcode";
564570
}
565571
}

drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,129 @@ static int mlx5e_get_ts_info(struct net_device *dev,
884884
return 0;
885885
}
886886

887+
static __u32 mlx5e_get_wol_supported(struct mlx5_core_dev *mdev)
888+
{
889+
__u32 ret = 0;
890+
891+
if (MLX5_CAP_GEN(mdev, wol_g))
892+
ret |= WAKE_MAGIC;
893+
894+
if (MLX5_CAP_GEN(mdev, wol_s))
895+
ret |= WAKE_MAGICSECURE;
896+
897+
if (MLX5_CAP_GEN(mdev, wol_a))
898+
ret |= WAKE_ARP;
899+
900+
if (MLX5_CAP_GEN(mdev, wol_b))
901+
ret |= WAKE_BCAST;
902+
903+
if (MLX5_CAP_GEN(mdev, wol_m))
904+
ret |= WAKE_MCAST;
905+
906+
if (MLX5_CAP_GEN(mdev, wol_u))
907+
ret |= WAKE_UCAST;
908+
909+
if (MLX5_CAP_GEN(mdev, wol_p))
910+
ret |= WAKE_PHY;
911+
912+
return ret;
913+
}
914+
915+
static __u32 mlx5e_refomrat_wol_mode_mlx5_to_linux(u8 mode)
916+
{
917+
__u32 ret = 0;
918+
919+
if (mode & MLX5_WOL_MAGIC)
920+
ret |= WAKE_MAGIC;
921+
922+
if (mode & MLX5_WOL_SECURED_MAGIC)
923+
ret |= WAKE_MAGICSECURE;
924+
925+
if (mode & MLX5_WOL_ARP)
926+
ret |= WAKE_ARP;
927+
928+
if (mode & MLX5_WOL_BROADCAST)
929+
ret |= WAKE_BCAST;
930+
931+
if (mode & MLX5_WOL_MULTICAST)
932+
ret |= WAKE_MCAST;
933+
934+
if (mode & MLX5_WOL_UNICAST)
935+
ret |= WAKE_UCAST;
936+
937+
if (mode & MLX5_WOL_PHY_ACTIVITY)
938+
ret |= WAKE_PHY;
939+
940+
return ret;
941+
}
942+
943+
static u8 mlx5e_refomrat_wol_mode_linux_to_mlx5(__u32 mode)
944+
{
945+
u8 ret = 0;
946+
947+
if (mode & WAKE_MAGIC)
948+
ret |= MLX5_WOL_MAGIC;
949+
950+
if (mode & WAKE_MAGICSECURE)
951+
ret |= MLX5_WOL_SECURED_MAGIC;
952+
953+
if (mode & WAKE_ARP)
954+
ret |= MLX5_WOL_ARP;
955+
956+
if (mode & WAKE_BCAST)
957+
ret |= MLX5_WOL_BROADCAST;
958+
959+
if (mode & WAKE_MCAST)
960+
ret |= MLX5_WOL_MULTICAST;
961+
962+
if (mode & WAKE_UCAST)
963+
ret |= MLX5_WOL_UNICAST;
964+
965+
if (mode & WAKE_PHY)
966+
ret |= MLX5_WOL_PHY_ACTIVITY;
967+
968+
return ret;
969+
}
970+
971+
static void mlx5e_get_wol(struct net_device *netdev,
972+
struct ethtool_wolinfo *wol)
973+
{
974+
struct mlx5e_priv *priv = netdev_priv(netdev);
975+
struct mlx5_core_dev *mdev = priv->mdev;
976+
u8 mlx5_wol_mode;
977+
int err;
978+
979+
memset(wol, 0, sizeof(*wol));
980+
981+
wol->supported = mlx5e_get_wol_supported(mdev);
982+
if (!wol->supported)
983+
return;
984+
985+
err = mlx5_query_port_wol(mdev, &mlx5_wol_mode);
986+
if (err)
987+
return;
988+
989+
wol->wolopts = mlx5e_refomrat_wol_mode_mlx5_to_linux(mlx5_wol_mode);
990+
}
991+
992+
static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
993+
{
994+
struct mlx5e_priv *priv = netdev_priv(netdev);
995+
struct mlx5_core_dev *mdev = priv->mdev;
996+
__u32 wol_supported = mlx5e_get_wol_supported(mdev);
997+
u32 mlx5_wol_mode;
998+
999+
if (!wol_supported)
1000+
return -ENOTSUPP;
1001+
1002+
if (wol->wolopts & ~wol_supported)
1003+
return -EINVAL;
1004+
1005+
mlx5_wol_mode = mlx5e_refomrat_wol_mode_linux_to_mlx5(wol->wolopts);
1006+
1007+
return mlx5_set_port_wol(mdev, mlx5_wol_mode);
1008+
}
1009+
8871010
const struct ethtool_ops mlx5e_ethtool_ops = {
8881011
.get_drvinfo = mlx5e_get_drvinfo,
8891012
.get_link = ethtool_op_get_link,
@@ -908,4 +1031,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
9081031
.get_pauseparam = mlx5e_get_pauseparam,
9091032
.set_pauseparam = mlx5e_set_pauseparam,
9101033
.get_ts_info = mlx5e_get_ts_info,
1034+
.get_wol = mlx5e_get_wol,
1035+
.set_wol = mlx5e_set_wol,
9111036
};

drivers/net/ethernet/mellanox/mlx5/core/port.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,3 +546,41 @@ int mlx5_query_port_ets_rate_limit(struct mlx5_core_dev *mdev,
546546
return 0;
547547
}
548548
EXPORT_SYMBOL_GPL(mlx5_query_port_ets_rate_limit);
549+
550+
int mlx5_set_port_wol(struct mlx5_core_dev *mdev, u8 wol_mode)
551+
{
552+
u32 in[MLX5_ST_SZ_DW(set_wol_rol_in)];
553+
u32 out[MLX5_ST_SZ_DW(set_wol_rol_out)];
554+
555+
memset(in, 0, sizeof(in));
556+
memset(out, 0, sizeof(out));
557+
558+
MLX5_SET(set_wol_rol_in, in, opcode, MLX5_CMD_OP_SET_WOL_ROL);
559+
MLX5_SET(set_wol_rol_in, in, wol_mode_valid, 1);
560+
MLX5_SET(set_wol_rol_in, in, wol_mode, wol_mode);
561+
562+
return mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
563+
out, sizeof(out));
564+
}
565+
EXPORT_SYMBOL_GPL(mlx5_set_port_wol);
566+
567+
int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode)
568+
{
569+
u32 in[MLX5_ST_SZ_DW(query_wol_rol_in)];
570+
u32 out[MLX5_ST_SZ_DW(query_wol_rol_out)];
571+
int err;
572+
573+
memset(in, 0, sizeof(in));
574+
memset(out, 0, sizeof(out));
575+
576+
MLX5_SET(query_wol_rol_in, in, opcode, MLX5_CMD_OP_QUERY_WOL_ROL);
577+
578+
err = mlx5_cmd_exec_check_status(mdev, in, sizeof(in),
579+
out, sizeof(out));
580+
581+
if (!err)
582+
*wol_mode = MLX5_GET(query_wol_rol_out, out, wol_mode);
583+
584+
return err;
585+
}
586+
EXPORT_SYMBOL_GPL(mlx5_query_port_wol);

include/linux/mlx5/device.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,17 @@ enum {
11831183
MLX5_RQC_RQ_TYPE_MEMORY_RQ_RPM = 0x1,
11841184
};
11851185

1186+
enum mlx5_wol_mode {
1187+
MLX5_WOL_DISABLE = 0,
1188+
MLX5_WOL_SECURED_MAGIC = 1 << 1,
1189+
MLX5_WOL_MAGIC = 1 << 2,
1190+
MLX5_WOL_ARP = 1 << 3,
1191+
MLX5_WOL_BROADCAST = 1 << 4,
1192+
MLX5_WOL_MULTICAST = 1 << 5,
1193+
MLX5_WOL_UNICAST = 1 << 6,
1194+
MLX5_WOL_PHY_ACTIVITY = 1 << 7,
1195+
};
1196+
11861197
/* MLX5 DEV CAPs */
11871198

11881199
/* TODO: EAT.ME */

include/linux/mlx5/mlx5_ifc.h

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ enum {
166166
MLX5_CMD_OP_SET_L2_TABLE_ENTRY = 0x829,
167167
MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY = 0x82a,
168168
MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY = 0x82b,
169+
MLX5_CMD_OP_SET_WOL_ROL = 0x830,
170+
MLX5_CMD_OP_QUERY_WOL_ROL = 0x831,
169171
MLX5_CMD_OP_CREATE_TIR = 0x900,
170172
MLX5_CMD_OP_MODIFY_TIR = 0x901,
171173
MLX5_CMD_OP_DESTROY_TIR = 0x902,
@@ -731,7 +733,17 @@ struct mlx5_ifc_cmd_hca_cap_bits {
731733
u8 log_max_msg[0x5];
732734
u8 reserved_at_1c7[0x4];
733735
u8 max_tc[0x4];
734-
u8 reserved_at_1cf[0x10];
736+
u8 reserved_at_1cf[0x6];
737+
u8 rol_s[0x1];
738+
u8 rol_g[0x1];
739+
u8 reserved_at_1d7[0x1];
740+
u8 wol_s[0x1];
741+
u8 wol_g[0x1];
742+
u8 wol_a[0x1];
743+
u8 wol_b[0x1];
744+
u8 wol_m[0x1];
745+
u8 wol_u[0x1];
746+
u8 wol_p[0x1];
735747

736748
u8 stat_rate_support[0x10];
737749
u8 reserved_at_1ef[0xc];
@@ -6873,6 +6885,54 @@ struct mlx5_ifc_mtt_bits {
68736885
u8 rd_en[0x1];
68746886
};
68756887

6888+
struct mlx5_ifc_query_wol_rol_out_bits {
6889+
u8 status[0x8];
6890+
u8 reserved_at_8[0x18];
6891+
6892+
u8 syndrome[0x20];
6893+
6894+
u8 reserved_at_40[0x10];
6895+
u8 rol_mode[0x8];
6896+
u8 wol_mode[0x8];
6897+
6898+
u8 reserved_at_60[0x20];
6899+
};
6900+
6901+
struct mlx5_ifc_query_wol_rol_in_bits {
6902+
u8 opcode[0x10];
6903+
u8 reserved_at_10[0x10];
6904+
6905+
u8 reserved_at_20[0x10];
6906+
u8 op_mod[0x10];
6907+
6908+
u8 reserved_at_40[0x40];
6909+
};
6910+
6911+
struct mlx5_ifc_set_wol_rol_out_bits {
6912+
u8 status[0x8];
6913+
u8 reserved_at_8[0x18];
6914+
6915+
u8 syndrome[0x20];
6916+
6917+
u8 reserved_at_40[0x40];
6918+
};
6919+
6920+
struct mlx5_ifc_set_wol_rol_in_bits {
6921+
u8 opcode[0x10];
6922+
u8 reserved_at_10[0x10];
6923+
6924+
u8 reserved_at_20[0x10];
6925+
u8 op_mod[0x10];
6926+
6927+
u8 rol_mode_valid[0x1];
6928+
u8 wol_mode_valid[0x1];
6929+
u8 reserved_at_42[0xe];
6930+
u8 rol_mode[0x8];
6931+
u8 wol_mode[0x8];
6932+
6933+
u8 reserved_at_60[0x20];
6934+
};
6935+
68766936
enum {
68776937
MLX5_INITIAL_SEG_NIC_INTERFACE_FULL_DRIVER = 0x0,
68786938
MLX5_INITIAL_SEG_NIC_INTERFACE_DISABLED = 0x1,

include/linux/mlx5/port.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,7 @@ int mlx5_modify_port_ets_rate_limit(struct mlx5_core_dev *mdev,
8181
int mlx5_query_port_ets_rate_limit(struct mlx5_core_dev *mdev,
8282
u8 *max_bw_value,
8383
u8 *max_bw_unit);
84+
int mlx5_set_port_wol(struct mlx5_core_dev *mdev, u8 wol_mode);
85+
int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode);
8486

8587
#endif /* __MLX5_PORT_H__ */

0 commit comments

Comments
 (0)