From 4301ba7b3ed9d3ffbaebc295413fcd3e8ab34949 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Sun, 18 Jun 2017 17:13:44 +0300 Subject: net/mlx5e: IPoIB, Move to a separate directory IPoIB netdevice driver was only introduced in previous kernel release and it is growing in terms of features and LOC, move it to a separate directory. Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/ipoib.c | 513 --------------------- drivers/net/ethernet/mellanox/mlx5/core/ipoib.h | 56 --- .../net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 513 +++++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h | 56 +++ 7 files changed, 572 insertions(+), 572 deletions(-) delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/ipoib.c delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/ipoib.h create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 12556c03eec4..59b87b30e438 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -15,4 +15,4 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \ mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o -mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib.o +mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 66b5fec15313..806139d62139 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -40,7 +40,7 @@ #include "en_tc.h" #include "eswitch.h" #include "en_rep.h" -#include "ipoib.h" +#include "ipoib/ipoib.h" static inline bool mlx5e_rx_hw_stamp(struct mlx5e_tstamp *tstamp) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index ef3e1918d8cc..354f474322ce 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -33,7 +33,7 @@ #include #include #include "en.h" -#include "ipoib.h" +#include "ipoib/ipoib.h" #define MLX5E_SQ_NOPS_ROOM MLX5_SEND_WQE_MAX_WQEBBS #define MLX5E_SQ_STOP_ROOM (MLX5_SEND_WQE_MAX_WQEBBS +\ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c deleted file mode 100644 index 22ca59145e6c..000000000000 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright (c) 2017, Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "en.h" -#include "ipoib.h" - -#define IB_DEFAULT_Q_KEY 0xb1b - -static int mlx5i_open(struct net_device *netdev); -static int mlx5i_close(struct net_device *netdev); -static int mlx5i_dev_init(struct net_device *dev); -static void mlx5i_dev_cleanup(struct net_device *dev); - -static const struct net_device_ops mlx5i_netdev_ops = { - .ndo_open = mlx5i_open, - .ndo_stop = mlx5i_close, - .ndo_init = mlx5i_dev_init, - .ndo_uninit = mlx5i_dev_cleanup, -}; - -/* IPoIB mlx5 netdev profile */ - -/* Called directly after IPoIB netdevice was created to initialize SW structs */ -static void mlx5i_init(struct mlx5_core_dev *mdev, - struct net_device *netdev, - const struct mlx5e_profile *profile, - void *ppriv) -{ - struct mlx5e_priv *priv = mlx5i_epriv(netdev); - - priv->mdev = mdev; - priv->netdev = netdev; - priv->profile = profile; - priv->ppriv = ppriv; - - mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev)); - - /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */ - mlx5e_set_rq_type_params(mdev, &priv->channels.params, MLX5_WQ_TYPE_LINKED_LIST); - priv->channels.params.lro_en = false; - - mutex_init(&priv->state_lock); - - netdev->hw_features |= NETIF_F_SG; - netdev->hw_features |= NETIF_F_IP_CSUM; - netdev->hw_features |= NETIF_F_IPV6_CSUM; - netdev->hw_features |= NETIF_F_GRO; - netdev->hw_features |= NETIF_F_TSO; - netdev->hw_features |= NETIF_F_TSO6; - netdev->hw_features |= NETIF_F_RXCSUM; - netdev->hw_features |= NETIF_F_RXHASH; - - netdev->netdev_ops = &mlx5i_netdev_ops; -} - -/* Called directly before IPoIB netdevice is destroyed to cleanup SW structs */ -static void mlx5i_cleanup(struct mlx5e_priv *priv) -{ - /* Do nothing .. */ -} - -#define MLX5_QP_ENHANCED_ULP_STATELESS_MODE 2 - -static int mlx5i_create_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp) -{ - struct mlx5_qp_context *context = NULL; - u32 *in = NULL; - void *addr_path; - int ret = 0; - int inlen; - void *qpc; - - inlen = MLX5_ST_SZ_BYTES(create_qp_in); - in = kvzalloc(inlen, GFP_KERNEL); - if (!in) - return -ENOMEM; - - qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); - MLX5_SET(qpc, qpc, st, MLX5_QP_ST_UD); - MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED); - MLX5_SET(qpc, qpc, ulp_stateless_offload_mode, - MLX5_QP_ENHANCED_ULP_STATELESS_MODE); - - addr_path = MLX5_ADDR_OF(qpc, qpc, primary_address_path); - MLX5_SET(ads, addr_path, port, 1); - MLX5_SET(ads, addr_path, grh, 1); - - ret = mlx5_core_create_qp(mdev, qp, in, inlen); - if (ret) { - mlx5_core_err(mdev, "Failed creating IPoIB QP err : %d\n", ret); - goto out; - } - - /* QP states */ - context = kzalloc(sizeof(*context), GFP_KERNEL); - if (!context) { - ret = -ENOMEM; - goto out; - } - - context->flags = cpu_to_be32(MLX5_QP_PM_MIGRATED << 11); - context->pri_path.port = 1; - context->qkey = cpu_to_be32(IB_DEFAULT_Q_KEY); - - ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_RST2INIT_QP, 0, context, qp); - if (ret) { - mlx5_core_err(mdev, "Failed to modify qp RST2INIT, err: %d\n", ret); - goto out; - } - memset(context, 0, sizeof(*context)); - - ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_INIT2RTR_QP, 0, context, qp); - if (ret) { - mlx5_core_err(mdev, "Failed to modify qp INIT2RTR, err: %d\n", ret); - goto out; - } - - ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_RTR2RTS_QP, 0, context, qp); - if (ret) { - mlx5_core_err(mdev, "Failed to modify qp RTR2RTS, err: %d\n", ret); - goto out; - } - -out: - kfree(context); - kvfree(in); - return ret; -} - -static void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp) -{ - mlx5_fs_remove_rx_underlay_qpn(mdev, qp->qpn); - - mlx5_core_destroy_qp(mdev, qp); -} - -static int mlx5i_init_tx(struct mlx5e_priv *priv) -{ - struct mlx5i_priv *ipriv = priv->ppriv; - int err; - - err = mlx5i_create_underlay_qp(priv->mdev, &ipriv->qp); - if (err) { - mlx5_core_warn(priv->mdev, "create underlay QP failed, %d\n", err); - return err; - } - - mlx5_fs_add_rx_underlay_qpn(priv->mdev, ipriv->qp.qpn); - - err = mlx5e_create_tis(priv->mdev, 0 /* tc */, ipriv->qp.qpn, &priv->tisn[0]); - if (err) { - mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err); - return err; - } - - return 0; -} - -static void mlx5i_cleanup_tx(struct mlx5e_priv *priv) -{ - struct mlx5i_priv *ipriv = priv->ppriv; - - mlx5e_destroy_tis(priv->mdev, priv->tisn[0]); - mlx5i_destroy_underlay_qp(priv->mdev, &ipriv->qp); -} - -static int mlx5i_create_flow_steering(struct mlx5e_priv *priv) -{ - int err; - - priv->fs.ns = mlx5_get_flow_namespace(priv->mdev, - MLX5_FLOW_NAMESPACE_KERNEL); - - if (!priv->fs.ns) - return -EINVAL; - - err = mlx5e_arfs_create_tables(priv); - if (err) { - netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n", - err); - priv->netdev->hw_features &= ~NETIF_F_NTUPLE; - } - - err = mlx5e_create_ttc_table(priv); - if (err) { - netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n", - err); - goto err_destroy_arfs_tables; - } - - return 0; - -err_destroy_arfs_tables: - mlx5e_arfs_destroy_tables(priv); - - return err; -} - -static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv) -{ - mlx5e_destroy_ttc_table(priv); - mlx5e_arfs_destroy_tables(priv); -} - -static int mlx5i_init_rx(struct mlx5e_priv *priv) -{ - int err; - - err = mlx5e_create_indirect_rqt(priv); - if (err) - return err; - - err = mlx5e_create_direct_rqts(priv); - if (err) - goto err_destroy_indirect_rqts; - - err = mlx5e_create_indirect_tirs(priv); - if (err) - goto err_destroy_direct_rqts; - - err = mlx5e_create_direct_tirs(priv); - if (err) - goto err_destroy_indirect_tirs; - - err = mlx5i_create_flow_steering(priv); - if (err) - goto err_destroy_direct_tirs; - - return 0; - -err_destroy_direct_tirs: - mlx5e_destroy_direct_tirs(priv); -err_destroy_indirect_tirs: - mlx5e_destroy_indirect_tirs(priv); -err_destroy_direct_rqts: - mlx5e_destroy_direct_rqts(priv); -err_destroy_indirect_rqts: - mlx5e_destroy_rqt(priv, &priv->indir_rqt); - return err; -} - -static void mlx5i_cleanup_rx(struct mlx5e_priv *priv) -{ - mlx5i_destroy_flow_steering(priv); - mlx5e_destroy_direct_tirs(priv); - mlx5e_destroy_indirect_tirs(priv); - mlx5e_destroy_direct_rqts(priv); - mlx5e_destroy_rqt(priv, &priv->indir_rqt); -} - -static const struct mlx5e_profile mlx5i_nic_profile = { - .init = mlx5i_init, - .cleanup = mlx5i_cleanup, - .init_tx = mlx5i_init_tx, - .cleanup_tx = mlx5i_cleanup_tx, - .init_rx = mlx5i_init_rx, - .cleanup_rx = mlx5i_cleanup_rx, - .enable = NULL, /* mlx5i_enable */ - .disable = NULL, /* mlx5i_disable */ - .update_stats = NULL, /* mlx5i_update_stats */ - .max_nch = mlx5e_get_max_num_channels, - .rx_handlers.handle_rx_cqe = mlx5i_handle_rx_cqe, - .rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */ - .max_tc = MLX5I_MAX_NUM_TC, -}; - -/* mlx5i netdev NDos */ - -static int mlx5i_dev_init(struct net_device *dev) -{ - struct mlx5e_priv *priv = mlx5i_epriv(dev); - struct mlx5i_priv *ipriv = priv->ppriv; - - /* Set dev address using underlay QP */ - dev->dev_addr[1] = (ipriv->qp.qpn >> 16) & 0xff; - dev->dev_addr[2] = (ipriv->qp.qpn >> 8) & 0xff; - dev->dev_addr[3] = (ipriv->qp.qpn) & 0xff; - - return 0; -} - -static void mlx5i_dev_cleanup(struct net_device *dev) -{ - struct mlx5e_priv *priv = mlx5i_epriv(dev); - struct mlx5_core_dev *mdev = priv->mdev; - struct mlx5i_priv *ipriv = priv->ppriv; - struct mlx5_qp_context context; - - /* detach qp from flow-steering by reset it */ - mlx5_core_qp_modify(mdev, MLX5_CMD_OP_2RST_QP, 0, &context, &ipriv->qp); -} - -static int mlx5i_open(struct net_device *netdev) -{ - struct mlx5e_priv *priv = mlx5i_epriv(netdev); - int err; - - mutex_lock(&priv->state_lock); - - set_bit(MLX5E_STATE_OPENED, &priv->state); - - err = mlx5e_open_channels(priv, &priv->channels); - if (err) - goto err_clear_state_opened_flag; - - mlx5e_refresh_tirs(priv, false); - mlx5e_activate_priv_channels(priv); - mutex_unlock(&priv->state_lock); - return 0; - -err_clear_state_opened_flag: - clear_bit(MLX5E_STATE_OPENED, &priv->state); - mutex_unlock(&priv->state_lock); - return err; -} - -static int mlx5i_close(struct net_device *netdev) -{ - struct mlx5e_priv *priv = mlx5i_epriv(netdev); - - /* May already be CLOSED in case a previous configuration operation - * (e.g RX/TX queue size change) that involves close&open failed. - */ - mutex_lock(&priv->state_lock); - - if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) - goto unlock; - - clear_bit(MLX5E_STATE_OPENED, &priv->state); - - netif_carrier_off(priv->netdev); - mlx5e_deactivate_priv_channels(priv); - mlx5e_close_channels(&priv->channels); -unlock: - mutex_unlock(&priv->state_lock); - return 0; -} - -/* IPoIB RDMA netdev callbacks */ -static int mlx5i_attach_mcast(struct net_device *netdev, struct ib_device *hca, - union ib_gid *gid, u16 lid, int set_qkey, - u32 qkey) -{ - struct mlx5e_priv *epriv = mlx5i_epriv(netdev); - struct mlx5_core_dev *mdev = epriv->mdev; - struct mlx5i_priv *ipriv = epriv->ppriv; - int err; - - mlx5_core_dbg(mdev, "attaching QPN 0x%x, MGID %pI6\n", ipriv->qp.qpn, gid->raw); - err = mlx5_core_attach_mcg(mdev, gid, ipriv->qp.qpn); - if (err) - mlx5_core_warn(mdev, "failed attaching QPN 0x%x, MGID %pI6\n", - ipriv->qp.qpn, gid->raw); - - if (set_qkey) { - mlx5_core_dbg(mdev, "%s setting qkey 0x%x\n", - netdev->name, qkey); - ipriv->qkey = qkey; - } - - return err; -} - -static int mlx5i_detach_mcast(struct net_device *netdev, struct ib_device *hca, - union ib_gid *gid, u16 lid) -{ - struct mlx5e_priv *epriv = mlx5i_epriv(netdev); - struct mlx5_core_dev *mdev = epriv->mdev; - struct mlx5i_priv *ipriv = epriv->ppriv; - int err; - - mlx5_core_dbg(mdev, "detaching QPN 0x%x, MGID %pI6\n", ipriv->qp.qpn, gid->raw); - - err = mlx5_core_detach_mcg(mdev, gid, ipriv->qp.qpn); - if (err) - mlx5_core_dbg(mdev, "failed dettaching QPN 0x%x, MGID %pI6\n", - ipriv->qp.qpn, gid->raw); - - return err; -} - -static int mlx5i_xmit(struct net_device *dev, struct sk_buff *skb, - struct ib_ah *address, u32 dqpn) -{ - struct mlx5e_priv *epriv = mlx5i_epriv(dev); - struct mlx5e_txqsq *sq = epriv->txq2sq[skb_get_queue_mapping(skb)]; - struct mlx5_ib_ah *mah = to_mah(address); - struct mlx5i_priv *ipriv = epriv->ppriv; - - return mlx5i_sq_xmit(sq, skb, &mah->av, dqpn, ipriv->qkey); -} - -static int mlx5i_check_required_hca_cap(struct mlx5_core_dev *mdev) -{ - if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_IB) - return -EOPNOTSUPP; - - if (!MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) { - mlx5_core_warn(mdev, "IPoIB enhanced offloads are not supported\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, - struct ib_device *ibdev, - const char *name, - void (*setup)(struct net_device *)) -{ - const struct mlx5e_profile *profile = &mlx5i_nic_profile; - int nch = profile->max_nch(mdev); - struct net_device *netdev; - struct mlx5i_priv *ipriv; - struct mlx5e_priv *epriv; - struct rdma_netdev *rn; - int err; - - if (mlx5i_check_required_hca_cap(mdev)) { - mlx5_core_warn(mdev, "Accelerated mode is not supported\n"); - return ERR_PTR(-EOPNOTSUPP); - } - - /* This function should only be called once per mdev */ - err = mlx5e_create_mdev_resources(mdev); - if (err) - return NULL; - - netdev = alloc_netdev_mqs(sizeof(struct mlx5i_priv) + sizeof(struct mlx5e_priv), - name, NET_NAME_UNKNOWN, - setup, - nch * MLX5E_MAX_NUM_TC, - nch); - if (!netdev) { - mlx5_core_warn(mdev, "alloc_netdev_mqs failed\n"); - goto free_mdev_resources; - } - - ipriv = netdev_priv(netdev); - epriv = mlx5i_epriv(netdev); - - epriv->wq = create_singlethread_workqueue("mlx5i"); - if (!epriv->wq) - goto err_free_netdev; - - profile->init(mdev, netdev, profile, ipriv); - - mlx5e_attach_netdev(epriv); - netif_carrier_off(netdev); - - /* set rdma_netdev func pointers */ - rn = &ipriv->rn; - rn->hca = ibdev; - rn->send = mlx5i_xmit; - rn->attach_mcast = mlx5i_attach_mcast; - rn->detach_mcast = mlx5i_detach_mcast; - - return netdev; - -err_free_netdev: - free_netdev(netdev); -free_mdev_resources: - mlx5e_destroy_mdev_resources(mdev); - - return NULL; -} -EXPORT_SYMBOL(mlx5_rdma_netdev_alloc); - -void mlx5_rdma_netdev_free(struct net_device *netdev) -{ - struct mlx5e_priv *priv = mlx5i_epriv(netdev); - const struct mlx5e_profile *profile = priv->profile; - - mlx5e_detach_netdev(priv); - profile->cleanup(priv); - destroy_workqueue(priv->wq); - free_netdev(netdev); - - mlx5e_destroy_mdev_resources(priv->mdev); -} -EXPORT_SYMBOL(mlx5_rdma_netdev_free); - diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.h b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.h deleted file mode 100644 index 213191a78464..000000000000 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2017, Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __MLX5E_IPOB_H__ -#define __MLX5E_IPOB_H__ - -#include -#include "en.h" - -#define MLX5I_MAX_NUM_TC 1 - -/* ipoib rdma netdev's private data structure */ -struct mlx5i_priv { - struct rdma_netdev rn; /* keep this first */ - struct mlx5_core_qp qp; - u32 qkey; - char *mlx5e_priv[0]; -}; - -/* Extract mlx5e_priv from IPoIB netdev */ -#define mlx5i_epriv(netdev) ((void *)(((struct mlx5i_priv *)netdev_priv(netdev))->mlx5e_priv)) - -netdev_tx_t mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, - struct mlx5_av *av, u32 dqpn, u32 dqkey); -void mlx5i_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe); - -#endif /* __MLX5E_IPOB_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c new file mode 100644 index 000000000000..22ca59145e6c --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2017, Mellanox Technologies. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include "en.h" +#include "ipoib.h" + +#define IB_DEFAULT_Q_KEY 0xb1b + +static int mlx5i_open(struct net_device *netdev); +static int mlx5i_close(struct net_device *netdev); +static int mlx5i_dev_init(struct net_device *dev); +static void mlx5i_dev_cleanup(struct net_device *dev); + +static const struct net_device_ops mlx5i_netdev_ops = { + .ndo_open = mlx5i_open, + .ndo_stop = mlx5i_close, + .ndo_init = mlx5i_dev_init, + .ndo_uninit = mlx5i_dev_cleanup, +}; + +/* IPoIB mlx5 netdev profile */ + +/* Called directly after IPoIB netdevice was created to initialize SW structs */ +static void mlx5i_init(struct mlx5_core_dev *mdev, + struct net_device *netdev, + const struct mlx5e_profile *profile, + void *ppriv) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + + priv->mdev = mdev; + priv->netdev = netdev; + priv->profile = profile; + priv->ppriv = ppriv; + + mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev)); + + /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */ + mlx5e_set_rq_type_params(mdev, &priv->channels.params, MLX5_WQ_TYPE_LINKED_LIST); + priv->channels.params.lro_en = false; + + mutex_init(&priv->state_lock); + + netdev->hw_features |= NETIF_F_SG; + netdev->hw_features |= NETIF_F_IP_CSUM; + netdev->hw_features |= NETIF_F_IPV6_CSUM; + netdev->hw_features |= NETIF_F_GRO; + netdev->hw_features |= NETIF_F_TSO; + netdev->hw_features |= NETIF_F_TSO6; + netdev->hw_features |= NETIF_F_RXCSUM; + netdev->hw_features |= NETIF_F_RXHASH; + + netdev->netdev_ops = &mlx5i_netdev_ops; +} + +/* Called directly before IPoIB netdevice is destroyed to cleanup SW structs */ +static void mlx5i_cleanup(struct mlx5e_priv *priv) +{ + /* Do nothing .. */ +} + +#define MLX5_QP_ENHANCED_ULP_STATELESS_MODE 2 + +static int mlx5i_create_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp) +{ + struct mlx5_qp_context *context = NULL; + u32 *in = NULL; + void *addr_path; + int ret = 0; + int inlen; + void *qpc; + + inlen = MLX5_ST_SZ_BYTES(create_qp_in); + in = kvzalloc(inlen, GFP_KERNEL); + if (!in) + return -ENOMEM; + + qpc = MLX5_ADDR_OF(create_qp_in, in, qpc); + MLX5_SET(qpc, qpc, st, MLX5_QP_ST_UD); + MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED); + MLX5_SET(qpc, qpc, ulp_stateless_offload_mode, + MLX5_QP_ENHANCED_ULP_STATELESS_MODE); + + addr_path = MLX5_ADDR_OF(qpc, qpc, primary_address_path); + MLX5_SET(ads, addr_path, port, 1); + MLX5_SET(ads, addr_path, grh, 1); + + ret = mlx5_core_create_qp(mdev, qp, in, inlen); + if (ret) { + mlx5_core_err(mdev, "Failed creating IPoIB QP err : %d\n", ret); + goto out; + } + + /* QP states */ + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (!context) { + ret = -ENOMEM; + goto out; + } + + context->flags = cpu_to_be32(MLX5_QP_PM_MIGRATED << 11); + context->pri_path.port = 1; + context->qkey = cpu_to_be32(IB_DEFAULT_Q_KEY); + + ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_RST2INIT_QP, 0, context, qp); + if (ret) { + mlx5_core_err(mdev, "Failed to modify qp RST2INIT, err: %d\n", ret); + goto out; + } + memset(context, 0, sizeof(*context)); + + ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_INIT2RTR_QP, 0, context, qp); + if (ret) { + mlx5_core_err(mdev, "Failed to modify qp INIT2RTR, err: %d\n", ret); + goto out; + } + + ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_RTR2RTS_QP, 0, context, qp); + if (ret) { + mlx5_core_err(mdev, "Failed to modify qp RTR2RTS, err: %d\n", ret); + goto out; + } + +out: + kfree(context); + kvfree(in); + return ret; +} + +static void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp) +{ + mlx5_fs_remove_rx_underlay_qpn(mdev, qp->qpn); + + mlx5_core_destroy_qp(mdev, qp); +} + +static int mlx5i_init_tx(struct mlx5e_priv *priv) +{ + struct mlx5i_priv *ipriv = priv->ppriv; + int err; + + err = mlx5i_create_underlay_qp(priv->mdev, &ipriv->qp); + if (err) { + mlx5_core_warn(priv->mdev, "create underlay QP failed, %d\n", err); + return err; + } + + mlx5_fs_add_rx_underlay_qpn(priv->mdev, ipriv->qp.qpn); + + err = mlx5e_create_tis(priv->mdev, 0 /* tc */, ipriv->qp.qpn, &priv->tisn[0]); + if (err) { + mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err); + return err; + } + + return 0; +} + +static void mlx5i_cleanup_tx(struct mlx5e_priv *priv) +{ + struct mlx5i_priv *ipriv = priv->ppriv; + + mlx5e_destroy_tis(priv->mdev, priv->tisn[0]); + mlx5i_destroy_underlay_qp(priv->mdev, &ipriv->qp); +} + +static int mlx5i_create_flow_steering(struct mlx5e_priv *priv) +{ + int err; + + priv->fs.ns = mlx5_get_flow_namespace(priv->mdev, + MLX5_FLOW_NAMESPACE_KERNEL); + + if (!priv->fs.ns) + return -EINVAL; + + err = mlx5e_arfs_create_tables(priv); + if (err) { + netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n", + err); + priv->netdev->hw_features &= ~NETIF_F_NTUPLE; + } + + err = mlx5e_create_ttc_table(priv); + if (err) { + netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n", + err); + goto err_destroy_arfs_tables; + } + + return 0; + +err_destroy_arfs_tables: + mlx5e_arfs_destroy_tables(priv); + + return err; +} + +static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv) +{ + mlx5e_destroy_ttc_table(priv); + mlx5e_arfs_destroy_tables(priv); +} + +static int mlx5i_init_rx(struct mlx5e_priv *priv) +{ + int err; + + err = mlx5e_create_indirect_rqt(priv); + if (err) + return err; + + err = mlx5e_create_direct_rqts(priv); + if (err) + goto err_destroy_indirect_rqts; + + err = mlx5e_create_indirect_tirs(priv); + if (err) + goto err_destroy_direct_rqts; + + err = mlx5e_create_direct_tirs(priv); + if (err) + goto err_destroy_indirect_tirs; + + err = mlx5i_create_flow_steering(priv); + if (err) + goto err_destroy_direct_tirs; + + return 0; + +err_destroy_direct_tirs: + mlx5e_destroy_direct_tirs(priv); +err_destroy_indirect_tirs: + mlx5e_destroy_indirect_tirs(priv); +err_destroy_direct_rqts: + mlx5e_destroy_direct_rqts(priv); +err_destroy_indirect_rqts: + mlx5e_destroy_rqt(priv, &priv->indir_rqt); + return err; +} + +static void mlx5i_cleanup_rx(struct mlx5e_priv *priv) +{ + mlx5i_destroy_flow_steering(priv); + mlx5e_destroy_direct_tirs(priv); + mlx5e_destroy_indirect_tirs(priv); + mlx5e_destroy_direct_rqts(priv); + mlx5e_destroy_rqt(priv, &priv->indir_rqt); +} + +static const struct mlx5e_profile mlx5i_nic_profile = { + .init = mlx5i_init, + .cleanup = mlx5i_cleanup, + .init_tx = mlx5i_init_tx, + .cleanup_tx = mlx5i_cleanup_tx, + .init_rx = mlx5i_init_rx, + .cleanup_rx = mlx5i_cleanup_rx, + .enable = NULL, /* mlx5i_enable */ + .disable = NULL, /* mlx5i_disable */ + .update_stats = NULL, /* mlx5i_update_stats */ + .max_nch = mlx5e_get_max_num_channels, + .rx_handlers.handle_rx_cqe = mlx5i_handle_rx_cqe, + .rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */ + .max_tc = MLX5I_MAX_NUM_TC, +}; + +/* mlx5i netdev NDos */ + +static int mlx5i_dev_init(struct net_device *dev) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + struct mlx5i_priv *ipriv = priv->ppriv; + + /* Set dev address using underlay QP */ + dev->dev_addr[1] = (ipriv->qp.qpn >> 16) & 0xff; + dev->dev_addr[2] = (ipriv->qp.qpn >> 8) & 0xff; + dev->dev_addr[3] = (ipriv->qp.qpn) & 0xff; + + return 0; +} + +static void mlx5i_dev_cleanup(struct net_device *dev) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + struct mlx5_core_dev *mdev = priv->mdev; + struct mlx5i_priv *ipriv = priv->ppriv; + struct mlx5_qp_context context; + + /* detach qp from flow-steering by reset it */ + mlx5_core_qp_modify(mdev, MLX5_CMD_OP_2RST_QP, 0, &context, &ipriv->qp); +} + +static int mlx5i_open(struct net_device *netdev) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + int err; + + mutex_lock(&priv->state_lock); + + set_bit(MLX5E_STATE_OPENED, &priv->state); + + err = mlx5e_open_channels(priv, &priv->channels); + if (err) + goto err_clear_state_opened_flag; + + mlx5e_refresh_tirs(priv, false); + mlx5e_activate_priv_channels(priv); + mutex_unlock(&priv->state_lock); + return 0; + +err_clear_state_opened_flag: + clear_bit(MLX5E_STATE_OPENED, &priv->state); + mutex_unlock(&priv->state_lock); + return err; +} + +static int mlx5i_close(struct net_device *netdev) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + + /* May already be CLOSED in case a previous configuration operation + * (e.g RX/TX queue size change) that involves close&open failed. + */ + mutex_lock(&priv->state_lock); + + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) + goto unlock; + + clear_bit(MLX5E_STATE_OPENED, &priv->state); + + netif_carrier_off(priv->netdev); + mlx5e_deactivate_priv_channels(priv); + mlx5e_close_channels(&priv->channels); +unlock: + mutex_unlock(&priv->state_lock); + return 0; +} + +/* IPoIB RDMA netdev callbacks */ +static int mlx5i_attach_mcast(struct net_device *netdev, struct ib_device *hca, + union ib_gid *gid, u16 lid, int set_qkey, + u32 qkey) +{ + struct mlx5e_priv *epriv = mlx5i_epriv(netdev); + struct mlx5_core_dev *mdev = epriv->mdev; + struct mlx5i_priv *ipriv = epriv->ppriv; + int err; + + mlx5_core_dbg(mdev, "attaching QPN 0x%x, MGID %pI6\n", ipriv->qp.qpn, gid->raw); + err = mlx5_core_attach_mcg(mdev, gid, ipriv->qp.qpn); + if (err) + mlx5_core_warn(mdev, "failed attaching QPN 0x%x, MGID %pI6\n", + ipriv->qp.qpn, gid->raw); + + if (set_qkey) { + mlx5_core_dbg(mdev, "%s setting qkey 0x%x\n", + netdev->name, qkey); + ipriv->qkey = qkey; + } + + return err; +} + +static int mlx5i_detach_mcast(struct net_device *netdev, struct ib_device *hca, + union ib_gid *gid, u16 lid) +{ + struct mlx5e_priv *epriv = mlx5i_epriv(netdev); + struct mlx5_core_dev *mdev = epriv->mdev; + struct mlx5i_priv *ipriv = epriv->ppriv; + int err; + + mlx5_core_dbg(mdev, "detaching QPN 0x%x, MGID %pI6\n", ipriv->qp.qpn, gid->raw); + + err = mlx5_core_detach_mcg(mdev, gid, ipriv->qp.qpn); + if (err) + mlx5_core_dbg(mdev, "failed dettaching QPN 0x%x, MGID %pI6\n", + ipriv->qp.qpn, gid->raw); + + return err; +} + +static int mlx5i_xmit(struct net_device *dev, struct sk_buff *skb, + struct ib_ah *address, u32 dqpn) +{ + struct mlx5e_priv *epriv = mlx5i_epriv(dev); + struct mlx5e_txqsq *sq = epriv->txq2sq[skb_get_queue_mapping(skb)]; + struct mlx5_ib_ah *mah = to_mah(address); + struct mlx5i_priv *ipriv = epriv->ppriv; + + return mlx5i_sq_xmit(sq, skb, &mah->av, dqpn, ipriv->qkey); +} + +static int mlx5i_check_required_hca_cap(struct mlx5_core_dev *mdev) +{ + if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_IB) + return -EOPNOTSUPP; + + if (!MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) { + mlx5_core_warn(mdev, "IPoIB enhanced offloads are not supported\n"); + return -EOPNOTSUPP; + } + + return 0; +} + +struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, + struct ib_device *ibdev, + const char *name, + void (*setup)(struct net_device *)) +{ + const struct mlx5e_profile *profile = &mlx5i_nic_profile; + int nch = profile->max_nch(mdev); + struct net_device *netdev; + struct mlx5i_priv *ipriv; + struct mlx5e_priv *epriv; + struct rdma_netdev *rn; + int err; + + if (mlx5i_check_required_hca_cap(mdev)) { + mlx5_core_warn(mdev, "Accelerated mode is not supported\n"); + return ERR_PTR(-EOPNOTSUPP); + } + + /* This function should only be called once per mdev */ + err = mlx5e_create_mdev_resources(mdev); + if (err) + return NULL; + + netdev = alloc_netdev_mqs(sizeof(struct mlx5i_priv) + sizeof(struct mlx5e_priv), + name, NET_NAME_UNKNOWN, + setup, + nch * MLX5E_MAX_NUM_TC, + nch); + if (!netdev) { + mlx5_core_warn(mdev, "alloc_netdev_mqs failed\n"); + goto free_mdev_resources; + } + + ipriv = netdev_priv(netdev); + epriv = mlx5i_epriv(netdev); + + epriv->wq = create_singlethread_workqueue("mlx5i"); + if (!epriv->wq) + goto err_free_netdev; + + profile->init(mdev, netdev, profile, ipriv); + + mlx5e_attach_netdev(epriv); + netif_carrier_off(netdev); + + /* set rdma_netdev func pointers */ + rn = &ipriv->rn; + rn->hca = ibdev; + rn->send = mlx5i_xmit; + rn->attach_mcast = mlx5i_attach_mcast; + rn->detach_mcast = mlx5i_detach_mcast; + + return netdev; + +err_free_netdev: + free_netdev(netdev); +free_mdev_resources: + mlx5e_destroy_mdev_resources(mdev); + + return NULL; +} +EXPORT_SYMBOL(mlx5_rdma_netdev_alloc); + +void mlx5_rdma_netdev_free(struct net_device *netdev) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + const struct mlx5e_profile *profile = priv->profile; + + mlx5e_detach_netdev(priv); + profile->cleanup(priv); + destroy_workqueue(priv->wq); + free_netdev(netdev); + + mlx5e_destroy_mdev_resources(priv->mdev); +} +EXPORT_SYMBOL(mlx5_rdma_netdev_free); + diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h new file mode 100644 index 000000000000..213191a78464 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017, Mellanox Technologies. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __MLX5E_IPOB_H__ +#define __MLX5E_IPOB_H__ + +#include +#include "en.h" + +#define MLX5I_MAX_NUM_TC 1 + +/* ipoib rdma netdev's private data structure */ +struct mlx5i_priv { + struct rdma_netdev rn; /* keep this first */ + struct mlx5_core_qp qp; + u32 qkey; + char *mlx5e_priv[0]; +}; + +/* Extract mlx5e_priv from IPoIB netdev */ +#define mlx5i_epriv(netdev) ((void *)(((struct mlx5i_priv *)netdev_priv(netdev))->mlx5e_priv)) + +netdev_tx_t mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, + struct mlx5_av *av, u32 dqpn, u32 dqkey); +void mlx5i_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe); + +#endif /* __MLX5E_IPOB_H__ */ -- cgit v1.2.3-59-g8ed1b From c66f2091c9248ddf42504c74cd327ae8619b04a4 Mon Sep 17 00:00:00 2001 From: Feras Daoud Date: Sun, 4 Jun 2017 17:45:02 +0300 Subject: net/mlx5e: Prevent PFC call for non ethernet ports Port flow control supported only for ethernet ports, therefore, prevent any call if the port type differs from MLX5_CAP_PORT_TYPE_ETH. Signed-off-by: Feras Daoud Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 216752070391..7408c298ce2f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -135,6 +135,9 @@ static unsigned long mlx5e_query_pfc_combined(struct mlx5e_priv *priv) u8 pfc_en_rx; int err; + if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) + return 0; + err = mlx5_query_port_pfc(mdev, &pfc_en_tx, &pfc_en_rx); return err ? 0 : pfc_en_tx | pfc_en_rx; @@ -147,6 +150,9 @@ static bool mlx5e_query_global_pause_combined(struct mlx5e_priv *priv) u32 tx_pause; int err; + if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) + return false; + err = mlx5_query_port_pause(mdev, &rx_pause, &tx_pause); return err ? false : rx_pause | tx_pause; -- cgit v1.2.3-59-g8ed1b From 076b0936e5fb8dd5513c1472a2c1d487b64d1580 Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Mon, 15 May 2017 13:32:28 +0300 Subject: net/mlx5e: IPoIB, Add ethtool support Add support for the following: "ethtool -S" (statistics). "ethtool -i" (driver info). "ethtool -g/G" (rings parameters). "ethtool -l/L" (channels parameters). "ethtool -c/C" (coalesce options). Signed-off-by: Erez Shitrit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en.h | 21 ++++ .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 138 +++++++++++++++------ .../ethernet/mellanox/mlx5/core/ipoib/ethtool.c | 127 +++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 2 +- .../net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h | 2 + 6 files changed, 255 insertions(+), 37 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 59b87b30e438..5ad093a21a6e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -15,4 +15,4 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \ mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o -mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o +mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 8094e78292de..49c5fe9fdff0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -1021,6 +1021,27 @@ int mlx5e_open(struct net_device *netdev); void mlx5e_update_stats_work(struct work_struct *work); u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout); +/* ethtool helpers */ +void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv, + struct ethtool_drvinfo *drvinfo); +void mlx5e_ethtool_get_strings(struct mlx5e_priv *priv, + uint32_t stringset, uint8_t *data); +int mlx5e_ethtool_get_sset_count(struct mlx5e_priv *priv, int sset); +void mlx5e_ethtool_get_ethtool_stats(struct mlx5e_priv *priv, + struct ethtool_stats *stats, u64 *data); +void mlx5e_ethtool_get_ringparam(struct mlx5e_priv *priv, + struct ethtool_ringparam *param); +int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv, + struct ethtool_ringparam *param); +void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv, + struct ethtool_channels *ch); +int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, + struct ethtool_channels *ch); +int mlx5e_ethtool_get_coalesce(struct mlx5e_priv *priv, + struct ethtool_coalesce *coal); +int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, + struct ethtool_coalesce *coal); + /* mlx5e generic netdev management API */ struct net_device* mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *profile, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 7408c298ce2f..fa472c4d3d00 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -32,10 +32,9 @@ #include "en.h" -static void mlx5e_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *drvinfo) +void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv, + struct ethtool_drvinfo *drvinfo) { - struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5_core_dev *mdev = priv->mdev; strlcpy(drvinfo->driver, DRIVER_NAME, sizeof(drvinfo->driver)); @@ -49,6 +48,14 @@ static void mlx5e_get_drvinfo(struct net_device *dev, sizeof(drvinfo->bus_info)); } +static void mlx5e_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + struct mlx5e_priv *priv = netdev_priv(dev); + + mlx5e_ethtool_get_drvinfo(priv, drvinfo); +} + struct ptys2ethtool_config { __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised); @@ -166,9 +173,8 @@ static bool mlx5e_query_global_pause_combined(struct mlx5e_priv *priv) ((mlx5e_query_global_pause_combined(priv) + hweight8(mlx5e_query_pfc_combined(priv))) * \ NUM_PPORT_PER_PRIO_PFC_COUNTERS) -static int mlx5e_get_sset_count(struct net_device *dev, int sset) +int mlx5e_ethtool_get_sset_count(struct mlx5e_priv *priv, int sset) { - struct mlx5e_priv *priv = netdev_priv(dev); switch (sset) { case ETH_SS_STATS: @@ -192,6 +198,13 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset) } } +static int mlx5e_get_sset_count(struct net_device *dev, int sset) +{ + struct mlx5e_priv *priv = netdev_priv(dev); + + return mlx5e_ethtool_get_sset_count(priv, sset); +} + static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data) { int i, j, tc, prio, idx = 0; @@ -279,10 +292,9 @@ static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data) priv->channel_tc2txq[i][tc]); } -static void mlx5e_get_strings(struct net_device *dev, - uint32_t stringset, uint8_t *data) +void mlx5e_ethtool_get_strings(struct mlx5e_priv *priv, + uint32_t stringset, uint8_t *data) { - struct mlx5e_priv *priv = netdev_priv(dev); int i; switch (stringset) { @@ -303,10 +315,17 @@ static void mlx5e_get_strings(struct net_device *dev, } } -static void mlx5e_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) +static void mlx5e_get_strings(struct net_device *dev, + uint32_t stringset, uint8_t *data) { struct mlx5e_priv *priv = netdev_priv(dev); + + mlx5e_ethtool_get_strings(priv, stringset, data); +} + +void mlx5e_ethtool_get_ethtool_stats(struct mlx5e_priv *priv, + struct ethtool_stats *stats, u64 *data) +{ struct mlx5e_channels *channels; struct mlx5_priv *mlx5_priv; int i, j, tc, prio, idx = 0; @@ -401,6 +420,15 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev, sq_stats_desc, j); } +static void mlx5e_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, + u64 *data) +{ + struct mlx5e_priv *priv = netdev_priv(dev); + + mlx5e_ethtool_get_ethtool_stats(priv, stats, data); +} + static u32 mlx5e_rx_wqes_to_packets(struct mlx5e_priv *priv, int rq_wq_type, int num_wqe) { @@ -445,10 +473,9 @@ static u32 mlx5e_packets_to_rx_wqes(struct mlx5e_priv *priv, int rq_wq_type, return 1 << (order_base_2(num_wqes)); } -static void mlx5e_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *param) +void mlx5e_ethtool_get_ringparam(struct mlx5e_priv *priv, + struct ethtool_ringparam *param) { - struct mlx5e_priv *priv = netdev_priv(dev); int rq_wq_type = priv->channels.params.rq_wq_type; param->rx_max_pending = mlx5e_rx_wqes_to_packets(priv, rq_wq_type, @@ -459,10 +486,17 @@ static void mlx5e_get_ringparam(struct net_device *dev, param->tx_pending = 1 << priv->channels.params.log_sq_size; } -static int mlx5e_set_ringparam(struct net_device *dev, - struct ethtool_ringparam *param) +static void mlx5e_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *param) { struct mlx5e_priv *priv = netdev_priv(dev); + + mlx5e_ethtool_get_ringparam(priv, param); +} + +int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv, + struct ethtool_ringparam *param) +{ int rq_wq_type = priv->channels.params.rq_wq_type; struct mlx5e_channels new_channels = {}; u32 rx_pending_wqes; @@ -474,12 +508,12 @@ static int mlx5e_set_ringparam(struct net_device *dev, int err = 0; if (param->rx_jumbo_pending) { - netdev_info(dev, "%s: rx_jumbo_pending not supported\n", + netdev_info(priv->netdev, "%s: rx_jumbo_pending not supported\n", __func__); return -EINVAL; } if (param->rx_mini_pending) { - netdev_info(dev, "%s: rx_mini_pending not supported\n", + netdev_info(priv->netdev, "%s: rx_mini_pending not supported\n", __func__); return -EINVAL; } @@ -492,13 +526,13 @@ static int mlx5e_set_ringparam(struct net_device *dev, param->rx_pending); if (param->rx_pending < min_rq_size) { - netdev_info(dev, "%s: rx_pending (%d) < min (%d)\n", + netdev_info(priv->netdev, "%s: rx_pending (%d) < min (%d)\n", __func__, param->rx_pending, min_rq_size); return -EINVAL; } if (param->rx_pending > max_rq_size) { - netdev_info(dev, "%s: rx_pending (%d) > max (%d)\n", + netdev_info(priv->netdev, "%s: rx_pending (%d) > max (%d)\n", __func__, param->rx_pending, max_rq_size); return -EINVAL; @@ -507,19 +541,19 @@ static int mlx5e_set_ringparam(struct net_device *dev, num_mtts = MLX5E_REQUIRED_MTTS(rx_pending_wqes); if (priv->channels.params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ && !MLX5E_VALID_NUM_MTTS(num_mtts)) { - netdev_info(dev, "%s: rx_pending (%d) request can't be satisfied, try to reduce.\n", + netdev_info(priv->netdev, "%s: rx_pending (%d) request can't be satisfied, try to reduce.\n", __func__, param->rx_pending); return -EINVAL; } if (param->tx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { - netdev_info(dev, "%s: tx_pending (%d) < min (%d)\n", + netdev_info(priv->netdev, "%s: tx_pending (%d) < min (%d)\n", __func__, param->tx_pending, 1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); return -EINVAL; } if (param->tx_pending > (1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE)) { - netdev_info(dev, "%s: tx_pending (%d) > max (%d)\n", + netdev_info(priv->netdev, "%s: tx_pending (%d) > max (%d)\n", __func__, param->tx_pending, 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE); return -EINVAL; @@ -555,26 +589,39 @@ unlock: return err; } -static void mlx5e_get_channels(struct net_device *dev, - struct ethtool_channels *ch) +static int mlx5e_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *param) { struct mlx5e_priv *priv = netdev_priv(dev); + return mlx5e_ethtool_set_ringparam(priv, param); +} + +void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv, + struct ethtool_channels *ch) +{ ch->max_combined = priv->profile->max_nch(priv->mdev); ch->combined_count = priv->channels.params.num_channels; } -static int mlx5e_set_channels(struct net_device *dev, - struct ethtool_channels *ch) +static void mlx5e_get_channels(struct net_device *dev, + struct ethtool_channels *ch) { struct mlx5e_priv *priv = netdev_priv(dev); + + mlx5e_ethtool_get_channels(priv, ch); +} + +int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, + struct ethtool_channels *ch) +{ unsigned int count = ch->combined_count; struct mlx5e_channels new_channels = {}; bool arfs_enabled; int err = 0; if (!count) { - netdev_info(dev, "%s: combined_count=0 not supported\n", + netdev_info(priv->netdev, "%s: combined_count=0 not supported\n", __func__); return -EINVAL; } @@ -599,7 +646,7 @@ static int mlx5e_set_channels(struct net_device *dev, if (err) goto out; - arfs_enabled = dev->features & NETIF_F_NTUPLE; + arfs_enabled = priv->netdev->features & NETIF_F_NTUPLE; if (arfs_enabled) mlx5e_arfs_disable(priv); @@ -609,7 +656,7 @@ static int mlx5e_set_channels(struct net_device *dev, if (arfs_enabled) { err = mlx5e_arfs_enable(priv); if (err) - netdev_err(dev, "%s: mlx5e_arfs_enable failed: %d\n", + netdev_err(priv->netdev, "%s: mlx5e_arfs_enable failed: %d\n", __func__, err); } @@ -619,11 +666,17 @@ out: return err; } -static int mlx5e_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *coal) +static int mlx5e_set_channels(struct net_device *dev, + struct ethtool_channels *ch) { - struct mlx5e_priv *priv = netdev_priv(netdev); + struct mlx5e_priv *priv = netdev_priv(dev); + + return mlx5e_ethtool_set_channels(priv, ch); +} +int mlx5e_ethtool_get_coalesce(struct mlx5e_priv *priv, + struct ethtool_coalesce *coal) +{ if (!MLX5_CAP_GEN(priv->mdev, cq_moderation)) return -EOPNOTSUPP; @@ -636,6 +689,14 @@ static int mlx5e_get_coalesce(struct net_device *netdev, return 0; } +static int mlx5e_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *coal) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); + + return mlx5e_ethtool_get_coalesce(priv, coal); +} + static void mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal) { @@ -659,10 +720,9 @@ mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesc } } -static int mlx5e_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *coal) +int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, + struct ethtool_coalesce *coal) { - struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5_core_dev *mdev = priv->mdev; struct mlx5e_channels new_channels = {}; int err = 0; @@ -705,6 +765,14 @@ out: return err; } +static int mlx5e_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *coal) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); + + return mlx5e_ethtool_set_coalesce(priv, coal); +} + static void ptys2ethtool_supported_link(unsigned long *supported_modes, u32 eth_proto_cap) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c new file mode 100644 index 000000000000..20105eda2e11 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017, Mellanox Technologies. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "en.h" +#include "ipoib.h" + +static void mlx5i_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + + mlx5e_ethtool_get_drvinfo(priv, drvinfo); +} + +static void mlx5i_get_strings(struct net_device *dev, + uint32_t stringset, uint8_t *data) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + + mlx5e_ethtool_get_strings(priv, stringset, data); +} + +static int mlx5i_get_sset_count(struct net_device *dev, int sset) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + + return mlx5e_ethtool_get_sset_count(priv, sset); +} + +static void mlx5i_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, + u64 *data) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + + mlx5e_ethtool_get_ethtool_stats(priv, stats, data); +} + +static int mlx5i_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *param) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + + return mlx5e_ethtool_set_ringparam(priv, param); +} + +static void mlx5i_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *param) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + + mlx5e_ethtool_get_ringparam(priv, param); +} + +static int mlx5i_set_channels(struct net_device *dev, + struct ethtool_channels *ch) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + + return mlx5e_ethtool_set_channels(priv, ch); +} + +static void mlx5i_get_channels(struct net_device *dev, + struct ethtool_channels *ch) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + + mlx5e_ethtool_get_channels(priv, ch); +} + +static int mlx5i_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *coal) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + + return mlx5e_ethtool_set_coalesce(priv, coal); +} + +static int mlx5i_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *coal) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + + return mlx5e_ethtool_get_coalesce(priv, coal); +} + +const struct ethtool_ops mlx5i_ethtool_ops = { + .get_drvinfo = mlx5i_get_drvinfo, + .get_strings = mlx5i_get_strings, + .get_sset_count = mlx5i_get_sset_count, + .get_ethtool_stats = mlx5i_get_ethtool_stats, + .get_ringparam = mlx5i_get_ringparam, + .set_ringparam = mlx5i_set_ringparam, + .get_channels = mlx5i_get_channels, + .set_channels = mlx5i_set_channels, + .get_coalesce = mlx5i_get_coalesce, + .set_coalesce = mlx5i_set_coalesce, +}; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 22ca59145e6c..fdeb426d4751 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -82,6 +82,7 @@ static void mlx5i_init(struct mlx5_core_dev *mdev, netdev->hw_features |= NETIF_F_RXHASH; netdev->netdev_ops = &mlx5i_netdev_ops; + netdev->ethtool_ops = &mlx5i_ethtool_ops; } /* Called directly before IPoIB netdevice is destroyed to cleanup SW structs */ @@ -510,4 +511,3 @@ void mlx5_rdma_netdev_free(struct net_device *netdev) mlx5e_destroy_mdev_resources(priv->mdev); } EXPORT_SYMBOL(mlx5_rdma_netdev_free); - diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h index 213191a78464..3553a06c8fa6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h @@ -38,6 +38,8 @@ #define MLX5I_MAX_NUM_TC 1 +extern const struct ethtool_ops mlx5i_ethtool_ops; + /* ipoib rdma netdev's private data structure */ struct mlx5i_priv { struct rdma_netdev rn; /* keep this first */ -- cgit v1.2.3-59-g8ed1b From 7ca42c8094a4e265b8007a6776380f57cf093624 Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Thu, 18 May 2017 14:32:11 +0300 Subject: net/mlx5e: Add new profile function update_carrier Updating the carrier involves specific HW setting, each profile should use its own function for that. Both IPoIB and VF representor don't need carrier update function, since VF representor has only a logical link to VF and IPoIB manages its own link via ib_core upper layer. Signed-off-by: Erez Shitrit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 14 ++++++++++---- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 2 ++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 49c5fe9fdff0..a223a8e15ece 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -782,6 +782,7 @@ struct mlx5e_profile { void (*enable)(struct mlx5e_priv *priv); void (*disable)(struct mlx5e_priv *priv); void (*update_stats)(struct mlx5e_priv *priv); + void (*update_carrier)(struct mlx5e_priv *priv); int (*max_nch)(struct mlx5_core_dev *mdev); struct { mlx5e_fp_handle_rx_cqe handle_rx_cqe; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 06eb7a8b487c..343be65621db 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -143,7 +143,8 @@ static void mlx5e_update_carrier_work(struct work_struct *work) mutex_lock(&priv->state_lock); if (test_bit(MLX5E_STATE_OPENED, &priv->state)) - mlx5e_update_carrier(priv); + if (priv->profile->update_carrier) + priv->profile->update_carrier(priv); mutex_unlock(&priv->state_lock); } @@ -2598,9 +2599,10 @@ void mlx5e_switch_priv_channels(struct mlx5e_priv *priv, { struct net_device *netdev = priv->netdev; int new_num_txqs; - + int carrier_ok; new_num_txqs = new_chs->num * new_chs->params.num_tc; + carrier_ok = netif_carrier_ok(netdev); netif_carrier_off(netdev); if (new_num_txqs < netdev->real_num_tx_queues) @@ -2618,7 +2620,9 @@ void mlx5e_switch_priv_channels(struct mlx5e_priv *priv, mlx5e_refresh_tirs(priv, false); mlx5e_activate_priv_channels(priv); - mlx5e_update_carrier(priv); + /* return carrier back if needed */ + if (carrier_ok) + netif_carrier_on(netdev); } int mlx5e_open_locked(struct net_device *netdev) @@ -2634,7 +2638,8 @@ int mlx5e_open_locked(struct net_device *netdev) mlx5e_refresh_tirs(priv, false); mlx5e_activate_priv_channels(priv); - mlx5e_update_carrier(priv); + if (priv->profile->update_carrier) + priv->profile->update_carrier(priv); mlx5e_timestamp_init(priv); if (priv->profile->update_stats) @@ -4215,6 +4220,7 @@ static const struct mlx5e_profile mlx5e_nic_profile = { .disable = mlx5e_nic_disable, .update_stats = mlx5e_update_ndo_stats, .max_nch = mlx5e_get_max_num_channels, + .update_carrier = mlx5e_update_carrier, .rx_handlers.handle_rx_cqe = mlx5e_handle_rx_cqe, .rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq, .max_tc = MLX5E_MAX_NUM_TC, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 01798e1ab667..a39873bd88a6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -916,6 +916,7 @@ static struct mlx5e_profile mlx5e_rep_profile = { .cleanup_tx = mlx5e_cleanup_nic_tx, .update_stats = mlx5e_rep_update_stats, .max_nch = mlx5e_get_rep_max_num_channels, + .update_carrier = NULL, .rx_handlers.handle_rx_cqe = mlx5e_handle_rx_cqe_rep, .rx_handlers.handle_rx_cqe_mpwqe = NULL /* Not supported */, .max_tc = 1, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index fdeb426d4751..cc9ff4014e5c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -291,6 +291,7 @@ static const struct mlx5e_profile mlx5i_nic_profile = { .disable = NULL, /* mlx5i_disable */ .update_stats = NULL, /* mlx5i_update_stats */ .max_nch = mlx5e_get_max_num_channels, + .update_carrier = NULL, /* no HW update in IB link */ .rx_handlers.handle_rx_cqe = mlx5i_handle_rx_cqe, .rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */ .max_tc = MLX5I_MAX_NUM_TC, @@ -337,6 +338,7 @@ static int mlx5i_open(struct net_device *netdev) mlx5e_refresh_tirs(priv, false); mlx5e_activate_priv_channels(priv); + mutex_unlock(&priv->state_lock); return 0; -- cgit v1.2.3-59-g8ed1b From b6dc510fac4796a57527667d47c48ef57a578dfc Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Thu, 18 May 2017 14:44:15 +0300 Subject: net/mlx5e: IPoIB, Change parameters default values Add function that sets the default values for ipoib, setting/clearing abilities that IPoIB doesn't support, like RQ size in this case. Signed-off-by: Erez Shitrit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index cc9ff4014e5c..45ca869118c0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -36,6 +36,7 @@ #include "ipoib.h" #define IB_DEFAULT_Q_KEY 0xb1b +#define MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE 9 static int mlx5i_open(struct net_device *netdev); static int mlx5i_close(struct net_device *netdev); @@ -50,6 +51,19 @@ static const struct net_device_ops mlx5i_netdev_ops = { }; /* IPoIB mlx5 netdev profile */ +static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev, + struct mlx5e_params *params) +{ + /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */ + mlx5e_set_rq_type_params(mdev, params, MLX5_WQ_TYPE_LINKED_LIST); + + /* RQ size in ipoib by default is 512 */ + params->log_rq_size = is_kdump_kernel() ? + MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE : + MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE; + + params->lro_en = false; +} /* Called directly after IPoIB netdevice was created to initialize SW structs */ static void mlx5i_init(struct mlx5_core_dev *mdev, @@ -65,10 +79,7 @@ static void mlx5i_init(struct mlx5_core_dev *mdev, priv->ppriv = ppriv; mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev)); - - /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */ - mlx5e_set_rq_type_params(mdev, &priv->channels.params, MLX5_WQ_TYPE_LINKED_LIST); - priv->channels.params.lro_en = false; + mlx5i_build_nic_params(mdev, &priv->channels.params); mutex_init(&priv->state_lock); -- cgit v1.2.3-59-g8ed1b From c139dbfddd2c7848550ed06345060aa87701e818 Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Thu, 18 May 2017 17:03:21 +0300 Subject: net/mlx5e: Use hard_mtu as part of the mlx5e_priv struct The mtu extra space that kept for the HW is specific for each link type, and it is different in mlx5e and mlx5i modules. Now it is kept in the priv structures, set by the mlx5e/mlx5i driver accordingly. Signed-off-by: Erez Shitrit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 7 +++++-- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 10 ++++++---- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 3 +++ drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 6 +----- drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 6 ++++-- drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h | 5 +++++ 6 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index a223a8e15ece..318ef7f0292f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -52,8 +52,10 @@ #define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v) -#define MLX5E_HW2SW_MTU(hwmtu) ((hwmtu) - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)) -#define MLX5E_SW2HW_MTU(swmtu) ((swmtu) + (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)) +#define MLX5E_ETH_HARD_MTU (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) + +#define MLX5E_HW2SW_MTU(priv, hwmtu) ((hwmtu) - ((priv)->hard_mtu)) +#define MLX5E_SW2HW_MTU(priv, swmtu) ((swmtu) + ((priv)->hard_mtu)) #define MLX5E_MAX_NUM_TC 8 @@ -747,6 +749,7 @@ struct mlx5e_priv { struct mlx5e_tir indir_tir[MLX5E_NUM_INDIR_TIRS]; struct mlx5e_tir direct_tir[MLX5E_MAX_NUM_CHANNELS]; u32 tx_rates[MLX5E_MAX_NUM_SQS]; + int hard_mtu; struct mlx5e_flow_steering fs; struct mlx5e_vxlan_db vxlan; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 343be65621db..de1e936fc2be 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -635,7 +635,7 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c, rq->buff.wqe_sz = params->lro_en ? params->lro_wqe_sz : - MLX5E_SW2HW_MTU(c->netdev->mtu); + MLX5E_SW2HW_MTU(c->priv, c->netdev->mtu); byte_count = rq->buff.wqe_sz; /* calc the required page order */ @@ -2468,7 +2468,7 @@ free_in: static int mlx5e_set_mtu(struct mlx5e_priv *priv, u16 mtu) { struct mlx5_core_dev *mdev = priv->mdev; - u16 hw_mtu = MLX5E_SW2HW_MTU(mtu); + u16 hw_mtu = MLX5E_SW2HW_MTU(priv, mtu); int err; err = mlx5_set_port_mtu(mdev, hw_mtu, 1); @@ -2490,7 +2490,7 @@ static void mlx5e_query_mtu(struct mlx5e_priv *priv, u16 *mtu) if (err || !hw_mtu) /* fallback to port oper mtu */ mlx5_query_port_oper_mtu(mdev, &hw_mtu, 1); - *mtu = MLX5E_HW2SW_MTU(hw_mtu); + *mtu = MLX5E_HW2SW_MTU(priv, hw_mtu); } static int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) @@ -3876,6 +3876,7 @@ void mlx5e_build_nic_params(struct mlx5_core_dev *mdev, mlx5e_set_rq_params(mdev, params); /* HW LRO */ + /* TODO: && MLX5_CAP_ETH(mdev, lro_cap) */ if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) params->lro_en = hw_lro_heuristic(link_speed, pci_bw); @@ -3916,6 +3917,7 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev, priv->netdev = netdev; priv->profile = profile; priv->ppriv = ppriv; + priv->hard_mtu = MLX5E_ETH_HARD_MTU; mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev)); @@ -4161,7 +4163,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv) /* MTU range: 68 - hw-specific max */ netdev->min_mtu = ETH_MIN_MTU; mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1); - netdev->max_mtu = MLX5E_HW2SW_MTU(max_mtu); + netdev->max_mtu = MLX5E_HW2SW_MTU(priv, max_mtu); mlx5e_set_dev_port_mtu(priv); mlx5_lag_add(mdev, netdev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index a39873bd88a6..76cb6ad6e00b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -833,6 +833,9 @@ static void mlx5e_init_rep(struct mlx5_core_dev *mdev, INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work); priv->channels.params.num_channels = profile->max_nch(mdev); + + priv->hard_mtu = MLX5E_ETH_HARD_MTU; + mlx5e_build_rep_params(mdev, &priv->channels.params); mlx5e_build_rep_netdev(netdev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 806139d62139..da42d55939ed 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -648,7 +648,7 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq, prefetchw(wqe); if (unlikely(dma_len < MLX5E_XDP_MIN_INLINE || - MLX5E_SW2HW_MTU(rq->netdev->mtu) < dma_len)) { + MLX5E_SW2HW_MTU(rq->channel->priv, rq->netdev->mtu) < dma_len)) { rq->stats.xdp_drop++; mlx5e_page_release(rq, di, true); return false; @@ -1038,11 +1038,7 @@ void mlx5e_free_xdpsq_descs(struct mlx5e_xdpsq *sq) #ifdef CONFIG_MLX5_CORE_IPOIB #define MLX5_IB_GRH_DGID_OFFSET 24 -#define MLX5_IB_GRH_BYTES 40 -#define MLX5_IPOIB_ENCAP_LEN 4 #define MLX5_GID_SIZE 16 -#define MLX5_IPOIB_PSEUDO_LEN 20 -#define MLX5_IPOIB_HARD_LEN (MLX5_IPOIB_PSEUDO_LEN + MLX5_IPOIB_ENCAP_LEN) static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 45ca869118c0..9cf5f465caae 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -73,16 +73,18 @@ static void mlx5i_init(struct mlx5_core_dev *mdev, { struct mlx5e_priv *priv = mlx5i_epriv(netdev); + /* priv init */ priv->mdev = mdev; priv->netdev = netdev; priv->profile = profile; priv->ppriv = ppriv; + priv->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN; + mutex_init(&priv->state_lock); mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev)); mlx5i_build_nic_params(mdev, &priv->channels.params); - mutex_init(&priv->state_lock); - + /* netdev init */ netdev->hw_features |= NETIF_F_SG; netdev->hw_features |= NETIF_F_IP_CSUM; netdev->hw_features |= NETIF_F_IPV6_CSUM; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h index 3553a06c8fa6..a0f405f520f7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h @@ -40,6 +40,11 @@ extern const struct ethtool_ops mlx5i_ethtool_ops; +#define MLX5_IB_GRH_BYTES 40 +#define MLX5_IPOIB_ENCAP_LEN 4 +#define MLX5_IPOIB_PSEUDO_LEN 20 +#define MLX5_IPOIB_HARD_LEN (MLX5_IPOIB_PSEUDO_LEN + MLX5_IPOIB_ENCAP_LEN) + /* ipoib rdma netdev's private data structure */ struct mlx5i_priv { struct rdma_netdev rn; /* keep this first */ -- cgit v1.2.3-59-g8ed1b From 807c4415974ff0d0bd101fd99ff6152feb22b0ac Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Sun, 21 May 2017 08:56:20 +0300 Subject: net/mlx5e: IPoIB, Handle change_mtu Add the ndo that supports change mtu for IPoIB. The callback called from the ipoib ULP driver, that gives the ability to change the SW and HW resources accordingly in the lower driver. Signed-off-by: Erez Shitrit Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 9cf5f465caae..52a58af571a2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -42,12 +42,14 @@ static int mlx5i_open(struct net_device *netdev); static int mlx5i_close(struct net_device *netdev); static int mlx5i_dev_init(struct net_device *dev); static void mlx5i_dev_cleanup(struct net_device *dev); +static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu); static const struct net_device_ops mlx5i_netdev_ops = { .ndo_open = mlx5i_open, .ndo_stop = mlx5i_close, .ndo_init = mlx5i_dev_init, .ndo_uninit = mlx5i_dev_cleanup, + .ndo_change_mtu = mlx5i_change_mtu, }; /* IPoIB mlx5 netdev profile */ @@ -312,6 +314,35 @@ static const struct mlx5e_profile mlx5i_nic_profile = { /* mlx5i netdev NDos */ +static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + struct mlx5e_channels new_channels = {}; + int curr_mtu; + int err = 0; + + mutex_lock(&priv->state_lock); + + curr_mtu = netdev->mtu; + netdev->mtu = new_mtu; + + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) + goto out; + + new_channels.params = priv->channels.params; + err = mlx5e_open_channels(priv, &new_channels); + if (err) { + netdev->mtu = curr_mtu; + goto out; + } + + mlx5e_switch_priv_channels(priv, &new_channels, NULL); + +out: + mutex_unlock(&priv->state_lock); + return err; +} + static int mlx5i_dev_init(struct net_device *dev) { struct mlx5e_priv *priv = mlx5i_epriv(dev); -- cgit v1.2.3-59-g8ed1b From 4ec5cf781b13ef9bcacfd96e108adb61629aa97a Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Sun, 21 May 2017 16:28:07 +0300 Subject: net/mlx5e: IPoIB, Get more TX statistics Add misses counters (bytes, packet, gso, xmit_more) in TX flow for ipoib traffic. Fixes: 58545449b7b ("net/mlx5e: IPoIB, Xmit flow") Signed-off-by: Erez Shitrit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 354f474322ce..0433d69429f3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -557,11 +557,16 @@ netdev_tx_t mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, if (skb_is_gso(skb)) { opcode = MLX5_OPCODE_LSO; ihs = mlx5e_txwqe_build_eseg_gso(sq, skb, eseg, &num_bytes); + sq->stats.packets += skb_shinfo(skb)->gso_segs; } else { ihs = mlx5e_calc_min_inline(sq->min_inline_mode, skb); num_bytes = max_t(unsigned int, skb->len, ETH_ZLEN); + sq->stats.packets++; } + sq->stats.bytes += num_bytes; + sq->stats.xmit_more += skb->xmit_more; + ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS; if (ihs) { memcpy(eseg->inline_hdr.start, skb_data, ihs); -- cgit v1.2.3-59-g8ed1b From 3844b07ee4c96d0cf8886611c21bb3a367b759e1 Mon Sep 17 00:00:00 2001 From: Feras Daoud Date: Thu, 1 Jun 2017 14:43:43 +0300 Subject: net/mlx5e: IPoIB, Add PTP support to IPoIB device driver Enable PTP for IPoIB rdma_netdev and add the ability to get the time stamping parameters using ethtool. Signed-off-by: Feras Daoud Signed-off-by: Eitan Rabin Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 ++ drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 15 +++++++++++---- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 ++++ drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c | 9 +++++++++ drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 2 ++ 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 318ef7f0292f..626683f0f487 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -1045,6 +1045,8 @@ int mlx5e_ethtool_get_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal); int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal); +int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv, + struct ethtool_ts_info *info); /* mlx5e generic netdev management API */ struct net_device* diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index fa472c4d3d00..ab46061f72ab 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1372,13 +1372,12 @@ static int mlx5e_set_pauseparam(struct net_device *netdev, return err; } -static int mlx5e_get_ts_info(struct net_device *dev, - struct ethtool_ts_info *info) +int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv, + struct ethtool_ts_info *info) { - struct mlx5e_priv *priv = netdev_priv(dev); int ret; - ret = ethtool_op_get_ts_info(dev, info); + ret = ethtool_op_get_ts_info(priv->netdev, info); if (ret) return ret; @@ -1401,6 +1400,14 @@ static int mlx5e_get_ts_info(struct net_device *dev, return 0; } +static int mlx5e_get_ts_info(struct net_device *dev, + struct ethtool_ts_info *info) +{ + struct mlx5e_priv *priv = netdev_priv(dev); + + return mlx5e_ethtool_get_ts_info(priv, info); +} + static __u32 mlx5e_get_wol_supported(struct mlx5_core_dev *mdev) { __u32 ret = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index da42d55939ed..abf6d2fcfe0f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1046,6 +1046,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq, struct sk_buff *skb) { struct net_device *netdev = rq->netdev; + struct mlx5e_tstamp *tstamp = rq->tstamp; char *pseudo_header; u8 *dgid; u8 g; @@ -1070,6 +1071,9 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq, skb->ip_summed = CHECKSUM_COMPLETE; skb->csum = csum_unfold((__force __sum16)cqe->check_sum); + if (unlikely(mlx5e_rx_hw_stamp(tstamp))) + mlx5e_fill_hwstamp(tstamp, get_cqe_ts(cqe), skb_hwtstamps(skb)); + skb_record_rx_queue(skb, rq->ix); if (likely(netdev->features & NETIF_F_RXHASH)) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c index 20105eda2e11..bf686f0fde5d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c @@ -113,6 +113,14 @@ static int mlx5i_get_coalesce(struct net_device *netdev, return mlx5e_ethtool_get_coalesce(priv, coal); } +static int mlx5i_get_ts_info(struct net_device *netdev, + struct ethtool_ts_info *info) +{ + struct mlx5e_priv *priv = mlx5i_epriv(netdev); + + return mlx5e_ethtool_get_ts_info(priv, info); +} + const struct ethtool_ops mlx5i_ethtool_ops = { .get_drvinfo = mlx5i_get_drvinfo, .get_strings = mlx5i_get_strings, @@ -124,4 +132,5 @@ const struct ethtool_ops mlx5i_ethtool_ops = { .set_channels = mlx5i_set_channels, .get_coalesce = mlx5i_get_coalesce, .set_coalesce = mlx5i_set_coalesce, + .get_ts_info = mlx5i_get_ts_info, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 52a58af571a2..58bf0665f50b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -382,6 +382,7 @@ static int mlx5i_open(struct net_device *netdev) mlx5e_refresh_tirs(priv, false); mlx5e_activate_priv_channels(priv); + mlx5e_timestamp_init(priv); mutex_unlock(&priv->state_lock); return 0; @@ -406,6 +407,7 @@ static int mlx5i_close(struct net_device *netdev) clear_bit(MLX5E_STATE_OPENED, &priv->state); + mlx5e_timestamp_cleanup(priv); netif_carrier_off(priv->netdev); mlx5e_deactivate_priv_channels(priv); mlx5e_close_channels(&priv->channels); -- cgit v1.2.3-59-g8ed1b From 1170fbd8ff43ff7808ae4a698054762b8bfae340 Mon Sep 17 00:00:00 2001 From: Feras Daoud Date: Thu, 1 Jun 2017 14:56:17 +0300 Subject: net/mlx5e: IPoIB, Add ioctl support to IPoIB device driver Add ioctl support to IPoIB device driver. For now, this ioctl will support timestamp get and set. Signed-off-by: Feras Daoud Signed-off-by: Eitan Rabin Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/en_clock.c | 10 ++++------ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 6 ++++-- drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 626683f0f487..5d9ace493d85 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -853,8 +853,8 @@ void mlx5e_timestamp_init(struct mlx5e_priv *priv); void mlx5e_timestamp_cleanup(struct mlx5e_priv *priv); void mlx5e_pps_event_handler(struct mlx5e_priv *priv, struct ptp_clock_event *event); -int mlx5e_hwstamp_set(struct net_device *dev, struct ifreq *ifr); -int mlx5e_hwstamp_get(struct net_device *dev, struct ifreq *ifr); +int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr); +int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr); int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool val); int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c index e29494464cae..66f432385dbb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c @@ -86,9 +86,8 @@ static void mlx5e_timestamp_overflow(struct work_struct *work) schedule_delayed_work(&tstamp->overflow_work, tstamp->overflow_period); } -int mlx5e_hwstamp_set(struct net_device *dev, struct ifreq *ifr) +int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr) { - struct mlx5e_priv *priv = netdev_priv(dev); struct hwtstamp_config config; int err; @@ -130,10 +129,10 @@ int mlx5e_hwstamp_set(struct net_device *dev, struct ifreq *ifr) case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_NTP_ALL: /* Disable CQE compression */ - netdev_warn(dev, "Disabling cqe compression"); + netdev_warn(priv->netdev, "Disabling cqe compression"); err = mlx5e_modify_rx_cqe_compression_locked(priv, false); if (err) { - netdev_err(dev, "Failed disabling cqe compression err=%d\n", err); + netdev_err(priv->netdev, "Failed disabling cqe compression err=%d\n", err); mutex_unlock(&priv->state_lock); return err; } @@ -151,9 +150,8 @@ int mlx5e_hwstamp_set(struct net_device *dev, struct ifreq *ifr) sizeof(config)) ? -EFAULT : 0; } -int mlx5e_hwstamp_get(struct net_device *dev, struct ifreq *ifr) +int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr) { - struct mlx5e_priv *priv = netdev_priv(dev); struct hwtstamp_config *cfg = &priv->tstamp.hwtstamp_config; if (!MLX5_CAP_GEN(priv->mdev, device_frequency_khz)) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index de1e936fc2be..20ee29a2209e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3317,11 +3317,13 @@ out: static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { + struct mlx5e_priv *priv = netdev_priv(dev); + switch (cmd) { case SIOCSHWTSTAMP: - return mlx5e_hwstamp_set(dev, ifr); + return mlx5e_hwstamp_set(priv, ifr); case SIOCGHWTSTAMP: - return mlx5e_hwstamp_get(dev, ifr); + return mlx5e_hwstamp_get(priv, ifr); default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 58bf0665f50b..1ee5bce85901 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -43,6 +43,7 @@ static int mlx5i_close(struct net_device *netdev); static int mlx5i_dev_init(struct net_device *dev); static void mlx5i_dev_cleanup(struct net_device *dev); static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu); +static int mlx5i_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static const struct net_device_ops mlx5i_netdev_ops = { .ndo_open = mlx5i_open, @@ -50,6 +51,7 @@ static const struct net_device_ops mlx5i_netdev_ops = { .ndo_init = mlx5i_dev_init, .ndo_uninit = mlx5i_dev_cleanup, .ndo_change_mtu = mlx5i_change_mtu, + .ndo_do_ioctl = mlx5i_ioctl, }; /* IPoIB mlx5 netdev profile */ @@ -356,6 +358,20 @@ static int mlx5i_dev_init(struct net_device *dev) return 0; } +static int mlx5i_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct mlx5e_priv *priv = mlx5i_epriv(dev); + + switch (cmd) { + case SIOCSHWTSTAMP: + return mlx5e_hwstamp_set(priv, ifr); + case SIOCGHWTSTAMP: + return mlx5e_hwstamp_get(priv, ifr); + default: + return -EOPNOTSUPP; + } +} + static void mlx5i_dev_cleanup(struct net_device *dev) { struct mlx5e_priv *priv = mlx5i_epriv(dev); -- cgit v1.2.3-59-g8ed1b