en_port.c revision 219893
119304Speter/* 219304Speter * Copyright (c) 2007 Mellanox Technologies. All rights reserved. 319304Speter * 419304Speter * This software is available to you under a choice of one of two 519304Speter * licenses. You may choose to be licensed under the terms of the GNU 619304Speter * General Public License (GPL) Version 2, available from the file 719304Speter * COPYING in the main directory of this source tree, or the 819304Speter * OpenIB.org BSD license below: 919304Speter * 1019304Speter * Redistribution and use in source and binary forms, with or 1119304Speter * without modification, are permitted provided that the following 1219304Speter * conditions are met: 13254225Speter * 1419304Speter * - Redistributions of source code must retain the above 1519304Speter * copyright notice, this list of conditions and the following 1619304Speter * disclaimer. 1719304Speter * 1819304Speter * - Redistributions in binary form must reproduce the above 1919304Speter * copyright notice, this list of conditions and the following 2019304Speter * disclaimer in the documentation and/or other materials 2119304Speter * provided with the distribution. 2219304Speter * 2319304Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2419304Speter * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2519304Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26254225Speter * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27254225Speter * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28254225Speter * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2919304Speter * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3019304Speter * SOFTWARE. 3119304Speter * 3219304Speter */ 3319304Speter 3419304Speter 3519304Speter#include "mlx4_en.h" 3619304Speter 3719304Speter#include <linux/if_vlan.h> 3819304Speter 3919304Speter#include <linux/mlx4/device.h> 4019304Speter#include <linux/mlx4/cmd.h> 4119304Speter 4219304Speter 4319304Speterint mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, 4419304Speter u64 mac, u64 clear, u8 mode) 4519304Speter{ 4619304Speter return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, 4719304Speter MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B); 4819304Speter} 4919304Speter 5019304Speterint mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, u32 *vlans) 5119304Speter{ 52254225Speter struct mlx4_cmd_mailbox *mailbox; 5319304Speter struct mlx4_set_vlan_fltr_mbox *filter; 5419304Speter int i, j; 5519304Speter int err = 0; 5619304Speter 5719304Speter mailbox = mlx4_alloc_cmd_mailbox(dev); 5819304Speter if (IS_ERR(mailbox)) 59254225Speter return PTR_ERR(mailbox); 6019304Speter 6119304Speter filter = mailbox->buf; 6219304Speter memset(filter, 0, sizeof *filter); 6319304Speter if (vlans) 6419304Speter for (i = 0, j = VLAN_FLTR_SIZE - 1; i < VLAN_FLTR_SIZE; 6519304Speter i++, j--) 6619304Speter filter->entry[j] = cpu_to_be32(vlans[i]); 6719304Speter err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR, 6819304Speter MLX4_CMD_TIME_CLASS_B); 6919304Speter mlx4_free_cmd_mailbox(dev, mailbox); 7019304Speter return err; 7119304Speter} 7219304Speter 7319304Speter 7419304Speterint mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, 7519304Speter u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) 7619304Speter{ 7719304Speter struct mlx4_cmd_mailbox *mailbox; 7819304Speter struct mlx4_set_port_general_context *context; 7919304Speter int err; 8019304Speter u32 in_mod; 8119304Speter 8219304Speter mailbox = mlx4_alloc_cmd_mailbox(dev); 8319304Speter if (IS_ERR(mailbox)) 8419304Speter return PTR_ERR(mailbox); 8519304Speter context = mailbox->buf; 8619304Speter memset(context, 0, sizeof *context); 8719304Speter 8819304Speter context->flags = SET_PORT_GEN_ALL_VALID; 8919304Speter context->mtu = cpu_to_be16(mtu); 9019304Speter context->pptx = (pptx * (!pfctx)) << 7; 9119304Speter context->pfctx = pfctx; 9219304Speter context->pprx = (pprx * (!pfcrx)) << 7; 9319304Speter context->pfcrx = pfcrx; 9419304Speter 9519304Speter in_mod = MLX4_SET_PORT_GENERAL << 8 | port; 9619304Speter err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 9719304Speter MLX4_CMD_TIME_CLASS_B); 9819304Speter 9919304Speter mlx4_free_cmd_mailbox(dev, mailbox); 10019304Speter return err; 10119304Speter} 10219304Speter 10319304Speterint mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, 10419304Speter u8 promisc) 10519304Speter{ 10619304Speter struct mlx4_cmd_mailbox *mailbox; 10719304Speter struct mlx4_set_port_rqp_calc_context *context; 10819304Speter int err; 10919304Speter u32 in_mod; 11019304Speter 11119304Speter mailbox = mlx4_alloc_cmd_mailbox(dev); 11219304Speter if (IS_ERR(mailbox)) 11319304Speter return PTR_ERR(mailbox); 11419304Speter context = mailbox->buf; 11519304Speter memset(context, 0, sizeof *context); 11619304Speter 11719304Speter context->base_qpn = cpu_to_be32(base_qpn); 11819304Speter context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn); 11919304Speter context->mcast = cpu_to_be32((dev->caps.mc_promisc_mode << 12019304Speter SET_PORT_PROMISC_MODE_SHIFT) | base_qpn); 12119304Speter context->intra_no_vlan = 0; 12219304Speter context->no_vlan = MLX4_NO_VLAN_IDX; 12319304Speter context->intra_vlan_miss = 0; 12419304Speter context->vlan_miss = MLX4_VLAN_MISS_IDX; 12519304Speter 12619304Speter in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; 12719304Speter err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, 12819304Speter MLX4_CMD_TIME_CLASS_B); 12919304Speter 13019304Speter mlx4_free_cmd_mailbox(dev, mailbox); 13119304Speter return err; 13219304Speter} 13319304Speter 13419304Speterint mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port) 13519304Speter{ 13619304Speter struct mlx4_en_query_port_context *qport_context; 13719304Speter struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]); 138254225Speter struct mlx4_en_port_state *state = &priv->port_state; 139254225Speter struct mlx4_cmd_mailbox *mailbox; 14019304Speter int err; 14119304Speter 14219304Speter mailbox = mlx4_alloc_cmd_mailbox(mdev->dev); 14319304Speter if (IS_ERR(mailbox)) 14419304Speter return PTR_ERR(mailbox); 14519304Speter memset(mailbox->buf, 0, sizeof(*qport_context)); 14619304Speter err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0, 14719304Speter MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B); 14819304Speter if (err) 14919304Speter goto out; 150254225Speter qport_context = mailbox->buf; 151254225Speter 15219304Speter /* This command is always accessed from Ethtool context 153254225Speter * already synchronized, no need in locking */ 15419304Speter state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK); 15519304Speter if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) == 15619304Speter MLX4_EN_1G_SPEED) 15719304Speter state->link_speed = 1000; 15819304Speter else 15919304Speter state->link_speed = 10000; 16019304Speter state->transciver = qport_context->transceiver; 16119304Speter if (be32_to_cpu(qport_context->transceiver_code_hi) & 0x400) 16219304Speter state->transciver = 0x80; 16319304Speter 16419304Speterout: 165254225Speter mlx4_free_cmd_mailbox(mdev->dev, mailbox); 16619304Speter return err; 16719304Speter} 16819304Speter 16919304Speterstatic int read_iboe_counters(struct mlx4_dev *dev, int index, u64 counters[]) 17019304Speter{ 17119304Speter struct mlx4_cmd_mailbox *mailbox; 17219304Speter int err; 17319304Speter int mode; 17419304Speter struct mlx4_counters_ext *ext; 17519304Speter struct mlx4_counters *reg; 17619304Speter 17719304Speter mailbox = mlx4_alloc_cmd_mailbox(dev); 17819304Speter if (IS_ERR(mailbox)) 17919304Speter return -ENOMEM; 18019304Speter 18119304Speter err = mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, 18219304Speter MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C); 18319304Speter if (err) 18419304Speter goto out; 18519304Speter 18619304Speter mode = be32_to_cpu(((struct mlx4_counters *)mailbox->buf)->counter_mode) & 0xf; 18719304Speter switch (mode) { 188254225Speter case 0: 18919304Speter reg = mailbox->buf; 19019304Speter counters[0] = be64_to_cpu(reg->rx_frames); 19119304Speter counters[1] = be64_to_cpu(reg->tx_frames); 19219304Speter counters[2] = be64_to_cpu(reg->rx_bytes); 19319304Speter counters[3] = be64_to_cpu(reg->tx_bytes); 19419304Speter break; 19519304Speter case 1: 19619304Speter ext = mailbox->buf; 19719304Speter counters[0] = be64_to_cpu(ext->rx_uni_frames); 19819304Speter counters[1] = be64_to_cpu(ext->tx_uni_frames); 19919304Speter counters[2] = be64_to_cpu(ext->rx_uni_bytes); 20019304Speter counters[3] = be64_to_cpu(ext->tx_uni_bytes); 20119304Speter break; 20219304Speter default: 20319304Speter err = -EINVAL; 20419304Speter } 20519304Speter 20619304Speterout: 20719304Speter mlx4_free_cmd_mailbox(dev, mailbox); 20819304Speter return err; 20919304Speter} 21019304Speter 21119304Speterint mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) 21219304Speter{ 21319304Speter struct mlx4_en_stat_out_mbox *mlx4_en_stats; 21419304Speter struct net_device *dev; 21519304Speter struct mlx4_en_priv *priv; 21619304Speter struct mlx4_cmd_mailbox *mailbox; 21719304Speter u64 in_mod = reset << 8 | port; 21819304Speter unsigned long oerror; 21919304Speter unsigned long ierror; 22019304Speter int err; 22119304Speter int i; 22219304Speter int counter; 22319304Speter u64 counters[4]; 22419304Speter 22519304Speter dev = mdev->pndev[port]; 22619304Speter priv = netdev_priv(dev); 22719304Speter memset(counters, 0, sizeof counters); 22819304Speter counter = mlx4_get_iboe_counter(priv->mdev->dev, port); 22919304Speter if (counter >= 0) 23019304Speter err = read_iboe_counters(priv->mdev->dev, counter, counters); 23119304Speter 23219304Speter mailbox = mlx4_alloc_cmd_mailbox(mdev->dev); 23319304Speter if (IS_ERR(mailbox)) 23419304Speter return PTR_ERR(mailbox); 23519304Speter memset(mailbox->buf, 0, sizeof(*mlx4_en_stats)); 236254225Speter err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0, 23719304Speter MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B); 23819304Speter if (err) 23919304Speter goto out; 24019304Speter 24119304Speter mlx4_en_stats = mailbox->buf; 24219304Speter 24319304Speter spin_lock(&priv->stats_lock); 24419304Speter 24519304Speter oerror = ierror = 0; 24619304Speter dev->if_ipackets = counters[0]; 24719304Speter dev->if_ibytes = counters[2]; 24819304Speter for (i = 0; i < priv->rx_ring_num; i++) { 24919304Speter dev->if_ipackets += priv->rx_ring[i].packets; 25019304Speter dev->if_ibytes += priv->rx_ring[i].bytes; 25119304Speter ierror += priv->rx_ring[i].errors; 25219304Speter } 25319304Speter dev->if_opackets = counters[1]; 25419304Speter dev->if_obytes = counters[3]; 25519304Speter for (i = 0; i <= priv->tx_ring_num; i++) { 25619304Speter dev->if_opackets += priv->tx_ring[i].packets; 257254225Speter dev->if_obytes += priv->tx_ring[i].bytes; 25819304Speter oerror += priv->tx_ring[i].errors; 25919304Speter } 26019304Speter 26119304Speter dev->if_ierrors = be32_to_cpu(mlx4_en_stats->RDROP) + ierror; 26219304Speter dev->if_oerrors = be32_to_cpu(mlx4_en_stats->TDROP) + oerror; 26319304Speter dev->if_imcasts = be64_to_cpu(mlx4_en_stats->MCAST_prio_0) + 26419304Speter be64_to_cpu(mlx4_en_stats->MCAST_prio_1) + 26519304Speter be64_to_cpu(mlx4_en_stats->MCAST_prio_2) + 266254225Speter be64_to_cpu(mlx4_en_stats->MCAST_prio_3) + 26719304Speter be64_to_cpu(mlx4_en_stats->MCAST_prio_4) + 26819304Speter be64_to_cpu(mlx4_en_stats->MCAST_prio_5) + 26919304Speter be64_to_cpu(mlx4_en_stats->MCAST_prio_6) + 27019304Speter be64_to_cpu(mlx4_en_stats->MCAST_prio_7) + 27119304Speter be64_to_cpu(mlx4_en_stats->MCAST_novlan); 27219304Speter dev->if_omcasts = be64_to_cpu(mlx4_en_stats->TMCAST_prio_0) + 27319304Speter be64_to_cpu(mlx4_en_stats->TMCAST_prio_1) + 274254225Speter be64_to_cpu(mlx4_en_stats->TMCAST_prio_2) + 27519304Speter be64_to_cpu(mlx4_en_stats->TMCAST_prio_3) + 27619304Speter be64_to_cpu(mlx4_en_stats->TMCAST_prio_4) + 27719304Speter be64_to_cpu(mlx4_en_stats->TMCAST_prio_5) + 27819304Speter be64_to_cpu(mlx4_en_stats->TMCAST_prio_6) + 27919304Speter be64_to_cpu(mlx4_en_stats->TMCAST_prio_7) + 28019304Speter be64_to_cpu(mlx4_en_stats->TMCAST_novlan); 28119304Speter dev->if_collisions = 0; 28219304Speter 283254225Speter priv->pkstats.broadcast = 28419304Speter be64_to_cpu(mlx4_en_stats->RBCAST_prio_0) + 28519304Speter be64_to_cpu(mlx4_en_stats->RBCAST_prio_1) + 28619304Speter be64_to_cpu(mlx4_en_stats->RBCAST_prio_2) + 28719304Speter be64_to_cpu(mlx4_en_stats->RBCAST_prio_3) + 28819304Speter be64_to_cpu(mlx4_en_stats->RBCAST_prio_4) + 28919304Speter be64_to_cpu(mlx4_en_stats->RBCAST_prio_5) + 29019304Speter be64_to_cpu(mlx4_en_stats->RBCAST_prio_6) + 29119304Speter be64_to_cpu(mlx4_en_stats->RBCAST_prio_7) + 29219304Speter be64_to_cpu(mlx4_en_stats->RBCAST_novlan); 29319304Speter priv->pkstats.rx_prio[0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0); 29419304Speter priv->pkstats.rx_prio[1] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1); 29519304Speter priv->pkstats.rx_prio[2] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2); 29619304Speter priv->pkstats.rx_prio[3] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3); 29719304Speter priv->pkstats.rx_prio[4] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4); 298254225Speter priv->pkstats.rx_prio[5] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5); 29919304Speter priv->pkstats.rx_prio[6] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6); 30019304Speter priv->pkstats.rx_prio[7] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7); 30119304Speter priv->pkstats.tx_prio[0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0); 30219304Speter priv->pkstats.tx_prio[1] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1); 30319304Speter priv->pkstats.tx_prio[2] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2); 30419304Speter priv->pkstats.tx_prio[3] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3); 30519304Speter priv->pkstats.tx_prio[4] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4); 30619304Speter priv->pkstats.tx_prio[5] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5); 30719304Speter priv->pkstats.tx_prio[6] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6); 30819304Speter priv->pkstats.tx_prio[7] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7); 30919304Speter spin_unlock(&priv->stats_lock); 31019304Speter 31119304Speterout: 31219304Speter mlx4_free_cmd_mailbox(mdev->dev, mailbox); 31319304Speter return err; 31419304Speter} 31519304Speter 31619304Speter