Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1986647c authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mlx5e-updates-2018-10-10' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux



Saeed Mahameed says:

====================
mlx5e-updates-2018-10-10

IPoIB netlink support and mlx5e pre-allocated netdevice initialization

IP link was broken due to the changes in IPoIB for the rdma_netdev
support after commit cd565b4b
("IB/IPoIB: Support acceleration options callbacks").

This patchset fixes IPoIB pkey creation and removal using rtnetlink by
adding support in both IPoIB ULP layer and mlx5 layer:

From Jason and Denis:
1) Introduces changes in the RDMA netdev code in order to
   allow allocation of the netdev to be done by the rtnl netdev code.
2) Reworks IPoIB initialization to use the two step rdma_netdev
   creation.

From Feras and Saeed, mlx5e netdev layer refactoring to allow accepting
pre-allocated netdevs:
3) Adds support to initialize/cleanup netdevs that are not created
   by mlx5 driver.
4) Change mlx5e netdevice layer to accept the pre-allocated netdevice
   queue number.
5) Initialize mlx5e generic structures in one place to be used for all
   netdevs types NIC/representors/IPoIB (both mlx5 allocated and
   pre-allocted).
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3325cf9e 779d986d
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -2621,3 +2621,49 @@ 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, &params);
	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);

	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, &params);
	if (rc)
		return rc;

	return params.initialize_rdma_netdev(device, port_num,
					     netdev, params.param);
}
EXPORT_SYMBOL(rdma_init_netdev);
+8 −15
Original line number Diff line number Diff line
@@ -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,
static int mlx5_ib_rn_get_params(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;

	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;
+6 −2
Original line number Diff line number Diff line
@@ -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,
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)
{
+72 −60
Original line number Diff line number Diff line
@@ -2115,82 +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,
static struct net_device *ipoib_alloc_netdev(struct ib_device *hca, u8 port,
					     const char *name)
{
	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;
	}
	dev = rdma_alloc_netdev(hca, port, RDMA_NETDEV_IPOIB, name,
				NET_NAME_UNKNOWN, ipoib_setup_common);
	if (!IS_ERR(dev) || PTR_ERR(dev) != -EOPNOTSUPP)
		return dev;

	if (!hca->alloc_rdma_netdev || PTR_ERR(dev) == -EOPNOTSUPP)
		dev = ipoib_create_netdev_default(hca, name, NET_NAME_UNKNOWN,
	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
@@ -2201,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)
@@ -2387,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);
@@ -2417,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,
						     &params);

		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
+21 −2
Original line number Diff line number Diff line
@@ -122,13 +122,27 @@ 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);
		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);
Loading