1219820Sjeff/* 2219820Sjeff * Copyright (c) 2007 Mellanox Technologies. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff * 32219820Sjeff */ 33219820Sjeff 34219820Sjeff 35219820Sjeff#include "mlx4_en.h" 36219820Sjeff 37219820Sjeff#include <linux/if_vlan.h> 38219820Sjeff 39219820Sjeff#include <linux/mlx4/device.h> 40219820Sjeff#include <linux/mlx4/cmd.h> 41219820Sjeff 42219820Sjeff 43219820Sjeffint mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, 44219820Sjeff u64 mac, u64 clear, u8 mode) 45219820Sjeff{ 46219820Sjeff return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, 47219820Sjeff MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B); 48219820Sjeff} 49219820Sjeff 50219820Sjeffint mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, u32 *vlans) 51219820Sjeff{ 52219820Sjeff struct mlx4_cmd_mailbox *mailbox; 53219820Sjeff struct mlx4_set_vlan_fltr_mbox *filter; 54219893Sjeff int i, j; 55219820Sjeff int err = 0; 56219820Sjeff 57219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 58219820Sjeff if (IS_ERR(mailbox)) 59219820Sjeff return PTR_ERR(mailbox); 60219820Sjeff 61219820Sjeff filter = mailbox->buf; 62219820Sjeff memset(filter, 0, sizeof *filter); 63219820Sjeff if (vlans) 64219893Sjeff for (i = 0, j = VLAN_FLTR_SIZE - 1; i < VLAN_FLTR_SIZE; 65219893Sjeff i++, j--) 66219893Sjeff filter->entry[j] = cpu_to_be32(vlans[i]); 67219820Sjeff err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR, 68219820Sjeff MLX4_CMD_TIME_CLASS_B); 69219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 70219820Sjeff return err; 71219820Sjeff} 72219820Sjeff 73219820Sjeff 74219820Sjeffint mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, 75219820Sjeff u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) 76219820Sjeff{ 77219820Sjeff struct mlx4_cmd_mailbox *mailbox; 78219820Sjeff struct mlx4_set_port_general_context *context; 79219820Sjeff int err; 80219820Sjeff u32 in_mod; 81219820Sjeff 82219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 83219820Sjeff if (IS_ERR(mailbox)) 84219820Sjeff return PTR_ERR(mailbox); 85219820Sjeff context = mailbox->buf; 86219820Sjeff memset(context, 0, sizeof *context); 87219820Sjeff 88219820Sjeff context->flags = SET_PORT_GEN_ALL_VALID; 89219820Sjeff context->mtu = cpu_to_be16(mtu); 90219820Sjeff context->pptx = (pptx * (!pfctx)) << 7; 91219820Sjeff context->pfctx = pfctx; 92219820Sjeff context->pprx = (pprx * (!pfcrx)) << 7; 93219820Sjeff context->pfcrx = pfcrx; 94219820Sjeff 95219820Sjeff in_mod = MLX4_SET_PORT_GENERAL << 8 | port; 96219820Sjeff err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 97219820Sjeff MLX4_CMD_TIME_CLASS_B); 98219820Sjeff 99219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 100219820Sjeff return err; 101219820Sjeff} 102219820Sjeff 103219820Sjeffint mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, 104219820Sjeff u8 promisc) 105219820Sjeff{ 106219820Sjeff struct mlx4_cmd_mailbox *mailbox; 107219820Sjeff struct mlx4_set_port_rqp_calc_context *context; 108219820Sjeff int err; 109219820Sjeff u32 in_mod; 110219820Sjeff 111219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 112219820Sjeff if (IS_ERR(mailbox)) 113219820Sjeff return PTR_ERR(mailbox); 114219820Sjeff context = mailbox->buf; 115219820Sjeff memset(context, 0, sizeof *context); 116219820Sjeff 117219820Sjeff context->base_qpn = cpu_to_be32(base_qpn); 118219820Sjeff context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn); 119219820Sjeff context->mcast = cpu_to_be32((dev->caps.mc_promisc_mode << 120219820Sjeff SET_PORT_PROMISC_MODE_SHIFT) | base_qpn); 121219820Sjeff context->intra_no_vlan = 0; 122219820Sjeff context->no_vlan = MLX4_NO_VLAN_IDX; 123219820Sjeff context->intra_vlan_miss = 0; 124219820Sjeff context->vlan_miss = MLX4_VLAN_MISS_IDX; 125219820Sjeff 126219820Sjeff in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; 127219820Sjeff err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 128219820Sjeff MLX4_CMD_TIME_CLASS_B); 129219820Sjeff 130219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 131219820Sjeff return err; 132219820Sjeff} 133219820Sjeff 134219820Sjeffint mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port) 135219820Sjeff{ 136219820Sjeff struct mlx4_en_query_port_context *qport_context; 137219820Sjeff struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]); 138219820Sjeff struct mlx4_en_port_state *state = &priv->port_state; 139219820Sjeff struct mlx4_cmd_mailbox *mailbox; 140219820Sjeff int err; 141219820Sjeff 142219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(mdev->dev); 143219820Sjeff if (IS_ERR(mailbox)) 144219820Sjeff return PTR_ERR(mailbox); 145219820Sjeff memset(mailbox->buf, 0, sizeof(*qport_context)); 146219820Sjeff err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0, 147219820Sjeff MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B); 148219820Sjeff if (err) 149219820Sjeff goto out; 150219820Sjeff qport_context = mailbox->buf; 151219820Sjeff 152219820Sjeff /* This command is always accessed from Ethtool context 153219820Sjeff * already synchronized, no need in locking */ 154219820Sjeff state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK); 155236316Sjhb switch (qport_context->link_speed & MLX4_EN_SPEED_MASK) { 156236316Sjhb case MLX4_EN_1G_SPEED: 157219820Sjeff state->link_speed = 1000; 158236316Sjhb break; 159236316Sjhb case MLX4_EN_10G_SPEED_XAUI: 160236316Sjhb case MLX4_EN_10G_SPEED_XFI: 161219820Sjeff state->link_speed = 10000; 162236316Sjhb break; 163236316Sjhb case MLX4_EN_40G_SPEED: 164236316Sjhb state->link_speed = 40000; 165236316Sjhb break; 166236316Sjhb default: 167236316Sjhb state->link_speed = -1; 168236316Sjhb break; 169236316Sjhb } 170219820Sjeff state->transciver = qport_context->transceiver; 171219820Sjeff if (be32_to_cpu(qport_context->transceiver_code_hi) & 0x400) 172219820Sjeff state->transciver = 0x80; 173219820Sjeff 174219820Sjeffout: 175219820Sjeff mlx4_free_cmd_mailbox(mdev->dev, mailbox); 176219820Sjeff return err; 177219820Sjeff} 178219820Sjeff 179219820Sjeffstatic int read_iboe_counters(struct mlx4_dev *dev, int index, u64 counters[]) 180219820Sjeff{ 181219820Sjeff struct mlx4_cmd_mailbox *mailbox; 182219820Sjeff int err; 183219820Sjeff int mode; 184219820Sjeff struct mlx4_counters_ext *ext; 185219820Sjeff struct mlx4_counters *reg; 186219820Sjeff 187219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 188219820Sjeff if (IS_ERR(mailbox)) 189219820Sjeff return -ENOMEM; 190219820Sjeff 191219820Sjeff err = mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, 192219820Sjeff MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C); 193219820Sjeff if (err) 194219820Sjeff goto out; 195219820Sjeff 196219820Sjeff mode = be32_to_cpu(((struct mlx4_counters *)mailbox->buf)->counter_mode) & 0xf; 197219820Sjeff switch (mode) { 198219820Sjeff case 0: 199219820Sjeff reg = mailbox->buf; 200219820Sjeff counters[0] = be64_to_cpu(reg->rx_frames); 201219820Sjeff counters[1] = be64_to_cpu(reg->tx_frames); 202219820Sjeff counters[2] = be64_to_cpu(reg->rx_bytes); 203219820Sjeff counters[3] = be64_to_cpu(reg->tx_bytes); 204219820Sjeff break; 205219820Sjeff case 1: 206219820Sjeff ext = mailbox->buf; 207219820Sjeff counters[0] = be64_to_cpu(ext->rx_uni_frames); 208219820Sjeff counters[1] = be64_to_cpu(ext->tx_uni_frames); 209219820Sjeff counters[2] = be64_to_cpu(ext->rx_uni_bytes); 210219820Sjeff counters[3] = be64_to_cpu(ext->tx_uni_bytes); 211219820Sjeff break; 212219820Sjeff default: 213219820Sjeff err = -EINVAL; 214219820Sjeff } 215219820Sjeff 216219820Sjeffout: 217219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 218219820Sjeff return err; 219219820Sjeff} 220219820Sjeff 221219820Sjeffint mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) 222219820Sjeff{ 223219820Sjeff struct mlx4_en_stat_out_mbox *mlx4_en_stats; 224219820Sjeff struct net_device *dev; 225219820Sjeff struct mlx4_en_priv *priv; 226219820Sjeff struct mlx4_cmd_mailbox *mailbox; 227219820Sjeff u64 in_mod = reset << 8 | port; 228219820Sjeff unsigned long oerror; 229219820Sjeff unsigned long ierror; 230219820Sjeff int err; 231219820Sjeff int i; 232219820Sjeff int counter; 233219820Sjeff u64 counters[4]; 234219820Sjeff 235219820Sjeff dev = mdev->pndev[port]; 236219820Sjeff priv = netdev_priv(dev); 237219820Sjeff memset(counters, 0, sizeof counters); 238219820Sjeff counter = mlx4_get_iboe_counter(priv->mdev->dev, port); 239219820Sjeff if (counter >= 0) 240219820Sjeff err = read_iboe_counters(priv->mdev->dev, counter, counters); 241219820Sjeff 242219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(mdev->dev); 243219820Sjeff if (IS_ERR(mailbox)) 244219820Sjeff return PTR_ERR(mailbox); 245219820Sjeff memset(mailbox->buf, 0, sizeof(*mlx4_en_stats)); 246219820Sjeff err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0, 247219820Sjeff MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B); 248219820Sjeff if (err) 249219820Sjeff goto out; 250219820Sjeff 251219820Sjeff mlx4_en_stats = mailbox->buf; 252219820Sjeff 253219820Sjeff spin_lock(&priv->stats_lock); 254219820Sjeff 255219820Sjeff oerror = ierror = 0; 256219820Sjeff dev->if_ipackets = counters[0]; 257219820Sjeff dev->if_ibytes = counters[2]; 258219820Sjeff for (i = 0; i < priv->rx_ring_num; i++) { 259219820Sjeff dev->if_ipackets += priv->rx_ring[i].packets; 260219820Sjeff dev->if_ibytes += priv->rx_ring[i].bytes; 261219820Sjeff ierror += priv->rx_ring[i].errors; 262219820Sjeff } 263219820Sjeff dev->if_opackets = counters[1]; 264219820Sjeff dev->if_obytes = counters[3]; 265219820Sjeff for (i = 0; i <= priv->tx_ring_num; i++) { 266219820Sjeff dev->if_opackets += priv->tx_ring[i].packets; 267219820Sjeff dev->if_obytes += priv->tx_ring[i].bytes; 268219820Sjeff oerror += priv->tx_ring[i].errors; 269219820Sjeff } 270219820Sjeff 271219820Sjeff dev->if_ierrors = be32_to_cpu(mlx4_en_stats->RDROP) + ierror; 272219820Sjeff dev->if_oerrors = be32_to_cpu(mlx4_en_stats->TDROP) + oerror; 273219820Sjeff dev->if_imcasts = be64_to_cpu(mlx4_en_stats->MCAST_prio_0) + 274219820Sjeff be64_to_cpu(mlx4_en_stats->MCAST_prio_1) + 275219820Sjeff be64_to_cpu(mlx4_en_stats->MCAST_prio_2) + 276219820Sjeff be64_to_cpu(mlx4_en_stats->MCAST_prio_3) + 277219820Sjeff be64_to_cpu(mlx4_en_stats->MCAST_prio_4) + 278219820Sjeff be64_to_cpu(mlx4_en_stats->MCAST_prio_5) + 279219820Sjeff be64_to_cpu(mlx4_en_stats->MCAST_prio_6) + 280219820Sjeff be64_to_cpu(mlx4_en_stats->MCAST_prio_7) + 281219820Sjeff be64_to_cpu(mlx4_en_stats->MCAST_novlan); 282219820Sjeff dev->if_omcasts = be64_to_cpu(mlx4_en_stats->TMCAST_prio_0) + 283219820Sjeff be64_to_cpu(mlx4_en_stats->TMCAST_prio_1) + 284219820Sjeff be64_to_cpu(mlx4_en_stats->TMCAST_prio_2) + 285219820Sjeff be64_to_cpu(mlx4_en_stats->TMCAST_prio_3) + 286219820Sjeff be64_to_cpu(mlx4_en_stats->TMCAST_prio_4) + 287219820Sjeff be64_to_cpu(mlx4_en_stats->TMCAST_prio_5) + 288219820Sjeff be64_to_cpu(mlx4_en_stats->TMCAST_prio_6) + 289219820Sjeff be64_to_cpu(mlx4_en_stats->TMCAST_prio_7) + 290219820Sjeff be64_to_cpu(mlx4_en_stats->TMCAST_novlan); 291219820Sjeff dev->if_collisions = 0; 292219820Sjeff 293219820Sjeff priv->pkstats.broadcast = 294219820Sjeff be64_to_cpu(mlx4_en_stats->RBCAST_prio_0) + 295219820Sjeff be64_to_cpu(mlx4_en_stats->RBCAST_prio_1) + 296219820Sjeff be64_to_cpu(mlx4_en_stats->RBCAST_prio_2) + 297219820Sjeff be64_to_cpu(mlx4_en_stats->RBCAST_prio_3) + 298219820Sjeff be64_to_cpu(mlx4_en_stats->RBCAST_prio_4) + 299219820Sjeff be64_to_cpu(mlx4_en_stats->RBCAST_prio_5) + 300219820Sjeff be64_to_cpu(mlx4_en_stats->RBCAST_prio_6) + 301219820Sjeff be64_to_cpu(mlx4_en_stats->RBCAST_prio_7) + 302219820Sjeff be64_to_cpu(mlx4_en_stats->RBCAST_novlan); 303219820Sjeff priv->pkstats.rx_prio[0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0); 304219820Sjeff priv->pkstats.rx_prio[1] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1); 305219820Sjeff priv->pkstats.rx_prio[2] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2); 306219820Sjeff priv->pkstats.rx_prio[3] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3); 307219820Sjeff priv->pkstats.rx_prio[4] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4); 308219820Sjeff priv->pkstats.rx_prio[5] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5); 309219820Sjeff priv->pkstats.rx_prio[6] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6); 310219820Sjeff priv->pkstats.rx_prio[7] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7); 311219820Sjeff priv->pkstats.tx_prio[0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0); 312219820Sjeff priv->pkstats.tx_prio[1] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1); 313219820Sjeff priv->pkstats.tx_prio[2] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2); 314219820Sjeff priv->pkstats.tx_prio[3] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3); 315219820Sjeff priv->pkstats.tx_prio[4] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4); 316219820Sjeff priv->pkstats.tx_prio[5] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5); 317219820Sjeff priv->pkstats.tx_prio[6] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6); 318219820Sjeff priv->pkstats.tx_prio[7] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7); 319219820Sjeff spin_unlock(&priv->stats_lock); 320219820Sjeff 321219820Sjeffout: 322219820Sjeff mlx4_free_cmd_mailbox(mdev->dev, mailbox); 323219820Sjeff return err; 324219820Sjeff} 325219820Sjeff 326