brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · 946d9db Raw
205 lines · c
1/*2 * Copyright (c) 2007 Mellanox Technologies. All rights reserved.3 *4 * This software is available to you under a choice of one of two5 * licenses.  You may choose to be licensed under the terms of the GNU6 * General Public License (GPL) Version 2, available from the file7 * COPYING in the main directory of this source tree, or the8 * OpenIB.org BSD license below:9 *10 *     Redistribution and use in source and binary forms, with or11 *     without modification, are permitted provided that the following12 *     conditions are met:13 *14 *      - Redistributions of source code must retain the above15 *        copyright notice, this list of conditions and the following16 *        disclaimer.17 *18 *      - Redistributions in binary form must reproduce the above19 *        copyright notice, this list of conditions and the following20 *        disclaimer in the documentation and/or other materials21 *        provided with the distribution.22 *23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE30 * SOFTWARE.31 *32 */33 34#include <linux/kernel.h>35#include <linux/ethtool.h>36#include <linux/netdevice.h>37#include <linux/delay.h>38#include <linux/mlx4/driver.h>39 40#include "mlx4_en.h"41 42 43static int mlx4_en_test_registers(struct mlx4_en_priv *priv)44{45	return mlx4_cmd(priv->mdev->dev, 0, 0, 0, MLX4_CMD_HW_HEALTH_CHECK,46			MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);47}48 49static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv)50{51	struct sk_buff *skb;52	struct ethhdr *ethh;53	unsigned char *packet;54	unsigned int packet_size = MLX4_LOOPBACK_TEST_PAYLOAD;55	unsigned int i;56	int err;57 58 59	/* build the pkt before xmit */60	skb = netdev_alloc_skb(priv->dev, MLX4_LOOPBACK_TEST_PAYLOAD + ETH_HLEN + NET_IP_ALIGN);61	if (!skb)62		return -ENOMEM;63 64	skb_reserve(skb, NET_IP_ALIGN);65 66	ethh = skb_put(skb, sizeof(struct ethhdr));67	packet = skb_put(skb, packet_size);68	memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN);69	eth_zero_addr(ethh->h_source);70	ethh->h_proto = htons(ETH_P_ARP);71	skb_reset_mac_header(skb);72	for (i = 0; i < packet_size; ++i)	/* fill our packet */73		packet[i] = (unsigned char)(i & 0xff);74 75	/* xmit the pkt */76	err = mlx4_en_xmit(skb, priv->dev);77	return err;78}79 80static int mlx4_en_test_loopback(struct mlx4_en_priv *priv)81{82	u32 loopback_ok = 0;83	int i;84 85        priv->loopback_ok = 0;86	priv->validate_loopback = 1;87 88	mlx4_en_update_loopback_state(priv->dev, priv->dev->features);89 90	/* xmit */91	if (mlx4_en_test_loopback_xmit(priv)) {92		en_err(priv, "Transmitting loopback packet failed\n");93		goto mlx4_en_test_loopback_exit;94	}95 96	/* polling for result */97	for (i = 0; i < MLX4_EN_LOOPBACK_RETRIES; ++i) {98		msleep(MLX4_EN_LOOPBACK_TIMEOUT);99		if (priv->loopback_ok) {100			loopback_ok = 1;101			break;102		}103	}104	if (!loopback_ok)105		en_err(priv, "Loopback packet didn't arrive\n");106 107mlx4_en_test_loopback_exit:108 109	priv->validate_loopback = 0;110 111	mlx4_en_update_loopback_state(priv->dev, priv->dev->features);112	return !loopback_ok;113}114 115static int mlx4_en_test_interrupts(struct mlx4_en_priv *priv)116{117	struct mlx4_en_dev *mdev = priv->mdev;118	int err = 0;119	int i = 0;120 121	err = mlx4_test_async(mdev->dev);122	/* When not in MSI_X or slave, test only async */123	if (!(mdev->dev->flags & MLX4_FLAG_MSI_X) || mlx4_is_slave(mdev->dev))124		return err;125 126	/* A loop over all completion vectors of current port,127	 * for each vector check whether it works by mapping command128	 * completions to that vector and performing a NOP command129	 */130	for (i = 0; i < priv->rx_ring_num; i++) {131		err = mlx4_test_interrupt(mdev->dev, priv->rx_cq[i]->vector);132		if (err)133			break;134	}135 136	return err;137}138 139static int mlx4_en_test_link(struct mlx4_en_priv *priv)140{141	if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))142		return -ENOMEM;143	if (priv->port_state.link_state == 1)144		return 0;145	else146		return 1;147}148 149static int mlx4_en_test_speed(struct mlx4_en_priv *priv)150{151 152	if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))153		return -ENOMEM;154 155	/* The device supports 100M, 1G, 10G, 20G, 40G and 56G speed */156	if (priv->port_state.link_speed != SPEED_100 &&157	    priv->port_state.link_speed != SPEED_1000 &&158	    priv->port_state.link_speed != SPEED_10000 &&159	    priv->port_state.link_speed != SPEED_20000 &&160	    priv->port_state.link_speed != SPEED_40000 &&161	    priv->port_state.link_speed != SPEED_56000)162		return priv->port_state.link_speed;163 164	return 0;165}166 167 168void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)169{170	struct mlx4_en_priv *priv = netdev_priv(dev);171	int i, carrier_ok;172 173	memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);174 175	if (*flags & ETH_TEST_FL_OFFLINE) {176		/* disable the interface */177		carrier_ok = netif_carrier_ok(dev);178 179		netif_carrier_off(dev);180		/* Wait until all tx queues are empty.181		 * there should not be any additional incoming traffic182		 * since we turned the carrier off */183		msleep(200);184 185		if (priv->mdev->dev->caps.flags &186					MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {187			buf[3] = mlx4_en_test_registers(priv);188			if (priv->port_up && dev->mtu >= MLX4_SELFTEST_LB_MIN_MTU)189				buf[4] = mlx4_en_test_loopback(priv);190		}191 192		if (carrier_ok)193			netif_carrier_on(dev);194 195	}196	buf[0] = mlx4_en_test_interrupts(priv);197	buf[1] = mlx4_en_test_link(priv);198	buf[2] = mlx4_en_test_speed(priv);199 200	for (i = 0; i < MLX4_EN_NUM_SELF_TEST; i++) {201		if (buf[i])202			*flags |= ETH_TEST_FL_FAILED;203	}204}205