2 * Copyright (c) 2016, Mellanox Technologies, Ltd. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 #include <linux/prefetch.h>
35 #include <linux/udp.h>
49 const char mlx5e_self_tests
[MLX5E_ST_NUM
][ETH_GSTRING_LEN
] = {
58 int mlx5e_self_test_num(struct mlx5e_priv
*priv
)
60 return ARRAY_SIZE(mlx5e_self_tests
);
63 static int mlx5e_test_health_info(struct mlx5e_priv
*priv
)
65 struct mlx5_core_health
*health
= &priv
->mdev
->priv
.health
;
67 return health
->sick
? 1 : 0;
70 static int mlx5e_test_link_state(struct mlx5e_priv
*priv
)
74 if (!netif_carrier_ok(priv
->netdev
))
77 port_state
= mlx5_query_vport_state(priv
->mdev
, MLX5_QUERY_VPORT_STATE_IN_OP_MOD_VNIC_VPORT
, 0);
78 return port_state
== VPORT_STATE_UP
? 0 : 1;
81 static int mlx5e_test_link_speed(struct mlx5e_priv
*priv
)
83 u32 out
[MLX5_ST_SZ_DW(ptys_reg
)];
87 if (!netif_carrier_ok(priv
->netdev
))
90 if (mlx5_query_port_ptys(priv
->mdev
, out
, sizeof(out
), MLX5_PTYS_EN
, 1))
93 eth_proto_oper
= MLX5_GET(ptys_reg
, out
, eth_proto_oper
);
94 for (i
= 0; i
< MLX5E_LINK_MODES_NUMBER
; i
++) {
95 if (eth_proto_oper
& MLX5E_PROT_MASK(i
))
103 #define MLX5E_TEST_PKT_SIZE (MLX5_MPWRQ_SMALL_PACKET_THRESHOLD - NET_IP_ALIGN)
104 static const char mlx5e_test_text
[ETH_GSTRING_LEN
] = "MLX5E SELF TEST";
105 #define MLX5E_TEST_MAGIC 0x5AEED15C001ULL
110 char text
[ETH_GSTRING_LEN
];
113 static struct sk_buff
*mlx5e_test_get_udp_skb(struct mlx5e_priv
*priv
)
115 struct sk_buff
*skb
= NULL
;
116 struct mlx5ehdr
*mlxh
;
122 datalen
= MLX5E_TEST_PKT_SIZE
-
123 (sizeof(*ethh
) + sizeof(*iph
) + sizeof(*udph
));
125 skb
= netdev_alloc_skb(priv
->netdev
, MLX5E_TEST_PKT_SIZE
);
127 netdev_err(priv
->netdev
, "\tFailed to alloc loopback skb\n");
131 prefetchw(skb
->data
);
132 skb_reserve(skb
, NET_IP_ALIGN
);
134 /* Reserve for ethernet and IP header */
135 ethh
= skb_push(skb
, ETH_HLEN
);
136 skb_reset_mac_header(skb
);
138 skb_set_network_header(skb
, skb
->len
);
139 iph
= skb_put(skb
, sizeof(struct iphdr
));
141 skb_set_transport_header(skb
, skb
->len
);
142 udph
= skb_put(skb
, sizeof(struct udphdr
));
144 /* Fill ETH header */
145 ether_addr_copy(ethh
->h_dest
, priv
->netdev
->dev_addr
);
146 eth_zero_addr(ethh
->h_source
);
147 ethh
->h_proto
= htons(ETH_P_IP
);
149 /* Fill UDP header */
150 udph
->source
= htons(9);
151 udph
->dest
= htons(9); /* Discard Protocol */
152 udph
->len
= htons(datalen
+ sizeof(struct udphdr
));
159 iph
->protocol
= IPPROTO_UDP
;
160 iplen
= sizeof(struct iphdr
) + sizeof(struct udphdr
) + datalen
;
161 iph
->tot_len
= htons(iplen
);
169 /* Fill test header and data */
170 mlxh
= skb_put(skb
, sizeof(*mlxh
));
172 mlxh
->magic
= cpu_to_be64(MLX5E_TEST_MAGIC
);
173 strlcpy(mlxh
->text
, mlx5e_test_text
, sizeof(mlxh
->text
));
174 datalen
-= sizeof(*mlxh
);
175 skb_put_zero(skb
, datalen
);
178 skb
->ip_summed
= CHECKSUM_PARTIAL
;
179 udp4_hwcsum(skb
, iph
->saddr
, iph
->daddr
);
181 skb
->protocol
= htons(ETH_P_IP
);
182 skb
->pkt_type
= PACKET_HOST
;
183 skb
->dev
= priv
->netdev
;
188 struct mlx5e_lbt_priv
{
189 struct packet_type pt
;
190 struct completion comp
;
196 mlx5e_test_loopback_validate(struct sk_buff
*skb
,
197 struct net_device
*ndev
,
198 struct packet_type
*pt
,
199 struct net_device
*orig_ndev
)
201 struct mlx5e_lbt_priv
*lbtp
= pt
->af_packet_priv
;
202 struct mlx5ehdr
*mlxh
;
207 /* We are only going to peek, no need to clone the SKB */
208 if (MLX5E_TEST_PKT_SIZE
- ETH_HLEN
> skb_headlen(skb
))
211 ethh
= (struct ethhdr
*)skb_mac_header(skb
);
212 if (!ether_addr_equal(ethh
->h_dest
, orig_ndev
->dev_addr
))
216 if (iph
->protocol
!= IPPROTO_UDP
)
220 if (udph
->dest
!= htons(9))
223 mlxh
= (struct mlx5ehdr
*)((char *)udph
+ sizeof(*udph
));
224 if (mlxh
->magic
!= cpu_to_be64(MLX5E_TEST_MAGIC
))
225 goto out
; /* so close ! */
228 lbtp
->loopback_ok
= true;
229 complete(&lbtp
->comp
);
235 static int mlx5e_test_loopback_setup(struct mlx5e_priv
*priv
,
236 struct mlx5e_lbt_priv
*lbtp
)
240 /* Temporarily enable local_lb */
241 if (MLX5_CAP_GEN(priv
->mdev
, disable_local_lb
)) {
242 mlx5_nic_vport_query_local_lb(priv
->mdev
, &lbtp
->local_lb
);
244 mlx5_nic_vport_update_local_lb(priv
->mdev
, true);
247 err
= mlx5e_refresh_tirs(priv
, true);
251 lbtp
->loopback_ok
= false;
252 init_completion(&lbtp
->comp
);
254 lbtp
->pt
.type
= htons(ETH_P_IP
);
255 lbtp
->pt
.func
= mlx5e_test_loopback_validate
;
256 lbtp
->pt
.dev
= priv
->netdev
;
257 lbtp
->pt
.af_packet_priv
= lbtp
;
258 dev_add_pack(&lbtp
->pt
);
262 static void mlx5e_test_loopback_cleanup(struct mlx5e_priv
*priv
,
263 struct mlx5e_lbt_priv
*lbtp
)
265 if (MLX5_CAP_GEN(priv
->mdev
, disable_local_lb
)) {
267 mlx5_nic_vport_update_local_lb(priv
->mdev
, false);
270 dev_remove_pack(&lbtp
->pt
);
271 mlx5e_refresh_tirs(priv
, false);
274 #define MLX5E_LB_VERIFY_TIMEOUT (msecs_to_jiffies(200))
275 static int mlx5e_test_loopback(struct mlx5e_priv
*priv
)
277 struct mlx5e_lbt_priv
*lbtp
;
278 struct sk_buff
*skb
= NULL
;
281 if (!test_bit(MLX5E_STATE_OPENED
, &priv
->state
)) {
282 netdev_err(priv
->netdev
,
283 "\tCan't perform loobpack test while device is down\n");
287 lbtp
= kzalloc(sizeof(*lbtp
), GFP_KERNEL
);
290 lbtp
->loopback_ok
= false;
292 err
= mlx5e_test_loopback_setup(priv
, lbtp
);
296 skb
= mlx5e_test_get_udp_skb(priv
);
302 skb_set_queue_mapping(skb
, 0);
303 err
= dev_queue_xmit(skb
);
305 netdev_err(priv
->netdev
,
306 "\tFailed to xmit loopback packet err(%d)\n",
311 wait_for_completion_timeout(&lbtp
->comp
, MLX5E_LB_VERIFY_TIMEOUT
);
312 err
= !lbtp
->loopback_ok
;
315 mlx5e_test_loopback_cleanup(priv
, lbtp
);
322 static int (*mlx5e_st_func
[MLX5E_ST_NUM
])(struct mlx5e_priv
*) = {
323 mlx5e_test_link_state
,
324 mlx5e_test_link_speed
,
325 mlx5e_test_health_info
,
331 void mlx5e_self_test(struct net_device
*ndev
, struct ethtool_test
*etest
,
334 struct mlx5e_priv
*priv
= netdev_priv(ndev
);
337 memset(buf
, 0, sizeof(u64
) * MLX5E_ST_NUM
);
339 mutex_lock(&priv
->state_lock
);
340 netdev_info(ndev
, "Self test begin..\n");
342 for (i
= 0; i
< MLX5E_ST_NUM
; i
++) {
343 netdev_info(ndev
, "\t[%d] %s start..\n",
344 i
, mlx5e_self_tests
[i
]);
345 buf
[i
] = mlx5e_st_func
[i
](priv
);
346 netdev_info(ndev
, "\t[%d] %s end: result(%lld)\n",
347 i
, mlx5e_self_tests
[i
], buf
[i
]);
350 mutex_unlock(&priv
->state_lock
);
352 for (i
= 0; i
< MLX5E_ST_NUM
; i
++) {
354 etest
->flags
|= ETH_TEST_FL_FAILED
;
358 netdev_info(ndev
, "Self test out: status flags(0x%x)\n",