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

Commit d4186194 authored by Yuval Shaia's avatar Yuval Shaia Committed by Doug Ledford
Browse files

IB/core: Add generic function to extract IB speed from netdev



Logic of retrieving netdev speed from net_device and translating it to
IB speed is implemented in rxe, in usnic and in bnxt drivers.

Define new function which merges all.

Signed-off-by: default avatarYuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: default avatarChristian Benvenuti <benve@cisco.com>
Reviewed-by: default avatarSelvin Xavier <selvin.xavier@broadcom.com>
Reviewed-by: default avatarMoni Shoua <monis@mellanox.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 44b0b745
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@

static struct workqueue_struct *gid_cache_wq;

static struct workqueue_struct *gid_cache_wq;

enum gid_op_type {
	GID_DEL = 0,
	GID_ADD
+55 −0
Original line number Diff line number Diff line
@@ -1302,6 +1302,61 @@ int ib_modify_qp_with_udata(struct ib_qp *qp, struct ib_qp_attr *attr,
}
EXPORT_SYMBOL(ib_modify_qp_with_udata);

int ib_get_eth_speed(struct ib_device *dev, u8 port_num, u8 *speed, u8 *width)
{
	int rc;
	u32 netdev_speed;
	struct net_device *netdev;
	struct ethtool_link_ksettings lksettings;

	if (rdma_port_get_link_layer(dev, port_num) != IB_LINK_LAYER_ETHERNET)
		return -EINVAL;

	if (!dev->get_netdev)
		return -EOPNOTSUPP;

	netdev = dev->get_netdev(dev, port_num);
	if (!netdev)
		return -ENODEV;

	rtnl_lock();
	rc = __ethtool_get_link_ksettings(netdev, &lksettings);
	rtnl_unlock();

	dev_put(netdev);

	if (!rc) {
		netdev_speed = lksettings.base.speed;
	} else {
		netdev_speed = SPEED_1000;
		pr_warn("%s speed is unknown, defaulting to %d\n", netdev->name,
			netdev_speed);
	}

	if (netdev_speed <= SPEED_1000) {
		*width = IB_WIDTH_1X;
		*speed = IB_SPEED_SDR;
	} else if (netdev_speed <= SPEED_10000) {
		*width = IB_WIDTH_1X;
		*speed = IB_SPEED_FDR10;
	} else if (netdev_speed <= SPEED_20000) {
		*width = IB_WIDTH_4X;
		*speed = IB_SPEED_DDR;
	} else if (netdev_speed <= SPEED_25000) {
		*width = IB_WIDTH_1X;
		*speed = IB_SPEED_EDR;
	} else if (netdev_speed <= SPEED_40000) {
		*width = IB_WIDTH_4X;
		*speed = IB_SPEED_FDR10;
	} else {
		*width = IB_WIDTH_4X;
		*speed = IB_SPEED_EDR;
	}

	return 0;
}
EXPORT_SYMBOL(ib_get_eth_speed);

int ib_modify_qp(struct ib_qp *qp,
		 struct ib_qp_attr *qp_attr,
		 int qp_attr_mask)
+3 −46
Original line number Diff line number Diff line
@@ -223,50 +223,6 @@ int bnxt_re_modify_device(struct ib_device *ibdev,
	return 0;
}

static void __to_ib_speed_width(struct net_device *netdev, u8 *speed, u8 *width)
{
	struct ethtool_link_ksettings lksettings;
	u32 espeed;

	if (netdev->ethtool_ops && netdev->ethtool_ops->get_link_ksettings) {
		memset(&lksettings, 0, sizeof(lksettings));
		rtnl_lock();
		netdev->ethtool_ops->get_link_ksettings(netdev, &lksettings);
		rtnl_unlock();
		espeed = lksettings.base.speed;
	} else {
		espeed = SPEED_UNKNOWN;
	}
	switch (espeed) {
	case SPEED_1000:
		*speed = IB_SPEED_SDR;
		*width = IB_WIDTH_1X;
		break;
	case SPEED_10000:
		*speed = IB_SPEED_QDR;
		*width = IB_WIDTH_1X;
		break;
	case SPEED_20000:
		*speed = IB_SPEED_DDR;
		*width = IB_WIDTH_4X;
		break;
	case SPEED_25000:
		*speed = IB_SPEED_EDR;
		*width = IB_WIDTH_1X;
		break;
	case SPEED_40000:
		*speed = IB_SPEED_QDR;
		*width = IB_WIDTH_4X;
		break;
	case SPEED_50000:
		break;
	default:
		*speed = IB_SPEED_SDR;
		*width = IB_WIDTH_1X;
		break;
	}
}

/* Port */
int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num,
		       struct ib_port_attr *port_attr)
@@ -308,8 +264,9 @@ int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num,
	 * IB stack to avoid race in the NETDEV_UNREG path
	 */
	if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags))
		__to_ib_speed_width(rdev->netdev, &port_attr->active_speed,
				    &port_attr->active_width);
		if (!ib_get_eth_speed(ibdev, port_num, &port_attr->active_speed,
				      &port_attr->active_width))
			return -EINVAL;
	return 0;
}

+6 −25
Original line number Diff line number Diff line
@@ -226,27 +226,6 @@ static void qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
	spin_unlock(&vf->lock);
}

static void eth_speed_to_ib_speed(int speed, u8 *active_speed,
					u8 *active_width)
{
	if (speed <= 10000) {
		*active_width = IB_WIDTH_1X;
		*active_speed = IB_SPEED_FDR10;
	} else if (speed <= 20000) {
		*active_width = IB_WIDTH_4X;
		*active_speed = IB_SPEED_DDR;
	} else if (speed <= 30000) {
		*active_width = IB_WIDTH_4X;
		*active_speed = IB_SPEED_QDR;
	} else if (speed <= 40000) {
		*active_width = IB_WIDTH_4X;
		*active_speed = IB_SPEED_FDR10;
	} else {
		*active_width = IB_WIDTH_4X;
		*active_speed = IB_SPEED_EDR;
	}
}

static int create_qp_validate_user_data(struct usnic_ib_create_qp_cmd cmd)
{
	if (cmd.spec.trans_type <= USNIC_TRANSPORT_UNKNOWN ||
@@ -326,12 +305,16 @@ int usnic_ib_query_port(struct ib_device *ibdev, u8 port,
				struct ib_port_attr *props)
{
	struct usnic_ib_dev *us_ibdev = to_usdev(ibdev);
	struct ethtool_link_ksettings cmd;

	usnic_dbg("\n");

	mutex_lock(&us_ibdev->usdev_lock);
	__ethtool_get_link_ksettings(us_ibdev->netdev, &cmd);
	if (!ib_get_eth_speed(ibdev, port, &props->active_speed,
			      &props->active_width)) {
		mutex_unlock(&us_ibdev->usdev_lock);
		return -EINVAL;
	}

	/* props being zeroed by the caller, avoid zeroing it here */

	props->lid = 0;
@@ -355,8 +338,6 @@ int usnic_ib_query_port(struct ib_device *ibdev, u8 port,
	props->pkey_tbl_len = 1;
	props->bad_pkey_cntr = 0;
	props->qkey_viol_cntr = 0;
	eth_speed_to_ib_speed(cmd.base.speed, &props->active_speed,
			      &props->active_width);
	props->max_mtu = IB_MTU_4096;
	props->active_mtu = iboe_get_mtu(us_ibdev->ufdev->mtu);
	/* Userspace will adjust for hdrs */
+6 −47
Original line number Diff line number Diff line
@@ -51,40 +51,16 @@ static int rxe_query_device(struct ib_device *dev,
	return 0;
}

static void rxe_eth_speed_to_ib_speed(int speed, u8 *active_speed,
				      u8 *active_width)
{
	if (speed <= 1000) {
		*active_width = IB_WIDTH_1X;
		*active_speed = IB_SPEED_SDR;
	} else if (speed <= 10000) {
		*active_width = IB_WIDTH_1X;
		*active_speed = IB_SPEED_FDR10;
	} else if (speed <= 20000) {
		*active_width = IB_WIDTH_4X;
		*active_speed = IB_SPEED_DDR;
	} else if (speed <= 30000) {
		*active_width = IB_WIDTH_4X;
		*active_speed = IB_SPEED_QDR;
	} else if (speed <= 40000) {
		*active_width = IB_WIDTH_4X;
		*active_speed = IB_SPEED_FDR10;
	} else {
		*active_width = IB_WIDTH_4X;
		*active_speed = IB_SPEED_EDR;
	}
}

static int rxe_query_port(struct ib_device *dev,
			  u8 port_num, struct ib_port_attr *attr)
{
	struct rxe_dev *rxe = to_rdev(dev);
	struct rxe_port *port;
	u32 speed;
	int rc = -EINVAL;

	if (unlikely(port_num != 1)) {
		pr_warn("invalid port_number %d\n", port_num);
		goto err1;
		goto out;
	}

	port = &rxe->port;
@@ -93,29 +69,12 @@ static int rxe_query_port(struct ib_device *dev,
	*attr = port->attr;

	mutex_lock(&rxe->usdev_lock);
	if (rxe->ndev->ethtool_ops->get_link_ksettings) {
		struct ethtool_link_ksettings ks;

		rxe->ndev->ethtool_ops->get_link_ksettings(rxe->ndev, &ks);
		speed = ks.base.speed;
	} else if (rxe->ndev->ethtool_ops->get_settings) {
		struct ethtool_cmd cmd;

		rxe->ndev->ethtool_ops->get_settings(rxe->ndev, &cmd);
		speed = cmd.speed;
	} else {
		pr_warn("%s speed is unknown, defaulting to 1000\n",
			rxe->ndev->name);
		speed = 1000;
	}
	rxe_eth_speed_to_ib_speed(speed, &attr->active_speed,
	rc = ib_get_eth_speed(dev, port_num, &attr->active_speed,
			      &attr->active_width);
	mutex_unlock(&rxe->usdev_lock);

	return 0;

err1:
	return -EINVAL;
out:
	return rc;
}

static int rxe_query_gid(struct ib_device *device,
Loading