From patchwork Thu Oct 11 01:24:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Saeed Mahameed X-Patchwork-Id: 982175 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42VvVm5YbGz9s8F for ; Thu, 11 Oct 2018 13:07:28 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727219AbeJKJcZ (ORCPT ); Thu, 11 Oct 2018 05:32:25 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45073 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726798AbeJKJb4 (ORCPT ); Thu, 11 Oct 2018 05:31:56 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from saeedm@mellanox.com) with ESMTPS (AES256-SHA encrypted); 11 Oct 2018 03:29:48 +0200 Received: from sx1.hsd1.ca.comcast.net ([172.16.5.11]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w9B1Oq75030225; Thu, 11 Oct 2018 04:24:56 +0300 From: Saeed Mahameed To: "David S. Miller" Cc: netdev@vger.kernel.org, Jason Gunthorpe , linux-rdma@vger.kernel.org, Denis Drozdov , Saeed Mahameed Subject: [net-next 1/7] RDMA/netdev: Hoist alloc_netdev_mqs out of the driver Date: Wed, 10 Oct 2018 18:24:38 -0700 Message-Id: <20181011012444.28194-2-saeedm@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181011012444.28194-1-saeedm@mellanox.com> References: <20181011012444.28194-1-saeedm@mellanox.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Denis Drozdov netdev has several interfaces that expect to call alloc_netdev_mqs from the core code, with the driver only providing the arguments. This is incompatible with the rdma_netdev interface that returns the netdev directly. Thus re-organize the API used by ipoib so that the verbs core code calls alloc_netdev_mqs for the driver. This is done by allowing the drivers to provide the allocation parameters via a 'get_params' callback and then initializing an allocated netdev as a second step. Fixes: cd565b4b51e5 ("IB/IPoIB: Support acceleration options callbacks") Signed-off-by: Jason Gunthorpe Signed-off-by: Denis Drozdov Signed-off-by: Saeed Mahameed --- drivers/infiniband/core/verbs.c | 32 +++++++ drivers/infiniband/hw/mlx5/main.c | 23 ++--- drivers/infiniband/ulp/ipoib/ipoib_main.c | 21 ++--- .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 87 ++++++++++--------- include/linux/mlx5/driver.h | 14 +-- include/rdma/ib_verbs.h | 23 ++++- 6 files changed, 119 insertions(+), 81 deletions(-) diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 6ee03d6089eb..2f34d3412097 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -2621,3 +2621,35 @@ void ib_drain_qp(struct ib_qp *qp) ib_drain_rq(qp); } EXPORT_SYMBOL(ib_drain_qp); + +struct net_device *rdma_alloc_netdev(struct ib_device *device, u8 port_num, + enum rdma_netdev_t type, const char *name, + unsigned char name_assign_type, + void (*setup)(struct net_device *)) +{ + struct rdma_netdev_alloc_params params; + struct net_device *netdev; + int rc; + + if (!device->rdma_netdev_get_params) + return ERR_PTR(-EOPNOTSUPP); + + rc = device->rdma_netdev_get_params(device, port_num, type, ¶ms); + if (rc) + return ERR_PTR(rc); + + netdev = alloc_netdev_mqs(params.sizeof_priv, name, name_assign_type, + setup, params.txqs, params.rxqs); + if (!netdev) + return ERR_PTR(-ENOMEM); + + rc = params.initialize_rdma_netdev(device, port_num, netdev, + params.param); + if (rc) { + free_netdev(netdev); + return ERR_PTR(rc); + } + + return netdev; +} +EXPORT_SYMBOL(rdma_alloc_netdev); diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index c414f3809e5c..5d9b7f62a0ba 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -5163,22 +5163,14 @@ static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, return num_counters; } -static struct net_device* -mlx5_ib_alloc_rdma_netdev(struct ib_device *hca, - u8 port_num, - enum rdma_netdev_t type, - const char *name, - unsigned char name_assign_type, - void (*setup)(struct net_device *)) +static int mlx5_ib_rn_get_params(struct ib_device *device, u8 port_num, + enum rdma_netdev_t type, + struct rdma_netdev_alloc_params *params) { - struct net_device *netdev; - if (type != RDMA_NETDEV_IPOIB) - return ERR_PTR(-EOPNOTSUPP); + return -EOPNOTSUPP; - netdev = mlx5_rdma_netdev_alloc(to_mdev(hca)->mdev, hca, - name, setup); - return netdev; + return mlx5_rdma_rn_get_params(to_mdev(device)->mdev, device, params); } static void delay_drop_debugfs_cleanup(struct mlx5_ib_dev *dev) @@ -5824,8 +5816,9 @@ int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev) dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status; dev->ib_dev.get_dev_fw_str = get_dev_fw_str; dev->ib_dev.get_vector_affinity = mlx5_ib_get_vector_affinity; - if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) - dev->ib_dev.alloc_rdma_netdev = mlx5_ib_alloc_rdma_netdev; + if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads) && + IS_ENABLED(CONFIG_MLX5_CORE_IPOIB)) + dev->ib_dev.rdma_netdev_get_params = mlx5_ib_rn_get_params; if (mlx5_core_is_pf(mdev)) { dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index e3d28f9ad9c0..9c816cd41724 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -2146,20 +2146,15 @@ static struct net_device *ipoib_get_netdev(struct ib_device *hca, u8 port, { struct net_device *dev; - if (hca->alloc_rdma_netdev) { - dev = hca->alloc_rdma_netdev(hca, port, - RDMA_NETDEV_IPOIB, name, - NET_NAME_UNKNOWN, - ipoib_setup_common); - if (IS_ERR_OR_NULL(dev) && PTR_ERR(dev) != -EOPNOTSUPP) - return NULL; - } - - if (!hca->alloc_rdma_netdev || PTR_ERR(dev) == -EOPNOTSUPP) - dev = ipoib_create_netdev_default(hca, name, NET_NAME_UNKNOWN, - ipoib_setup_common); + dev = rdma_alloc_netdev(hca, port, RDMA_NETDEV_IPOIB, name, + NET_NAME_UNKNOWN, ipoib_setup_common); + if (!IS_ERR(dev)) + return dev; + if (PTR_ERR(dev) != -EOPNOTSUPP) + return NULL; - return dev; + return ipoib_create_netdev_default(hca, name, NET_NAME_UNKNOWN, + ipoib_setup_common); } struct ipoib_dev_priv *ipoib_intf_alloc(struct ib_device *hca, u8 port, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 299e2a897f7e..af1a95f80404 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -658,53 +658,36 @@ static void mlx5_rdma_netdev_free(struct net_device *netdev) } } -struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, - struct ib_device *ibdev, - const char *name, - void (*setup)(struct net_device *)) +static bool mlx5_is_sub_interface(struct mlx5_core_dev *mdev) { - const struct mlx5e_profile *profile; - struct net_device *netdev; + return mdev->mlx5e_res.pdn != 0; +} + +static const struct mlx5e_profile *mlx5_get_profile(struct mlx5_core_dev *mdev) +{ + if (mlx5_is_sub_interface(mdev)) + return mlx5i_pkey_get_profile(); + return &mlx5i_nic_profile; +} + +static int mlx5_rdma_setup_rn(struct ib_device *ibdev, u8 port_num, + struct net_device *netdev, void *param) +{ + struct mlx5_core_dev *mdev = (struct mlx5_core_dev *)param; + const struct mlx5e_profile *prof = mlx5_get_profile(mdev); struct mlx5i_priv *ipriv; struct mlx5e_priv *epriv; struct rdma_netdev *rn; - bool sub_interface; - int nch; int err; - if (mlx5i_check_required_hca_cap(mdev)) { - mlx5_core_warn(mdev, "Accelerated mode is not supported\n"); - return ERR_PTR(-EOPNOTSUPP); - } - - /* TODO: Need to find a better way to check if child device*/ - sub_interface = (mdev->mlx5e_res.pdn != 0); - - if (sub_interface) - profile = mlx5i_pkey_get_profile(); - else - profile = &mlx5i_nic_profile; - - nch = profile->max_nch(mdev); - - 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"); - return NULL; - } - ipriv = netdev_priv(netdev); epriv = mlx5i_epriv(netdev); epriv->wq = create_singlethread_workqueue("mlx5i"); if (!epriv->wq) - goto err_free_netdev; + return -ENOMEM; - ipriv->sub_interface = sub_interface; + ipriv->sub_interface = mlx5_is_sub_interface(mdev); if (!ipriv->sub_interface) { err = mlx5i_pkey_qpn_ht_init(netdev); if (err) { @@ -718,7 +701,7 @@ struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, goto destroy_ht; } - profile->init(mdev, netdev, profile, ipriv); + prof->init(mdev, netdev, prof, ipriv); mlx5e_attach_netdev(epriv); netif_carrier_off(netdev); @@ -734,15 +717,37 @@ struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, netdev->priv_destructor = mlx5_rdma_netdev_free; netdev->needs_free_netdev = 1; - return netdev; + return 0; destroy_ht: mlx5i_pkey_qpn_ht_cleanup(netdev); destroy_wq: destroy_workqueue(epriv->wq); -err_free_netdev: - free_netdev(netdev); + return err; +} + +int mlx5_rdma_rn_get_params(struct mlx5_core_dev *mdev, + struct ib_device *device, + struct rdma_netdev_alloc_params *params) +{ + int nch; + int rc; + + rc = mlx5i_check_required_hca_cap(mdev); + if (rc) + return rc; - return NULL; + nch = mlx5_get_profile(mdev)->max_nch(mdev); + + *params = (struct rdma_netdev_alloc_params){ + .sizeof_priv = sizeof(struct mlx5i_priv) + + sizeof(struct mlx5e_priv), + .txqs = nch * MLX5E_MAX_NUM_TC, + .rxqs = nch, + .param = mdev, + .initialize_rdma_netdev = mlx5_rdma_setup_rn, + }; + + return 0; } -EXPORT_SYMBOL(mlx5_rdma_netdev_alloc); +EXPORT_SYMBOL(mlx5_rdma_rn_get_params); diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 26a92462f4ce..4b75796cac23 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -1228,21 +1228,15 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev); void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up); -#ifndef CONFIG_MLX5_CORE_IPOIB -static inline -struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, - struct ib_device *ibdev, - const char *name, - void (*setup)(struct net_device *)) -{ - return ERR_PTR(-EOPNOTSUPP); -} -#else +#ifdef CONFIG_MLX5_CORE_IPOIB struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, struct ib_device *ibdev, const char *name, void (*setup)(struct net_device *)); #endif /* CONFIG_MLX5_CORE_IPOIB */ +int mlx5_rdma_rn_get_params(struct mlx5_core_dev *mdev, + struct ib_device *device, + struct rdma_netdev_alloc_params *params); struct mlx5_profile { u64 mask; diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index e950c2a68f06..020216cee8f1 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2223,6 +2223,16 @@ struct rdma_netdev { union ib_gid *gid, u16 mlid); }; +struct rdma_netdev_alloc_params { + size_t sizeof_priv; + unsigned int txqs; + unsigned int rxqs; + void *param; + + int (*initialize_rdma_netdev)(struct ib_device *device, u8 port_num, + struct net_device *netdev, void *param); +}; + struct ib_port_pkey_list { /* Lock to hold while modifying the list. */ spinlock_t list_lock; @@ -2523,8 +2533,8 @@ struct ib_device { /** * rdma netdev operation * - * Driver implementing alloc_rdma_netdev must return -EOPNOTSUPP if it - * doesn't support the specified rdma netdev type. + * Driver implementing alloc_rdma_netdev or rdma_netdev_get_params + * must return -EOPNOTSUPP if it doesn't support the specified type. */ struct net_device *(*alloc_rdma_netdev)( struct ib_device *device, @@ -2534,6 +2544,10 @@ struct ib_device { unsigned char name_assign_type, void (*setup)(struct net_device *)); + int (*rdma_netdev_get_params)(struct ib_device *device, u8 port_num, + enum rdma_netdev_t type, + struct rdma_netdev_alloc_params *params); + struct module *owner; struct device dev; struct kobject *ports_parent; @@ -4179,4 +4193,9 @@ struct ib_ucontext *ib_uverbs_get_ucontext(struct ib_uverbs_file *ufile); int uverbs_destroy_def_handler(struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs); + +struct net_device *rdma_alloc_netdev(struct ib_device *device, u8 port_num, + enum rdma_netdev_t type, const char *name, + unsigned char name_assign_type, + void (*setup)(struct net_device *)); #endif /* IB_VERBS_H */ From patchwork Thu Oct 11 01:24:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Saeed Mahameed X-Patchwork-Id: 982168 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42VvVM3NjPz9s8F for ; Thu, 11 Oct 2018 13:07:07 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727007AbeJKJb4 (ORCPT ); Thu, 11 Oct 2018 05:31:56 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45081 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726908AbeJKJby (ORCPT ); Thu, 11 Oct 2018 05:31:54 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from saeedm@mellanox.com) with ESMTPS (AES256-SHA encrypted); 11 Oct 2018 03:29:51 +0200 Received: from sx1.hsd1.ca.comcast.net ([172.16.5.11]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w9B1Oq76030225; Thu, 11 Oct 2018 04:24:58 +0300 From: Saeed Mahameed To: "David S. Miller" Cc: netdev@vger.kernel.org, Jason Gunthorpe , linux-rdma@vger.kernel.org, Denis Drozdov , Feras Daoud , Saeed Mahameed Subject: [net-next 2/7] RDMA/netdev: Fix netlink support in IPoIB Date: Wed, 10 Oct 2018 18:24:39 -0700 Message-Id: <20181011012444.28194-3-saeedm@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181011012444.28194-1-saeedm@mellanox.com> References: <20181011012444.28194-1-saeedm@mellanox.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Denis Drozdov IPoIB netlink support was broken by the below commit since integrating the rdma_netdev support relies on an allocation flow for netdevs that was controlled by the ipoib driver while netdev's rtnl_newlink implementation assumes that the netdev will be allocated by netlink. Such situation leads to crash in __ipoib_device_add, once trying to reuse netlink device. This patch fixes the kernel oops for both mlx4 and mlx5 devices triggered by the following command: Fixes: cd565b4b51e5 ("IB/IPoIB: Support acceleration options callbacks") Signed-off-by: Denis Drozdov Signed-off-by: Jason Gunthorpe Signed-off-by: Feras Daoud Signed-off-by: Saeed Mahameed --- drivers/infiniband/core/verbs.c | 28 +++-- drivers/infiniband/ulp/ipoib/ipoib.h | 8 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 123 +++++++++++-------- drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 23 +++- drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 19 +-- include/rdma/ib_verbs.h | 7 ++ 6 files changed, 136 insertions(+), 72 deletions(-) diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 2f34d3412097..8ec7418e99f0 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -2643,13 +2643,27 @@ struct net_device *rdma_alloc_netdev(struct ib_device *device, u8 port_num, if (!netdev) return ERR_PTR(-ENOMEM); - rc = params.initialize_rdma_netdev(device, port_num, netdev, - params.param); - if (rc) { - free_netdev(netdev); - return ERR_PTR(rc); - } - return netdev; } EXPORT_SYMBOL(rdma_alloc_netdev); + +int rdma_init_netdev(struct ib_device *device, u8 port_num, + enum rdma_netdev_t type, const char *name, + unsigned char name_assign_type, + void (*setup)(struct net_device *), + struct net_device *netdev) +{ + struct rdma_netdev_alloc_params params; + int rc; + + if (!device->rdma_netdev_get_params) + return -EOPNOTSUPP; + + rc = device->rdma_netdev_get_params(device, port_num, type, ¶ms); + if (rc) + return rc; + + return params.initialize_rdma_netdev(device, port_num, + netdev, params.param); +} +EXPORT_SYMBOL(rdma_init_netdev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 1abe3c62f106..1da119d901a9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -499,8 +499,10 @@ void ipoib_reap_ah(struct work_struct *work); struct ipoib_path *__path_find(struct net_device *dev, void *gid); void ipoib_mark_paths_invalid(struct net_device *dev); void ipoib_flush_paths(struct net_device *dev); -struct ipoib_dev_priv *ipoib_intf_alloc(struct ib_device *hca, u8 port, - const char *format); +struct net_device *ipoib_intf_alloc(struct ib_device *hca, u8 port, + const char *format); +int ipoib_intf_init(struct ib_device *hca, u8 port, const char *format, + struct net_device *dev); void ipoib_ib_tx_timer_func(struct timer_list *t); void ipoib_ib_dev_flush_light(struct work_struct *work); void ipoib_ib_dev_flush_normal(struct work_struct *work); @@ -531,6 +533,8 @@ int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req); void ipoib_dma_unmap_tx(struct ipoib_dev_priv *priv, struct ipoib_tx_buf *tx_req); +struct rtnl_link_ops *ipoib_get_link_ops(void); + static inline void ipoib_build_sge(struct ipoib_dev_priv *priv, struct ipoib_tx_buf *tx_req) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 9c816cd41724..8baa75a705c5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -2115,77 +2115,58 @@ static const struct net_device_ops ipoib_netdev_default_pf = { .ndo_stop = ipoib_ib_dev_stop_default, }; -static struct net_device -*ipoib_create_netdev_default(struct ib_device *hca, - const char *name, - unsigned char name_assign_type, - void (*setup)(struct net_device *)) -{ - struct net_device *dev; - struct rdma_netdev *rn; - - dev = alloc_netdev((int)sizeof(struct rdma_netdev), - name, - name_assign_type, setup); - if (!dev) - return NULL; - - rn = netdev_priv(dev); - - rn->send = ipoib_send; - rn->attach_mcast = ipoib_mcast_attach; - rn->detach_mcast = ipoib_mcast_detach; - rn->hca = hca; - dev->netdev_ops = &ipoib_netdev_default_pf; - - return dev; -} - -static struct net_device *ipoib_get_netdev(struct ib_device *hca, u8 port, - const char *name) +static struct net_device *ipoib_alloc_netdev(struct ib_device *hca, u8 port, + const char *name) { struct net_device *dev; dev = rdma_alloc_netdev(hca, port, RDMA_NETDEV_IPOIB, name, NET_NAME_UNKNOWN, ipoib_setup_common); - if (!IS_ERR(dev)) + if (!IS_ERR(dev) || PTR_ERR(dev) != -EOPNOTSUPP) return dev; - if (PTR_ERR(dev) != -EOPNOTSUPP) - return NULL; - return ipoib_create_netdev_default(hca, name, NET_NAME_UNKNOWN, - ipoib_setup_common); + dev = alloc_netdev(sizeof(struct rdma_netdev), name, NET_NAME_UNKNOWN, + ipoib_setup_common); + if (!dev) + return ERR_PTR(-ENOMEM); + return dev; } -struct ipoib_dev_priv *ipoib_intf_alloc(struct ib_device *hca, u8 port, - const char *name) +int ipoib_intf_init(struct ib_device *hca, u8 port, const char *name, + struct net_device *dev) { - struct net_device *dev; + struct rdma_netdev *rn = netdev_priv(dev); struct ipoib_dev_priv *priv; - struct rdma_netdev *rn; + int rc; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) - return NULL; + return -ENOMEM; priv->ca = hca; priv->port = port; - dev = ipoib_get_netdev(hca, port, name); - if (!dev) - goto free_priv; + rc = rdma_init_netdev(hca, port, RDMA_NETDEV_IPOIB, name, + NET_NAME_UNKNOWN, ipoib_setup_common, dev); + if (rc) { + if (rc != -EOPNOTSUPP) + goto out; + + dev->netdev_ops = &ipoib_netdev_default_pf; + rn->send = ipoib_send; + rn->attach_mcast = ipoib_mcast_attach; + rn->detach_mcast = ipoib_mcast_detach; + rn->hca = hca; + } priv->rn_ops = dev->netdev_ops; - /* fixme : should be after the query_cap */ - if (priv->hca_caps & IB_DEVICE_VIRTUAL_FUNCTION) + if (hca->attrs.device_cap_flags & IB_DEVICE_VIRTUAL_FUNCTION) dev->netdev_ops = &ipoib_netdev_ops_vf; else dev->netdev_ops = &ipoib_netdev_ops_pf; - rn = netdev_priv(dev); rn->clnt_priv = priv; - /* * Only the child register_netdev flows can handle priv_destructor * being set, so we force it to NULL here and handle manually until it @@ -2196,10 +2177,35 @@ struct ipoib_dev_priv *ipoib_intf_alloc(struct ib_device *hca, u8 port, ipoib_build_priv(dev); - return priv; -free_priv: + return 0; + +out: kfree(priv); - return NULL; + return rc; +} + +struct net_device *ipoib_intf_alloc(struct ib_device *hca, u8 port, + const char *name) +{ + struct net_device *dev; + int rc; + + dev = ipoib_alloc_netdev(hca, port, name); + if (IS_ERR(dev)) + return dev; + + rc = ipoib_intf_init(hca, port, name, dev); + if (rc) { + free_netdev(dev); + return ERR_PTR(rc); + } + + /* + * Upon success the caller must ensure ipoib_intf_free is called or + * register_netdevice succeed'd and priv_destructor is set to + * ipoib_intf_free. + */ + return dev; } void ipoib_intf_free(struct net_device *dev) @@ -2382,16 +2388,19 @@ int ipoib_add_pkey_attr(struct net_device *dev) static struct net_device *ipoib_add_port(const char *format, struct ib_device *hca, u8 port) { + struct rtnl_link_ops *ops = ipoib_get_link_ops(); + struct rdma_netdev_alloc_params params; struct ipoib_dev_priv *priv; struct net_device *ndev; int result; - priv = ipoib_intf_alloc(hca, port, format); - if (!priv) { - pr_warn("%s, %d: ipoib_intf_alloc failed\n", hca->name, port); - return ERR_PTR(-ENOMEM); + ndev = ipoib_intf_alloc(hca, port, format); + if (IS_ERR(ndev)) { + pr_warn("%s, %d: ipoib_intf_alloc failed %ld\n", hca->name, port, + PTR_ERR(ndev)); + return ndev; } - ndev = priv->dev; + priv = ipoib_priv(ndev); INIT_IB_EVENT_HANDLER(&priv->event_handler, priv->ca, ipoib_event); @@ -2412,6 +2421,14 @@ static struct net_device *ipoib_add_port(const char *format, return ERR_PTR(result); } + if (hca->rdma_netdev_get_params) { + int rc = hca->rdma_netdev_get_params(hca, port, + RDMA_NETDEV_IPOIB, + ¶ms); + + if (!rc && ops->priv_size < params.sizeof_priv) + ops->priv_size = params.sizeof_priv; + } /* * We cannot set priv_destructor before register_netdev because we * need priv to be always valid during the error flow to execute diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c index d4d553a51fa9..38c984d16996 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c @@ -122,12 +122,26 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, } else child_pkey = nla_get_u16(data[IFLA_IPOIB_PKEY]); + err = ipoib_intf_init(ppriv->ca, ppriv->port, dev->name, dev); + if (err) { + ipoib_warn(ppriv, "failed to initialize pkey device\n"); + return err; + } + err = __ipoib_vlan_add(ppriv, ipoib_priv(dev), child_pkey, IPOIB_RTNL_CHILD); + if (err) + return err; - if (!err && data) + if (data) { err = ipoib_changelink(dev, tb, data, extack); - return err; + if (err) { + unregister_netdevice(dev); + return err; + } + } + + return 0; } static size_t ipoib_get_size(const struct net_device *dev) @@ -149,6 +163,11 @@ static struct rtnl_link_ops ipoib_link_ops __read_mostly = { .fill_info = ipoib_fill_info, }; +struct rtnl_link_ops *ipoib_get_link_ops(void) +{ + return &ipoib_link_ops; +} + int __init ipoib_netlink_init(void) { return rtnl_link_register(&ipoib_link_ops); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 341753fbda54..8ac8e18fbe0c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -85,7 +85,7 @@ static bool is_child_unique(struct ipoib_dev_priv *ppriv, /* * NOTE: If this function fails then the priv->dev will remain valid, however - * priv can have been freed and must not be touched by caller in the error + * priv will have been freed and must not be touched by caller in the error * case. * * If (ndev->reg_state == NETREG_UNINITIALIZED) then it is up to the caller to @@ -100,6 +100,12 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, ASSERT_RTNL(); + /* + * We do not need to touch priv if register_netdevice fails, so just + * always use this flow. + */ + ndev->priv_destructor = ipoib_intf_free; + /* * Racing with unregister of the parent must be prevented by the * caller. @@ -120,9 +126,6 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, goto out_early; } - /* We do not need to touch priv if register_netdevice fails */ - ndev->priv_destructor = ipoib_intf_free; - result = register_netdevice(ndev); if (result) { ipoib_warn(priv, "failed to initialize; error %i", result); @@ -182,12 +185,12 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) snprintf(intf_name, sizeof(intf_name), "%s.%04x", ppriv->dev->name, pkey); - priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name); - if (!priv) { - result = -ENOMEM; + ndev = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name); + if (IS_ERR(ndev)) { + result = PTR_ERR(ndev); goto out; } - ndev = priv->dev; + priv = ipoib_priv(ndev); result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD); diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 020216cee8f1..0ed5d913a492 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -4198,4 +4198,11 @@ struct net_device *rdma_alloc_netdev(struct ib_device *device, u8 port_num, enum rdma_netdev_t type, const char *name, unsigned char name_assign_type, void (*setup)(struct net_device *)); + +int rdma_init_netdev(struct ib_device *device, u8 port_num, + enum rdma_netdev_t type, const char *name, + unsigned char name_assign_type, + void (*setup)(struct net_device *), + struct net_device *netdev); + #endif /* IB_VERBS_H */ From patchwork Thu Oct 11 01:24:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Saeed Mahameed X-Patchwork-Id: 982166 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42VvVF3pgpz9sB7 for ; Thu, 11 Oct 2018 13:07:01 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727039AbeJKJb5 (ORCPT ); Thu, 11 Oct 2018 05:31:57 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45091 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726920AbeJKJb4 (ORCPT ); Thu, 11 Oct 2018 05:31:56 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from saeedm@mellanox.com) with ESMTPS (AES256-SHA encrypted); 11 Oct 2018 03:29:54 +0200 Received: from sx1.hsd1.ca.comcast.net ([172.16.5.11]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w9B1Oq77030225; Thu, 11 Oct 2018 04:25:01 +0300 From: Saeed Mahameed To: "David S. Miller" Cc: netdev@vger.kernel.org, Jason Gunthorpe , linux-rdma@vger.kernel.org, Feras Daoud , Saeed Mahameed Subject: [net-next 3/7] net/mlx5e: Gather common netdev init/cleanup functionality in one place Date: Wed, 10 Oct 2018 18:24:40 -0700 Message-Id: <20181011012444.28194-4-saeedm@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181011012444.28194-1-saeedm@mellanox.com> References: <20181011012444.28194-1-saeedm@mellanox.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Feras Daoud Introduce a helper init/cleanup function that initializes mlx5e generic netdev private structure, and use them from all profiles init/cleanup callbacks. This patch will also be helpful to initialize/cleanup netdevs that are not created by mlx5 driver, e.g: accelerated ipoib child netdevs. Fixes: 26e59d8077a3 ("net/mlx5e: Implement mlx5e interface attach/detach callbacks") Signed-off-by: Feras Daoud Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 4 +- .../net/ethernet/mellanox/mlx5/core/en_main.c | 53 ++++++++++++------- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 25 ++++++--- .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 28 +++++----- .../ethernet/mellanox/mlx5/core/ipoib/ipoib.h | 9 ++-- .../mellanox/mlx5/core/ipoib/ipoib_vlan.c | 17 +++--- 6 files changed, 87 insertions(+), 49 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 1d743bd5d212..4b2737c613fe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -698,7 +698,7 @@ struct mlx5e_priv { }; struct mlx5e_profile { - void (*init)(struct mlx5_core_dev *mdev, + int (*init)(struct mlx5_core_dev *mdev, struct net_device *netdev, const struct mlx5e_profile *profile, void *ppriv); void (*cleanup)(struct mlx5e_priv *priv); @@ -962,6 +962,8 @@ int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv, struct ethtool_flash *flash); /* mlx5e generic netdev management API */ +int mlx5e_netdev_init(struct net_device *netdev, struct mlx5e_priv *priv); +void mlx5e_netdev_cleanup(struct net_device *netdev, struct mlx5e_priv *priv); struct net_device* mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *profile, void *ppriv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index bc034958c846..376197c97e3b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4749,14 +4749,18 @@ void mlx5e_destroy_q_counters(struct mlx5e_priv *priv) mlx5_core_dealloc_q_counter(priv->mdev, priv->drop_rq_q_counter); } -static void mlx5e_nic_init(struct mlx5_core_dev *mdev, - struct net_device *netdev, - const struct mlx5e_profile *profile, - void *ppriv) +static int mlx5e_nic_init(struct mlx5_core_dev *mdev, + struct net_device *netdev, + const struct mlx5e_profile *profile, + void *ppriv) { struct mlx5e_priv *priv = netdev_priv(netdev); int err; + err = mlx5e_netdev_init(netdev, priv); + if (err) + return err; + mlx5e_build_nic_netdev_priv(mdev, netdev, profile, ppriv); err = mlx5e_ipsec_init(priv); if (err) @@ -4766,12 +4770,15 @@ static void mlx5e_nic_init(struct mlx5_core_dev *mdev, mlx5_core_err(mdev, "TLS initialization failed, %d\n", err); mlx5e_build_nic_netdev(netdev); mlx5e_build_tc2txq_maps(priv); + + return 0; } static void mlx5e_nic_cleanup(struct mlx5e_priv *priv) { mlx5e_tls_cleanup(priv); mlx5e_ipsec_cleanup(priv); + mlx5e_netdev_cleanup(priv->netdev, priv); } static int mlx5e_init_nic_rx(struct mlx5e_priv *priv) @@ -4943,13 +4950,30 @@ static const struct mlx5e_profile mlx5e_nic_profile = { /* mlx5e generic netdev management API (move to en_common.c) */ +/* mlx5e_netdev_init/cleanup must be called from profile->init/cleanup callbacks */ +int mlx5e_netdev_init(struct net_device *netdev, struct mlx5e_priv *priv) +{ + netif_carrier_off(netdev); + + priv->wq = create_singlethread_workqueue("mlx5e"); + if (!priv->wq) + return -ENOMEM; + + return 0; +} + +void mlx5e_netdev_cleanup(struct net_device *netdev, struct mlx5e_priv *priv) +{ + destroy_workqueue(priv->wq); +} + struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *profile, void *ppriv) { int nch = profile->max_nch(mdev); struct net_device *netdev; - struct mlx5e_priv *priv; + int err; netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv), nch * profile->max_tc, @@ -4963,21 +4987,15 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev, netdev->rx_cpu_rmap = mdev->rmap; #endif - profile->init(mdev, netdev, profile, ppriv); - - netif_carrier_off(netdev); - - priv = netdev_priv(netdev); - - priv->wq = create_singlethread_workqueue("mlx5e"); - if (!priv->wq) - goto err_cleanup_nic; + err = profile->init(mdev, netdev, profile, ppriv); + if (err) { + mlx5_core_err(mdev, "failed to init mlx5e profile %d\n", err); + goto err_free_netdev; + } return netdev; -err_cleanup_nic: - if (profile->cleanup) - profile->cleanup(priv); +err_free_netdev: free_netdev(netdev); return NULL; @@ -5031,7 +5049,6 @@ void mlx5e_destroy_netdev(struct mlx5e_priv *priv) const struct mlx5e_profile *profile = priv->profile; struct net_device *netdev = priv->netdev; - destroy_workqueue(priv->wq); if (profile->cleanup) profile->cleanup(priv); free_netdev(netdev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 9264c3332aa6..6176e53c8b83 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1078,28 +1078,40 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev) netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu); } -static void mlx5e_init_rep(struct mlx5_core_dev *mdev, - struct net_device *netdev, - const struct mlx5e_profile *profile, - void *ppriv) +static int mlx5e_init_rep(struct mlx5_core_dev *mdev, + struct net_device *netdev, + const struct mlx5e_profile *profile, + void *ppriv) { struct mlx5e_priv *priv = netdev_priv(netdev); + int err; priv->mdev = mdev; priv->netdev = netdev; priv->profile = profile; priv->ppriv = ppriv; - mutex_init(&priv->state_lock); + err = mlx5e_netdev_init(netdev, priv); + if (err) + return err; INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work); - priv->channels.params.num_channels = 1; + mutex_init(&priv->state_lock); + + priv->channels.params.num_channels = profile->max_nch(mdev); mlx5e_build_rep_params(mdev, &priv->channels.params, netdev->mtu); mlx5e_build_rep_netdev(netdev); mlx5e_timestamp_init(priv); + + return 0; +} + +static void mlx5e_cleanup_rep(struct mlx5e_priv *priv) +{ + mlx5e_netdev_cleanup(priv->netdev, priv); } static int mlx5e_create_rep_ttc_table(struct mlx5e_priv *priv) @@ -1224,6 +1236,7 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) static const struct mlx5e_profile mlx5e_rep_profile = { .init = mlx5e_init_rep, + .cleanup = mlx5e_cleanup_rep, .init_rx = mlx5e_init_rep_rx, .cleanup_rx = mlx5e_cleanup_rep_rx, .init_tx = mlx5e_init_rep_tx, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index af1a95f80404..3f544baab9c9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -71,13 +71,14 @@ static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev, } /* Called directly after IPoIB netdevice was created to initialize SW structs */ -void mlx5i_init(struct mlx5_core_dev *mdev, - struct net_device *netdev, - const struct mlx5e_profile *profile, - void *ppriv) +int 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); u16 max_mtu; + int err; /* priv init */ priv->mdev = mdev; @@ -87,6 +88,10 @@ void mlx5i_init(struct mlx5_core_dev *mdev, priv->max_opened_tc = 1; mutex_init(&priv->state_lock); + err = mlx5e_netdev_init(netdev, priv); + if (err) + return err; + mlx5_query_port_max_mtu(mdev, &max_mtu, 1); netdev->mtu = max_mtu; @@ -108,12 +113,14 @@ void mlx5i_init(struct mlx5_core_dev *mdev, netdev->netdev_ops = &mlx5i_netdev_ops; netdev->ethtool_ops = &mlx5i_ethtool_ops; + + return 0; } /* Called directly before IPoIB netdevice is destroyed to cleanup SW structs */ -static void mlx5i_cleanup(struct mlx5e_priv *priv) +void mlx5i_cleanup(struct mlx5e_priv *priv) { - /* Do nothing .. */ + mlx5e_netdev_cleanup(priv->netdev, priv); } static void mlx5i_grp_sw_update_stats(struct mlx5e_priv *priv) @@ -650,7 +657,6 @@ static void mlx5_rdma_netdev_free(struct net_device *netdev) mlx5e_detach_netdev(priv); profile->cleanup(priv); - destroy_workqueue(priv->wq); if (!ipriv->sub_interface) { mlx5i_pkey_qpn_ht_cleanup(netdev); @@ -683,16 +689,12 @@ static int mlx5_rdma_setup_rn(struct ib_device *ibdev, u8 port_num, ipriv = netdev_priv(netdev); epriv = mlx5i_epriv(netdev); - epriv->wq = create_singlethread_workqueue("mlx5i"); - if (!epriv->wq) - return -ENOMEM; - ipriv->sub_interface = mlx5_is_sub_interface(mdev); if (!ipriv->sub_interface) { err = mlx5i_pkey_qpn_ht_init(netdev); if (err) { mlx5_core_warn(mdev, "allocate qpn_to_netdev ht failed\n"); - goto destroy_wq; + return err; } /* This should only be called once per mdev */ @@ -721,8 +723,6 @@ static int mlx5_rdma_setup_rn(struct ib_device *ibdev, u8 port_num, destroy_ht: mlx5i_pkey_qpn_ht_cleanup(netdev); -destroy_wq: - destroy_workqueue(epriv->wq); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h index 2e7fb829e1b0..5ef3ef0072b4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h @@ -84,10 +84,11 @@ void mlx5i_dev_cleanup(struct net_device *dev); int mlx5i_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); /* Parent profile functions */ -void mlx5i_init(struct mlx5_core_dev *mdev, - struct net_device *netdev, - const struct mlx5e_profile *profile, - void *ppriv); +int mlx5i_init(struct mlx5_core_dev *mdev, + struct net_device *netdev, + const struct mlx5e_profile *profile, + void *ppriv); +void mlx5i_cleanup(struct mlx5e_priv *priv); /* Get child interface nic profile */ const struct mlx5e_profile *mlx5i_pkey_get_profile(void); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c index e3e8a5f1ac9b..3dbfa532fda1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c @@ -275,14 +275,17 @@ static int mlx5i_pkey_change_mtu(struct net_device *netdev, int new_mtu) } /* Called directly after IPoIB netdevice was created to initialize SW structs */ -static void mlx5i_pkey_init(struct mlx5_core_dev *mdev, - struct net_device *netdev, - const struct mlx5e_profile *profile, - void *ppriv) +static int mlx5i_pkey_init(struct mlx5_core_dev *mdev, + struct net_device *netdev, + const struct mlx5e_profile *profile, + void *ppriv) { struct mlx5e_priv *priv = mlx5i_epriv(netdev); + int err; - mlx5i_init(mdev, netdev, profile, ppriv); + err = mlx5i_init(mdev, netdev, profile, ppriv); + if (err) + return err; /* Override parent ndo */ netdev->netdev_ops = &mlx5i_pkey_netdev_ops; @@ -292,12 +295,14 @@ static void mlx5i_pkey_init(struct mlx5_core_dev *mdev, /* Use dummy rqs */ priv->channels.params.log_rq_mtu_frames = MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE; + + return 0; } /* Called directly before IPoIB netdevice is destroyed to cleanup SW structs */ static void mlx5i_pkey_cleanup(struct mlx5e_priv *priv) { - /* Do nothing .. */ + mlx5i_cleanup(priv); } static int mlx5i_pkey_init_tx(struct mlx5e_priv *priv) From patchwork Thu Oct 11 01:24:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Saeed Mahameed X-Patchwork-Id: 982165 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42VvVD5Srmz9s8F for ; Thu, 11 Oct 2018 13:07:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727029AbeJKJb4 (ORCPT ); Thu, 11 Oct 2018 05:31:56 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45103 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726944AbeJKJby (ORCPT ); Thu, 11 Oct 2018 05:31:54 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from saeedm@mellanox.com) with ESMTPS (AES256-SHA encrypted); 11 Oct 2018 03:29:57 +0200 Received: from sx1.hsd1.ca.comcast.net ([172.16.5.11]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w9B1Oq78030225; Thu, 11 Oct 2018 04:25:04 +0300 From: Saeed Mahameed To: "David S. Miller" Cc: netdev@vger.kernel.org, Jason Gunthorpe , linux-rdma@vger.kernel.org, Feras Daoud , Saeed Mahameed Subject: [net-next 4/7] net/mlx5e: Always initialize update stats delayed work Date: Wed, 10 Oct 2018 18:24:41 -0700 Message-Id: <20181011012444.28194-5-saeedm@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181011012444.28194-1-saeedm@mellanox.com> References: <20181011012444.28194-1-saeedm@mellanox.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Feras Daoud mlx5e_detach_netdev cancels update_stats work which was not initialized in ipoib netdevice profile, as a result, the following assert occurs: ODEBUG: assert_init not available (active state 0) object type: timer_list hint:(null) This change moves the update stats work to be initialized for all mlx5e netdevices. Fixes: cd565b4b51e5 ("IB/IPoIB: Support acceleration options callbacks") Signed-off-by: Feras Daoud Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 - drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 5 +++-- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 4b2737c613fe..59d07a6fe7c5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -926,7 +926,6 @@ int mlx5e_create_tises(struct mlx5e_priv *priv); void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv); int mlx5e_close(struct net_device *netdev); int mlx5e_open(struct net_device *netdev); -void mlx5e_update_stats_work(struct work_struct *work); int mlx5e_bits_invert(unsigned long a, int size); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 376197c97e3b..9cf5863b7949 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -272,7 +272,7 @@ static void mlx5e_update_ndo_stats(struct mlx5e_priv *priv) mlx5e_stats_grps[i].update_stats(priv); } -void mlx5e_update_stats_work(struct work_struct *work) +static void mlx5e_update_stats_work(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct mlx5e_priv *priv = container_of(dwork, struct mlx5e_priv, @@ -4582,7 +4582,6 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev, INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work); INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work); INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work); - INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work); mlx5e_timestamp_init(priv); } @@ -4955,6 +4954,8 @@ int mlx5e_netdev_init(struct net_device *netdev, struct mlx5e_priv *priv) { netif_carrier_off(netdev); + INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work); + priv->wq = create_singlethread_workqueue("mlx5e"); if (!priv->wq) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 6176e53c8b83..bd8caac2e572 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1095,8 +1095,6 @@ static int mlx5e_init_rep(struct mlx5_core_dev *mdev, if (err) return err; - INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work); - mutex_init(&priv->state_lock); priv->channels.params.num_channels = profile->max_nch(mdev); From patchwork Thu Oct 11 01:24:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Saeed Mahameed X-Patchwork-Id: 982174 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42VvVl3Y19z9sB7 for ; Thu, 11 Oct 2018 13:07:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726990AbeJKJb4 (ORCPT ); Thu, 11 Oct 2018 05:31:56 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45114 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726955AbeJKJbz (ORCPT ); Thu, 11 Oct 2018 05:31:55 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from saeedm@mellanox.com) with ESMTPS (AES256-SHA encrypted); 11 Oct 2018 03:30:00 +0200 Received: from sx1.hsd1.ca.comcast.net ([172.16.5.11]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w9B1Oq79030225; Thu, 11 Oct 2018 04:25:07 +0300 From: Saeed Mahameed To: "David S. Miller" Cc: netdev@vger.kernel.org, Jason Gunthorpe , linux-rdma@vger.kernel.org, Saeed Mahameed , Feras Daoud Subject: [net-next 5/7] net/mlx5e: Initialize all netdev common structures in one place Date: Wed, 10 Oct 2018 18:24:42 -0700 Message-Id: <20181011012444.28194-6-saeedm@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181011012444.28194-1-saeedm@mellanox.com> References: <20181011012444.28194-1-saeedm@mellanox.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Move all mlx5e generic structures initializations to mlx5e_netdev_init. The common structure new initializer function will be used to initialize mlx5 context for netlink created netdevs such as IPoIB mlx5 accelerated child netdevs. Fixes: cd565b4b51e5 ("IB/IPoIB: Support acceleration options callbacks") Signed-off-by: Saeed Mahameed Signed-off-by: Feras Daoud --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 6 +- .../net/ethernet/mellanox/mlx5/core/en_main.c | 63 +++++++++---------- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 8 +-- .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 10 +-- 4 files changed, 36 insertions(+), 51 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 59d07a6fe7c5..f6dd0254d103 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -961,7 +961,11 @@ int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv, struct ethtool_flash *flash); /* mlx5e generic netdev management API */ -int mlx5e_netdev_init(struct net_device *netdev, struct mlx5e_priv *priv); +int mlx5e_netdev_init(struct net_device *netdev, + struct mlx5e_priv *priv, + struct mlx5_core_dev *mdev, + const struct mlx5e_profile *profile, + void *ppriv); void mlx5e_netdev_cleanup(struct net_device *netdev, struct mlx5e_priv *priv); 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_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 9cf5863b7949..d5a7bd493240 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4560,32 +4560,6 @@ void mlx5e_build_nic_params(struct mlx5_core_dev *mdev, mlx5e_build_rss_params(params); } -static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev, - struct net_device *netdev, - const struct mlx5e_profile *profile, - void *ppriv) -{ - struct mlx5e_priv *priv = netdev_priv(netdev); - - priv->mdev = mdev; - priv->netdev = netdev; - priv->profile = profile; - priv->ppriv = ppriv; - priv->msglevel = MLX5E_MSG_LEVEL; - priv->max_opened_tc = 1; - - mlx5e_build_nic_params(mdev, &priv->channels.params, - profile->max_nch(mdev), netdev->mtu); - - mutex_init(&priv->state_lock); - - INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work); - INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work); - INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work); - - mlx5e_timestamp_init(priv); -} - static void mlx5e_set_netdev_dev_addr(struct net_device *netdev) { struct mlx5e_priv *priv = netdev_priv(netdev); @@ -4756,11 +4730,15 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv = netdev_priv(netdev); int err; - err = mlx5e_netdev_init(netdev, priv); + err = mlx5e_netdev_init(netdev, priv, mdev, profile, ppriv); if (err) return err; - mlx5e_build_nic_netdev_priv(mdev, netdev, profile, ppriv); + mlx5e_build_nic_params(mdev, &priv->channels.params, + profile->max_nch(mdev), netdev->mtu); + + mlx5e_timestamp_init(priv); + err = mlx5e_ipsec_init(priv); if (err) mlx5_core_err(mdev, "IPSec initialization failed, %d\n", err); @@ -4950,16 +4928,37 @@ static const struct mlx5e_profile mlx5e_nic_profile = { /* mlx5e generic netdev management API (move to en_common.c) */ /* mlx5e_netdev_init/cleanup must be called from profile->init/cleanup callbacks */ -int mlx5e_netdev_init(struct net_device *netdev, struct mlx5e_priv *priv) +int mlx5e_netdev_init(struct net_device *netdev, + struct mlx5e_priv *priv, + struct mlx5_core_dev *mdev, + const struct mlx5e_profile *profile, + void *ppriv) { - netif_carrier_off(netdev); + /* priv init */ + priv->mdev = mdev; + priv->netdev = netdev; + priv->profile = profile; + priv->ppriv = ppriv; + priv->msglevel = MLX5E_MSG_LEVEL; + priv->max_opened_tc = 1; + mutex_init(&priv->state_lock); + INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work); + INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work); + INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work); INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work); priv->wq = create_singlethread_workqueue("mlx5e"); if (!priv->wq) return -ENOMEM; + /* netdev init */ + netif_carrier_off(netdev); + +#ifdef CONFIG_MLX5_EN_ARFS + netdev->rx_cpu_rmap = mdev->rmap; +#endif + return 0; } @@ -4984,10 +4983,6 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev, return NULL; } -#ifdef CONFIG_MLX5_EN_ARFS - netdev->rx_cpu_rmap = mdev->rmap; -#endif - err = profile->init(mdev, netdev, profile, ppriv); if (err) { mlx5_core_err(mdev, "failed to init mlx5e profile %d\n", err); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index bd8caac2e572..1a3efa87f557 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1086,16 +1086,10 @@ static int mlx5e_init_rep(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv = netdev_priv(netdev); int err; - priv->mdev = mdev; - priv->netdev = netdev; - priv->profile = profile; - priv->ppriv = ppriv; - - err = mlx5e_netdev_init(netdev, priv); + err = mlx5e_netdev_init(netdev, priv, mdev, profile, ppriv); if (err) return err; - mutex_init(&priv->state_lock); priv->channels.params.num_channels = profile->max_nch(mdev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 3f544baab9c9..ed28602c98f6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -80,15 +80,7 @@ int mlx5i_init(struct mlx5_core_dev *mdev, u16 max_mtu; int err; - /* priv init */ - priv->mdev = mdev; - priv->netdev = netdev; - priv->profile = profile; - priv->ppriv = ppriv; - priv->max_opened_tc = 1; - mutex_init(&priv->state_lock); - - err = mlx5e_netdev_init(netdev, priv); + err = mlx5e_netdev_init(netdev, priv, mdev, profile, ppriv); if (err) return err; From patchwork Thu Oct 11 01:24:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Saeed Mahameed X-Patchwork-Id: 982176 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42VvVr4bgfz9s8F for ; Thu, 11 Oct 2018 13:07:32 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727226AbeJKJc2 (ORCPT ); Thu, 11 Oct 2018 05:32:28 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45119 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726960AbeJKJb4 (ORCPT ); Thu, 11 Oct 2018 05:31:56 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from saeedm@mellanox.com) with ESMTPS (AES256-SHA encrypted); 11 Oct 2018 03:30:02 +0200 Received: from sx1.hsd1.ca.comcast.net ([172.16.5.11]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w9B1Oq7A030225; Thu, 11 Oct 2018 04:25:09 +0300 From: Saeed Mahameed To: "David S. Miller" Cc: netdev@vger.kernel.org, Jason Gunthorpe , linux-rdma@vger.kernel.org, Saeed Mahameed Subject: [net-next 6/7] net/mlx5e: Use non-delayed work for update stats Date: Wed, 10 Oct 2018 18:24:43 -0700 Message-Id: <20181011012444.28194-7-saeedm@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181011012444.28194-1-saeedm@mellanox.com> References: <20181011012444.28194-1-saeedm@mellanox.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Convert mlx5e update stats work to a normal work structure, since it is never used delayed. Add a helper function to queue update stats work on demand which checks for some conditions and reduce code duplication to have a better abstraction. Fixes: ed56c5193ad8 ("net/mlx5e: Update NIC HW stats on demand only") Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 ++- .../net/ethernet/mellanox/mlx5/core/en_main.c | 24 ++++++++++++------- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 3 +-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index f6dd0254d103..0fbdd7696ec4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -673,7 +673,7 @@ struct mlx5e_priv { struct work_struct update_carrier_work; struct work_struct set_rx_mode_work; struct work_struct tx_timeout_work; - struct delayed_work update_stats_work; + struct work_struct update_stats_work; struct mlx5_core_dev *mdev; struct net_device *netdev; @@ -927,6 +927,7 @@ void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv); int mlx5e_close(struct net_device *netdev); int mlx5e_open(struct net_device *netdev); +void mlx5e_queue_update_stats(struct mlx5e_priv *priv); int mlx5e_bits_invert(unsigned long a, int size); typedef int (*change_hw_mtu_cb)(struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index d5a7bd493240..f4b11bdae879 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -274,8 +274,7 @@ static void mlx5e_update_ndo_stats(struct mlx5e_priv *priv) static void mlx5e_update_stats_work(struct work_struct *work) { - struct delayed_work *dwork = to_delayed_work(work); - struct mlx5e_priv *priv = container_of(dwork, struct mlx5e_priv, + struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv, update_stats_work); mutex_lock(&priv->state_lock); @@ -283,6 +282,17 @@ static void mlx5e_update_stats_work(struct work_struct *work) mutex_unlock(&priv->state_lock); } +void mlx5e_queue_update_stats(struct mlx5e_priv *priv) +{ + if (!priv->profile->update_stats) + return; + + if (unlikely(test_bit(MLX5E_STATE_DESTROYING, &priv->state))) + return; + + queue_work(priv->wq, &priv->update_stats_work); +} + static void mlx5e_async_event(struct mlx5_core_dev *mdev, void *vpriv, enum mlx5_dev_event event, unsigned long param) { @@ -2957,9 +2967,7 @@ int mlx5e_open_locked(struct net_device *netdev) if (priv->profile->update_carrier) priv->profile->update_carrier(priv); - if (priv->profile->update_stats) - queue_delayed_work(priv->wq, &priv->update_stats_work, 0); - + mlx5e_queue_update_stats(priv); return 0; err_clear_state_opened_flag: @@ -3441,7 +3449,7 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) struct mlx5e_pport_stats *pstats = &priv->stats.pport; /* update HW stats in background for next time */ - queue_delayed_work(priv->wq, &priv->update_stats_work, 0); + mlx5e_queue_update_stats(priv); if (mlx5e_is_uplink_rep(priv)) { stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok); @@ -4946,7 +4954,7 @@ int mlx5e_netdev_init(struct net_device *netdev, INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work); INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work); INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work); - INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work); + INIT_WORK(&priv->update_stats_work, mlx5e_update_stats_work); priv->wq = create_singlethread_workqueue("mlx5e"); if (!priv->wq) @@ -5037,7 +5045,7 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv) profile->cleanup_rx(priv); profile->cleanup_tx(priv); - cancel_delayed_work_sync(&priv->update_stats_work); + cancel_work_sync(&priv->update_stats_work); } void mlx5e_destroy_netdev(struct mlx5e_priv *priv) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 1a3efa87f557..1846edb01fd6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -992,8 +992,7 @@ mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) struct mlx5e_priv *priv = netdev_priv(dev); /* update HW stats in background for next time */ - queue_delayed_work(priv->wq, &priv->update_stats_work, 0); - + mlx5e_queue_update_stats(priv); memcpy(stats, &priv->stats.vf_vport, sizeof(*stats)); } From patchwork Thu Oct 11 01:24:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Saeed Mahameed X-Patchwork-Id: 982167 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42VvVH1TqNz9s8F for ; Thu, 11 Oct 2018 13:07:03 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727059AbeJKJb7 (ORCPT ); Thu, 11 Oct 2018 05:31:59 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45127 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726967AbeJKJb6 (ORCPT ); Thu, 11 Oct 2018 05:31:58 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from saeedm@mellanox.com) with ESMTPS (AES256-SHA encrypted); 11 Oct 2018 03:30:05 +0200 Received: from sx1.hsd1.ca.comcast.net ([172.16.5.11]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w9B1Oq7B030225; Thu, 11 Oct 2018 04:25:12 +0300 From: Saeed Mahameed To: "David S. Miller" Cc: netdev@vger.kernel.org, Jason Gunthorpe , linux-rdma@vger.kernel.org, Feras Daoud , Saeed Mahameed Subject: [net-next 7/7] net/mlx5e: Do not ignore netdevice TX/RX queues number Date: Wed, 10 Oct 2018 18:24:44 -0700 Message-Id: <20181011012444.28194-8-saeedm@mellanox.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181011012444.28194-1-saeedm@mellanox.com> References: <20181011012444.28194-1-saeedm@mellanox.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Feras Daoud The current design of mlx5e driver ignores the netdevice TX/RX queues number for netdevices that RDMA IPoIB ULP creates. Instead, the queue number is initialized to the maximum number that mlx5 thinks best for performance. As a result, ULP drivers that choose to create a netdevice with queue number that is less than the maximum channels mlx5 creates, will get a memory corruption. This fix changes the mlx5e netdev logic to respect ULP netdevices TX/RX queue number and use it when creating resources instead of the maximum channel number. Fixes: cd565b4b51e5 ("IB/IPoIB: Support acceleration options callbacks") Signed-off-by: Feras Daoud Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 11 ++++++-- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 2 +- .../net/ethernet/mellanox/mlx5/core/en_main.c | 25 ++++++++++--------- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 9 ++++--- .../ethernet/mellanox/mlx5/core/en_stats.c | 8 +++--- .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 9 ++++--- .../mellanox/mlx5/core/ipoib/ipoib_vlan.c | 1 - 7 files changed, 37 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 0fbdd7696ec4..d7fbd5b6ac95 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -173,6 +173,7 @@ static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size) } } +/* Use this function to get max num channels (rxqs/txqs) only to create netdev */ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev) { return is_kdump_kernel() ? @@ -181,6 +182,13 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev) MLX5E_MAX_NUM_CHANNELS); } +/* Use this function to get max num channels after netdev was created */ +static inline int mlx5e_get_netdev_max_channels(struct net_device *netdev) +{ + return min_t(unsigned int, netdev->num_rx_queues, + netdev->num_tx_queues); +} + struct mlx5e_tx_wqe { struct mlx5_wqe_ctrl_seg ctrl; struct mlx5_wqe_eth_seg eth; @@ -710,7 +718,6 @@ struct mlx5e_profile { 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; mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe; @@ -970,7 +977,7 @@ int mlx5e_netdev_init(struct net_device *netdev, void mlx5e_netdev_cleanup(struct net_device *netdev, struct mlx5e_priv *priv); struct net_device* mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *profile, - void *ppriv); + int nch, void *ppriv); int mlx5e_attach_netdev(struct mlx5e_priv *priv); void mlx5e_detach_netdev(struct mlx5e_priv *priv); void mlx5e_destroy_netdev(struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index c86fd770c463..c61f6302cde2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -319,7 +319,7 @@ static int mlx5e_set_ringparam(struct net_device *dev, void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv, struct ethtool_channels *ch) { - ch->max_combined = priv->profile->max_nch(priv->mdev); + ch->max_combined = mlx5e_get_netdev_max_channels(priv->netdev); ch->combined_count = priv->channels.params.num_channels; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index f4b11bdae879..c9848e333450 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1799,7 +1799,7 @@ static int mlx5e_open_sqs(struct mlx5e_channel *c, struct mlx5e_channel_param *cparam) { struct mlx5e_priv *priv = c->priv; - int err, tc, max_nch = priv->profile->max_nch(priv->mdev); + int err, tc, max_nch = mlx5e_get_netdev_max_channels(priv->netdev); for (tc = 0; tc < params->num_tc; tc++) { int txq_ix = c->ix + tc * max_nch; @@ -2439,7 +2439,7 @@ int mlx5e_create_direct_rqts(struct mlx5e_priv *priv) int err; int ix; - for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) { + for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) { rqt = &priv->direct_tir[ix].rqt; err = mlx5e_create_rqt(priv, 1 /*size */, rqt); if (err) @@ -2460,7 +2460,7 @@ void mlx5e_destroy_direct_rqts(struct mlx5e_priv *priv) { int i; - for (i = 0; i < priv->profile->max_nch(priv->mdev); i++) + for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt); } @@ -2554,7 +2554,7 @@ static void mlx5e_redirect_rqts(struct mlx5e_priv *priv, mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, rrp); } - for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) { + for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) { struct mlx5e_redirect_rqt_param direct_rrp = { .is_rss = false, { @@ -2755,7 +2755,7 @@ static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv) goto free_in; } - for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) { + for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) { err = mlx5_core_modify_tir(mdev, priv->direct_tir[ix].tirn, in, inlen); if (err) @@ -2855,7 +2855,7 @@ static void mlx5e_netdev_set_tcs(struct net_device *netdev) static void mlx5e_build_tc2txq_maps(struct mlx5e_priv *priv) { - int max_nch = priv->profile->max_nch(priv->mdev); + int max_nch = mlx5e_get_netdev_max_channels(priv->netdev); int i, tc; for (i = 0; i < max_nch; i++) @@ -3247,7 +3247,7 @@ int mlx5e_create_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc) int mlx5e_create_direct_tirs(struct mlx5e_priv *priv) { - int nch = priv->profile->max_nch(priv->mdev); + int nch = mlx5e_get_netdev_max_channels(priv->netdev); struct mlx5e_tir *tir; void *tirc; int inlen; @@ -3300,7 +3300,7 @@ void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc) void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv) { - int nch = priv->profile->max_nch(priv->mdev); + int nch = mlx5e_get_netdev_max_channels(priv->netdev); int i; for (i = 0; i < nch; i++) @@ -4743,7 +4743,7 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev, return err; mlx5e_build_nic_params(mdev, &priv->channels.params, - profile->max_nch(mdev), netdev->mtu); + mlx5e_get_netdev_max_channels(netdev), netdev->mtu); mlx5e_timestamp_init(priv); @@ -4926,7 +4926,6 @@ static const struct mlx5e_profile mlx5e_nic_profile = { .enable = mlx5e_nic_enable, .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, @@ -4977,9 +4976,9 @@ void mlx5e_netdev_cleanup(struct net_device *netdev, struct mlx5e_priv *priv) struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *profile, + int nch, void *ppriv) { - int nch = profile->max_nch(mdev); struct net_device *netdev; int err; @@ -5101,6 +5100,7 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev) void *rpriv = NULL; void *priv; int err; + int nch; err = mlx5e_check_required_hca_cap(mdev); if (err) @@ -5116,7 +5116,8 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev) } #endif - netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, rpriv); + nch = mlx5e_get_max_num_channels(mdev); + netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, nch, rpriv); if (!netdev) { mlx5_core_err(mdev, "mlx5e_create_netdev failed\n"); goto err_free_rpriv; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 1846edb01fd6..64c2b9ea8b1e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1090,7 +1090,8 @@ static int mlx5e_init_rep(struct mlx5_core_dev *mdev, return err; - priv->channels.params.num_channels = profile->max_nch(mdev); + priv->channels.params.num_channels = + mlx5e_get_netdev_max_channels(netdev); mlx5e_build_rep_params(mdev, &priv->channels.params, netdev->mtu); mlx5e_build_rep_netdev(netdev); @@ -1233,7 +1234,6 @@ static const struct mlx5e_profile mlx5e_rep_profile = { .init_tx = mlx5e_init_rep_tx, .cleanup_tx = mlx5e_cleanup_nic_tx, .update_stats = mlx5e_rep_update_hw_counters, - .max_nch = mlx5e_get_max_num_channels, .update_carrier = NULL, .rx_handlers.handle_rx_cqe = mlx5e_handle_rx_cqe_rep, .rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq, @@ -1296,13 +1296,14 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) struct mlx5e_rep_priv *rpriv; struct net_device *netdev; struct mlx5e_priv *upriv; - int err; + int nch, err; rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL); if (!rpriv) return -ENOMEM; - netdev = mlx5e_create_netdev(dev, &mlx5e_rep_profile, rpriv); + nch = mlx5e_get_max_num_channels(dev); + netdev = mlx5e_create_netdev(dev, &mlx5e_rep_profile, nch, rpriv); if (!netdev) { pr_warn("Failed to create representor netdev for vport %d\n", rep->vport); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index b7d4896c7c7b..1c006869a642 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -133,7 +133,7 @@ void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv) memset(s, 0, sizeof(*s)); - for (i = 0; i < priv->profile->max_nch(priv->mdev); i++) { + for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) { struct mlx5e_channel_stats *channel_stats = &priv->channel_stats[i]; struct mlx5e_xdpsq_stats *xdpsq_red_stats = &channel_stats->xdpsq; @@ -1217,7 +1217,7 @@ static const struct counter_desc ch_stats_desc[] = { static int mlx5e_grp_channels_get_num_stats(struct mlx5e_priv *priv) { - int max_nch = priv->profile->max_nch(priv->mdev); + int max_nch = mlx5e_get_netdev_max_channels(priv->netdev); return (NUM_RQ_STATS * max_nch) + (NUM_CH_STATS * max_nch) + @@ -1229,7 +1229,7 @@ static int mlx5e_grp_channels_get_num_stats(struct mlx5e_priv *priv) static int mlx5e_grp_channels_fill_strings(struct mlx5e_priv *priv, u8 *data, int idx) { - int max_nch = priv->profile->max_nch(priv->mdev); + int max_nch = mlx5e_get_netdev_max_channels(priv->netdev); int i, j, tc; for (i = 0; i < max_nch; i++) @@ -1264,7 +1264,7 @@ static int mlx5e_grp_channels_fill_strings(struct mlx5e_priv *priv, u8 *data, static int mlx5e_grp_channels_fill_stats(struct mlx5e_priv *priv, u64 *data, int idx) { - int max_nch = priv->profile->max_nch(priv->mdev); + int max_nch = mlx5e_get_netdev_max_channels(priv->netdev); int i, j, tc; for (i = 0; i < max_nch; i++) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index ed28602c98f6..b59953daf8b4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -88,7 +88,8 @@ int mlx5i_init(struct mlx5_core_dev *mdev, netdev->mtu = max_mtu; mlx5e_build_nic_params(mdev, &priv->channels.params, - profile->max_nch(mdev), netdev->mtu); + mlx5e_get_netdev_max_channels(netdev), + netdev->mtu); mlx5i_build_nic_params(mdev, &priv->channels.params); mlx5e_timestamp_init(priv); @@ -117,10 +118,11 @@ void mlx5i_cleanup(struct mlx5e_priv *priv) static void mlx5i_grp_sw_update_stats(struct mlx5e_priv *priv) { + int max_nch = mlx5e_get_netdev_max_channels(priv->netdev); struct mlx5e_sw_stats s = { 0 }; int i, j; - for (i = 0; i < priv->profile->max_nch(priv->mdev); i++) { + for (i = 0; i < max_nch; i++) { struct mlx5e_channel_stats *channel_stats; struct mlx5e_rq_stats *rq_stats; @@ -417,7 +419,6 @@ static const struct mlx5e_profile mlx5i_nic_profile = { .enable = NULL, /* mlx5i_enable */ .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 */ @@ -729,7 +730,7 @@ int mlx5_rdma_rn_get_params(struct mlx5_core_dev *mdev, if (rc) return rc; - nch = mlx5_get_profile(mdev)->max_nch(mdev); + nch = mlx5e_get_max_num_channels(mdev); *params = (struct rdma_netdev_alloc_params){ .sizeof_priv = sizeof(struct mlx5i_priv) + diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c index 3dbfa532fda1..b491b8f5fd6b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c @@ -351,7 +351,6 @@ static const struct mlx5e_profile mlx5i_pkey_nic_profile = { .enable = NULL, .disable = NULL, .update_stats = NULL, - .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,