Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mlx4_en: Added self diagnostics test implementation

The selftest includes 5 features:
1. Interrupt test: Executing commands and receiving command completion
on all our interrupt vectors.
2. Link test: Verifying we are connected to valid link partner.
3. Speed test: Check that we negotiated link speed correctly.
4. Registers test: Activate HW health check command.
5. Loopback test: Send a packet on loopback interface and catch it on RX side.

Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yevgeny Petrilin and committed by
David S. Miller
e7c1c2c4 3005ad40

+387 -26
+1 -1
drivers/net/mlx4/Makefile
··· 6 6 obj-$(CONFIG_MLX4_EN) += mlx4_en.o 7 7 8 8 mlx4_en-y := en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \ 9 - en_resources.o en_netdev.o 9 + en_resources.o en_netdev.o en_selftest.o
+53 -24
drivers/net/mlx4/en_ethtool.c
··· 125 125 #define NUM_MAIN_STATS 21 126 126 #define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS) 127 127 128 + static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= { 129 + "Interupt Test", 130 + "Link Test", 131 + "Speed Test", 132 + "Register Test", 133 + "Loopback Test", 134 + }; 135 + 128 136 static u32 mlx4_en_get_msglevel(struct net_device *dev) 129 137 { 130 138 return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable; ··· 154 146 { 155 147 struct mlx4_en_priv *priv = netdev_priv(dev); 156 148 157 - if (sset != ETH_SS_STATS) 149 + switch (sset) { 150 + case ETH_SS_STATS: 151 + return NUM_ALL_STATS + 152 + (priv->tx_ring_num + priv->rx_ring_num) * 2; 153 + case ETH_SS_TEST: 154 + return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.loopback_support) * 2; 155 + default: 158 156 return -EOPNOTSUPP; 159 - 160 - return NUM_ALL_STATS + (priv->tx_ring_num + priv->rx_ring_num) * 2; 157 + } 161 158 } 162 159 163 160 static void mlx4_en_get_ethtool_stats(struct net_device *dev, ··· 194 181 195 182 } 196 183 184 + static void mlx4_en_self_test(struct net_device *dev, 185 + struct ethtool_test *etest, u64 *buf) 186 + { 187 + mlx4_en_ex_selftest(dev, &etest->flags, buf); 188 + } 189 + 197 190 static void mlx4_en_get_strings(struct net_device *dev, 198 191 uint32_t stringset, uint8_t *data) 199 192 { ··· 207 188 int index = 0; 208 189 int i; 209 190 210 - if (stringset != ETH_SS_STATS) 211 - return; 191 + switch (stringset) { 192 + case ETH_SS_TEST: 193 + for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++) 194 + strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]); 195 + if (priv->mdev->dev->caps.loopback_support) 196 + for (; i < MLX4_EN_NUM_SELF_TEST; i++) 197 + strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]); 198 + break; 212 199 213 - /* Add main counters */ 214 - for (i = 0; i < NUM_MAIN_STATS; i++) 215 - strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]); 216 - for (i = 0; i < NUM_PORT_STATS; i++) 217 - strcpy(data + (index++) * ETH_GSTRING_LEN, 200 + case ETH_SS_STATS: 201 + /* Add main counters */ 202 + for (i = 0; i < NUM_MAIN_STATS; i++) 203 + strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]); 204 + for (i = 0; i< NUM_PORT_STATS; i++) 205 + strcpy(data + (index++) * ETH_GSTRING_LEN, 218 206 main_strings[i + NUM_MAIN_STATS]); 219 - for (i = 0; i < priv->tx_ring_num; i++) { 220 - sprintf(data + (index++) * ETH_GSTRING_LEN, 221 - "tx%d_packets", i); 222 - sprintf(data + (index++) * ETH_GSTRING_LEN, 223 - "tx%d_bytes", i); 224 - } 225 - for (i = 0; i < priv->rx_ring_num; i++) { 226 - sprintf(data + (index++) * ETH_GSTRING_LEN, 227 - "rx%d_packets", i); 228 - sprintf(data + (index++) * ETH_GSTRING_LEN, 229 - "rx%d_bytes", i); 230 - } 231 - for (i = 0; i < NUM_PKT_STATS; i++) 232 - strcpy(data + (index++) * ETH_GSTRING_LEN, 207 + for (i = 0; i < priv->tx_ring_num; i++) { 208 + sprintf(data + (index++) * ETH_GSTRING_LEN, 209 + "tx%d_packets", i); 210 + sprintf(data + (index++) * ETH_GSTRING_LEN, 211 + "tx%d_bytes", i); 212 + } 213 + for (i = 0; i < priv->rx_ring_num; i++) { 214 + sprintf(data + (index++) * ETH_GSTRING_LEN, 215 + "rx%d_packets", i); 216 + sprintf(data + (index++) * ETH_GSTRING_LEN, 217 + "rx%d_bytes", i); 218 + } 219 + for (i = 0; i< NUM_PKT_STATS; i++) 220 + strcpy(data + (index++) * ETH_GSTRING_LEN, 233 221 main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]); 222 + break; 223 + } 234 224 } 235 225 236 226 static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ··· 467 439 .get_strings = mlx4_en_get_strings, 468 440 .get_sset_count = mlx4_en_get_sset_count, 469 441 .get_ethtool_stats = mlx4_en_get_ethtool_stats, 442 + .self_test = mlx4_en_self_test, 470 443 .get_wol = mlx4_en_get_wol, 471 444 .get_msglevel = mlx4_en_get_msglevel, 472 445 .set_msglevel = mlx4_en_set_msglevel,
+1 -1
drivers/net/mlx4/en_netdev.c
··· 109 109 mutex_unlock(&mdev->state_lock); 110 110 } 111 111 112 - static u64 mlx4_en_mac_to_u64(u8 *addr) 112 + u64 mlx4_en_mac_to_u64(u8 *addr) 113 113 { 114 114 u64 mac = 0; 115 115 int i;
+32
drivers/net/mlx4/en_port.c
··· 142 142 return err; 143 143 } 144 144 145 + int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port) 146 + { 147 + struct mlx4_en_query_port_context *qport_context; 148 + struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]); 149 + struct mlx4_en_port_state *state = &priv->port_state; 150 + struct mlx4_cmd_mailbox *mailbox; 151 + int err; 152 + 153 + mailbox = mlx4_alloc_cmd_mailbox(mdev->dev); 154 + if (IS_ERR(mailbox)) 155 + return PTR_ERR(mailbox); 156 + memset(mailbox->buf, 0, sizeof(*qport_context)); 157 + err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0, 158 + MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B); 159 + if (err) 160 + goto out; 161 + qport_context = mailbox->buf; 162 + 163 + /* This command is always accessed from Ethtool context 164 + * already synchronized, no need in locking */ 165 + state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK); 166 + if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) == 167 + MLX4_EN_1G_SPEED) 168 + state->link_speed = 1000; 169 + else 170 + state->link_speed = 10000; 171 + state->transciver = qport_context->transceiver; 172 + 173 + out: 174 + mlx4_free_cmd_mailbox(mdev->dev, mailbox); 175 + return err; 176 + } 145 177 146 178 int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) 147 179 {
+14
drivers/net/mlx4/en_port.h
··· 84 84 MLX4_MCAST_ENABLE = 2, 85 85 }; 86 86 87 + struct mlx4_en_query_port_context { 88 + u8 link_up; 89 + #define MLX4_EN_LINK_UP_MASK 0x80 90 + u8 reserved; 91 + __be16 mtu; 92 + u8 reserved2; 93 + u8 link_speed; 94 + #define MLX4_EN_SPEED_MASK 0x3 95 + #define MLX4_EN_1G_SPEED 0x2 96 + u16 reserved3[5]; 97 + __be64 mac; 98 + u8 transceiver; 99 + }; 100 + 87 101 88 102 struct mlx4_en_stat_out_mbox { 89 103 /* Received frames with a length of 64 octets */
+20
drivers/net/mlx4/en_rx.c
··· 541 541 return skb; 542 542 } 543 543 544 + static void validate_loopback(struct mlx4_en_priv *priv, struct sk_buff *skb) 545 + { 546 + int i; 547 + int offset = ETH_HLEN; 548 + 549 + for (i = 0; i < MLX4_LOOPBACK_TEST_PAYLOAD; i++, offset++) { 550 + if (*(skb->data + offset) != (unsigned char) (i & 0xff)) 551 + goto out_loopback; 552 + } 553 + /* Loopback found */ 554 + priv->loopback_ok = 1; 555 + 556 + out_loopback: 557 + dev_kfree_skb_any(skb); 558 + } 544 559 545 560 int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) 546 561 { ··· 667 652 ring->page_alloc, length); 668 653 if (!skb) { 669 654 priv->stats.rx_dropped++; 655 + goto next; 656 + } 657 + 658 + if (unlikely(priv->validate_loopback)) { 659 + validate_loopback(priv, skb); 670 660 goto next; 671 661 } 672 662
+179
drivers/net/mlx4/en_selftest.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 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: 9 + * 10 + * Redistribution and use in source and binary forms, with or 11 + * without modification, are permitted provided that the following 12 + * conditions are met: 13 + * 14 + * - Redistributions of source code must retain the above 15 + * copyright notice, this list of conditions and the following 16 + * disclaimer. 17 + * 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. 22 + * 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 30 + * 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 + 43 + static 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); 47 + } 48 + 49 + static 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 + en_err(priv, "-LOOPBACK_TEST_XMIT- failed to create skb for xmit\n"); 63 + return -ENOMEM; 64 + } 65 + skb_reserve(skb, NET_IP_ALIGN); 66 + 67 + ethh = (struct ethhdr *)skb_put(skb, sizeof(struct ethhdr)); 68 + packet = (unsigned char *)skb_put(skb, packet_size); 69 + memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN); 70 + memset(ethh->h_source, 0, ETH_ALEN); 71 + ethh->h_proto = htons(ETH_P_ARP); 72 + skb_set_mac_header(skb, 0); 73 + for (i = 0; i < packet_size; ++i) /* fill our packet */ 74 + packet[i] = (unsigned char)(i & 0xff); 75 + 76 + /* xmit the pkt */ 77 + err = mlx4_en_xmit(skb, priv->dev); 78 + return err; 79 + } 80 + 81 + static int mlx4_en_test_loopback(struct mlx4_en_priv *priv) 82 + { 83 + u32 loopback_ok = 0; 84 + int i; 85 + 86 + 87 + priv->loopback_ok = 0; 88 + priv->validate_loopback = 1; 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 + 107 + mlx4_en_test_loopback_exit: 108 + 109 + priv->validate_loopback = 0; 110 + return (!loopback_ok); 111 + } 112 + 113 + 114 + static int mlx4_en_test_link(struct mlx4_en_priv *priv) 115 + { 116 + if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) 117 + return -ENOMEM; 118 + if (priv->port_state.link_state == 1) 119 + return 0; 120 + else 121 + return 1; 122 + } 123 + 124 + static int mlx4_en_test_speed(struct mlx4_en_priv *priv) 125 + { 126 + 127 + if (mlx4_en_QUERY_PORT(priv->mdev, priv->port)) 128 + return -ENOMEM; 129 + 130 + /* The device currently only supports 10G speed */ 131 + if (priv->port_state.link_speed != SPEED_10000) 132 + return priv->port_state.link_speed; 133 + return 0; 134 + } 135 + 136 + 137 + void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf) 138 + { 139 + struct mlx4_en_priv *priv = netdev_priv(dev); 140 + struct mlx4_en_dev *mdev = priv->mdev; 141 + struct mlx4_en_tx_ring *tx_ring; 142 + int i, carrier_ok; 143 + 144 + memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST); 145 + 146 + if (*flags & ETH_TEST_FL_OFFLINE) { 147 + /* disable the interface */ 148 + carrier_ok = netif_carrier_ok(dev); 149 + 150 + netif_carrier_off(dev); 151 + retry_tx: 152 + /* Wait untill all tx queues are empty. 153 + * there should not be any additional incoming traffic 154 + * since we turned the carrier off */ 155 + msleep(200); 156 + for (i = 0; i < priv->tx_ring_num && carrier_ok; i++) { 157 + tx_ring = &priv->tx_ring[i]; 158 + if (tx_ring->prod != (tx_ring->cons + tx_ring->last_nr_txbb)) 159 + goto retry_tx; 160 + } 161 + 162 + if (priv->mdev->dev->caps.loopback_support){ 163 + buf[3] = mlx4_en_test_registers(priv); 164 + buf[4] = mlx4_en_test_loopback(priv); 165 + } 166 + 167 + if (carrier_ok) 168 + netif_carrier_on(dev); 169 + 170 + } 171 + buf[0] = mlx4_test_interrupts(mdev->dev); 172 + buf[1] = mlx4_en_test_link(priv); 173 + buf[2] = mlx4_en_test_speed(priv); 174 + 175 + for (i = 0; i < MLX4_EN_NUM_SELF_TEST; i++) { 176 + if (buf[i]) 177 + *flags |= ETH_TEST_FL_FAILED; 178 + } 179 + }
+16
drivers/net/mlx4/en_tx.c
··· 600 600 struct mlx4_wqe_data_seg *data; 601 601 struct skb_frag_struct *frag; 602 602 struct mlx4_en_tx_info *tx_info; 603 + struct ethhdr *ethh; 604 + u64 mac; 605 + u32 mac_l, mac_h; 603 606 int tx_ind = 0; 604 607 int nr_txbb; 605 608 int desc_size; ··· 680 677 tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM | 681 678 MLX4_WQE_CTRL_TCP_UDP_CSUM); 682 679 priv->port_stats.tx_chksum_offload++; 680 + } 681 + 682 + if (unlikely(priv->validate_loopback)) { 683 + /* Copy dst mac address to wqe */ 684 + skb_reset_mac_header(skb); 685 + ethh = eth_hdr(skb); 686 + if (ethh && ethh->h_dest) { 687 + mac = mlx4_en_mac_to_u64(ethh->h_dest); 688 + mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16); 689 + mac_l = (u32) (mac & 0xffffffff); 690 + tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h); 691 + tx_desc->ctrl.imm = cpu_to_be32(mac_l); 692 + } 683 693 } 684 694 685 695 /* Handle LSO (TSO) packets */
+44
drivers/net/mlx4/eq.c
··· 699 699 700 700 kfree(priv->eq_table.uar_map); 701 701 } 702 + 703 + /* A test that verifies that we can accept interrupts on all 704 + * the irq vectors of the device. 705 + * Interrupts are checked using the NOP command. 706 + */ 707 + int mlx4_test_interrupts(struct mlx4_dev *dev) 708 + { 709 + struct mlx4_priv *priv = mlx4_priv(dev); 710 + int i; 711 + int err; 712 + 713 + err = mlx4_NOP(dev); 714 + /* When not in MSI_X, there is only one irq to check */ 715 + if (!(dev->flags & MLX4_FLAG_MSI_X)) 716 + return err; 717 + 718 + /* A loop over all completion vectors, for each vector we will check 719 + * whether it works by mapping command completions to that vector 720 + * and performing a NOP command 721 + */ 722 + for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) { 723 + /* Temporary use polling for command completions */ 724 + mlx4_cmd_use_polling(dev); 725 + 726 + /* Map the new eq to handle all asyncronous events */ 727 + err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0, 728 + priv->eq_table.eq[i].eqn); 729 + if (err) { 730 + mlx4_warn(dev, "Failed mapping eq for interrupt test\n"); 731 + mlx4_cmd_use_events(dev); 732 + break; 733 + } 734 + 735 + /* Go back to using events */ 736 + mlx4_cmd_use_events(dev); 737 + err = mlx4_NOP(dev); 738 + } 739 + 740 + /* Return to default */ 741 + mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0, 742 + priv->eq_table.eq[dev->caps.num_comp_vectors].eqn); 743 + return err; 744 + } 745 + EXPORT_SYMBOL(mlx4_test_interrupts);
+3
drivers/net/mlx4/fw.c
··· 178 178 #define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b 179 179 #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c 180 180 #define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f 181 + #define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET 0x43 181 182 #define QUERY_DEV_CAP_FLAGS_OFFSET 0x44 182 183 #define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48 183 184 #define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49 ··· 269 268 dev_cap->max_msg_sz = 1 << (field & 0x1f); 270 269 MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); 271 270 dev_cap->stat_rate_support = stat_rate; 271 + MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET); 272 + dev_cap->loopback_support = field & 0x1; 272 273 MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); 273 274 MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); 274 275 dev_cap->reserved_uars = field >> 4;
+1
drivers/net/mlx4/fw.h
··· 74 74 u64 def_mac[MLX4_MAX_PORTS + 1]; 75 75 u16 eth_mtu[MLX4_MAX_PORTS + 1]; 76 76 u16 stat_rate_support; 77 + int loopback_support; 77 78 u32 flags; 78 79 int reserved_uars; 79 80 int uar_size;
+1
drivers/net/mlx4/main.c
··· 221 221 dev->caps.bmme_flags = dev_cap->bmme_flags; 222 222 dev->caps.reserved_lkey = dev_cap->reserved_lkey; 223 223 dev->caps.stat_rate_support = dev_cap->stat_rate_support; 224 + dev->caps.loopback_support = dev_cap->loopback_support; 224 225 dev->caps.max_gso_sz = dev_cap->max_gso_sz; 225 226 226 227 dev->caps.log_num_macs = log_num_mac;
+19
drivers/net/mlx4/mlx4_en.h
··· 45 45 #include <linux/mlx4/cq.h> 46 46 #include <linux/mlx4/srq.h> 47 47 #include <linux/mlx4/doorbell.h> 48 + #include <linux/mlx4/cmd.h> 48 49 49 50 #include "en_port.h" 50 51 ··· 140 139 141 140 #define SMALL_PACKET_SIZE (256 - NET_IP_ALIGN) 142 141 #define HEADER_COPY_SIZE (128 - NET_IP_ALIGN) 142 + #define MLX4_LOOPBACK_TEST_PAYLOAD (HEADER_COPY_SIZE - ETH_HLEN) 143 143 144 144 #define MLX4_EN_MIN_MTU 46 145 145 #define ETH_BCAST 0xffffffffffffULL 146 + 147 + #define MLX4_EN_LOOPBACK_RETRIES 5 148 + #define MLX4_EN_LOOPBACK_TIMEOUT 100 146 149 147 150 #ifdef MLX4_EN_PERF_STAT 148 151 /* Number of samples to 'average' */ ··· 361 356 __be32 rss_key[10]; 362 357 }; 363 358 359 + struct mlx4_en_port_state { 360 + int link_state; 361 + int link_speed; 362 + int transciver; 363 + }; 364 + 364 365 struct mlx4_en_pkt_stats { 365 366 unsigned long broadcast; 366 367 unsigned long rx_prio[8]; ··· 415 404 struct vlan_group *vlgrp; 416 405 struct net_device_stats stats; 417 406 struct net_device_stats ret_stats; 407 + struct mlx4_en_port_state port_state; 418 408 spinlock_t stats_lock; 419 409 420 410 unsigned long last_moder_packets; ··· 434 422 u16 sample_interval; 435 423 u16 adaptive_rx_coal; 436 424 u32 msg_enable; 425 + u32 loopback_ok; 426 + u32 validate_loopback; 437 427 438 428 struct mlx4_hwq_resources res; 439 429 int link_state; ··· 544 530 u8 promisc); 545 531 546 532 int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset); 533 + int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port); 534 + 535 + #define MLX4_EN_NUM_SELF_TEST 5 536 + void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf); 537 + u64 mlx4_en_mac_to_u64(u8 *addr); 547 538 548 539 /* 549 540 * Globals
+1
include/linux/mlx4/cmd.h
··· 56 56 MLX4_CMD_QUERY_HCA = 0xb, 57 57 MLX4_CMD_QUERY_PORT = 0x43, 58 58 MLX4_CMD_SENSE_PORT = 0x4d, 59 + MLX4_CMD_HW_HEALTH_CHECK = 0x50, 59 60 MLX4_CMD_SET_PORT = 0xc, 60 61 MLX4_CMD_ACCESS_DDR = 0x2e, 61 62 MLX4_CMD_MAP_ICM = 0xffa,
+2
include/linux/mlx4/device.h
··· 229 229 u32 bmme_flags; 230 230 u32 reserved_lkey; 231 231 u16 stat_rate_support; 232 + int loopback_support; 232 233 u8 port_width_cap[MLX4_MAX_PORTS + 1]; 233 234 int max_gso_sz; 234 235 int reserved_qps_cnt[MLX4_NUM_QP_REGION]; ··· 481 480 u32 *lkey, u32 *rkey); 482 481 int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr); 483 482 int mlx4_SYNC_TPT(struct mlx4_dev *dev); 483 + int mlx4_test_interrupts(struct mlx4_dev *dev); 484 484 485 485 #endif /* MLX4_DEVICE_H */