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: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Christian Benvenuti <benve@cisco.com>
Reviewed-by: Selvin Xavier <selvin.xavier@broadcom.com>
Reviewed-by: Moni Shoua <monis@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
Yuval Shaia 2017-06-14 23:13:34 +03:00 committed by Doug Ledford
parent 44b0b7455f
commit d41861942f
6 changed files with 73 additions and 118 deletions

View File

@ -44,6 +44,8 @@
static struct workqueue_struct *gid_cache_wq; static struct workqueue_struct *gid_cache_wq;
static struct workqueue_struct *gid_cache_wq;
enum gid_op_type { enum gid_op_type {
GID_DEL = 0, GID_DEL = 0,
GID_ADD GID_ADD

View File

@ -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); 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, int ib_modify_qp(struct ib_qp *qp,
struct ib_qp_attr *qp_attr, struct ib_qp_attr *qp_attr,
int qp_attr_mask) int qp_attr_mask)

View File

@ -223,50 +223,6 @@ int bnxt_re_modify_device(struct ib_device *ibdev,
return 0; 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 */ /* Port */
int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num, int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num,
struct ib_port_attr *port_attr) 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 * IB stack to avoid race in the NETDEV_UNREG path
*/ */
if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags))
__to_ib_speed_width(rdev->netdev, &port_attr->active_speed, if (!ib_get_eth_speed(ibdev, port_num, &port_attr->active_speed,
&port_attr->active_width); &port_attr->active_width))
return -EINVAL;
return 0; return 0;
} }

View File

@ -226,27 +226,6 @@ static void qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
spin_unlock(&vf->lock); 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) static int create_qp_validate_user_data(struct usnic_ib_create_qp_cmd cmd)
{ {
if (cmd.spec.trans_type <= USNIC_TRANSPORT_UNKNOWN || 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 ib_port_attr *props)
{ {
struct usnic_ib_dev *us_ibdev = to_usdev(ibdev); struct usnic_ib_dev *us_ibdev = to_usdev(ibdev);
struct ethtool_link_ksettings cmd;
usnic_dbg("\n"); usnic_dbg("\n");
mutex_lock(&us_ibdev->usdev_lock); 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 being zeroed by the caller, avoid zeroing it here */
props->lid = 0; props->lid = 0;
@ -355,8 +338,6 @@ int usnic_ib_query_port(struct ib_device *ibdev, u8 port,
props->pkey_tbl_len = 1; props->pkey_tbl_len = 1;
props->bad_pkey_cntr = 0; props->bad_pkey_cntr = 0;
props->qkey_viol_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->max_mtu = IB_MTU_4096;
props->active_mtu = iboe_get_mtu(us_ibdev->ufdev->mtu); props->active_mtu = iboe_get_mtu(us_ibdev->ufdev->mtu);
/* Userspace will adjust for hdrs */ /* Userspace will adjust for hdrs */

View File

@ -51,40 +51,16 @@ static int rxe_query_device(struct ib_device *dev,
return 0; 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, static int rxe_query_port(struct ib_device *dev,
u8 port_num, struct ib_port_attr *attr) u8 port_num, struct ib_port_attr *attr)
{ {
struct rxe_dev *rxe = to_rdev(dev); struct rxe_dev *rxe = to_rdev(dev);
struct rxe_port *port; struct rxe_port *port;
u32 speed; int rc = -EINVAL;
if (unlikely(port_num != 1)) { if (unlikely(port_num != 1)) {
pr_warn("invalid port_number %d\n", port_num); pr_warn("invalid port_number %d\n", port_num);
goto err1; goto out;
} }
port = &rxe->port; port = &rxe->port;
@ -93,29 +69,12 @@ static int rxe_query_port(struct ib_device *dev,
*attr = port->attr; *attr = port->attr;
mutex_lock(&rxe->usdev_lock); mutex_lock(&rxe->usdev_lock);
if (rxe->ndev->ethtool_ops->get_link_ksettings) { rc = ib_get_eth_speed(dev, port_num, &attr->active_speed,
struct ethtool_link_ksettings ks; &attr->active_width);
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,
&attr->active_width);
mutex_unlock(&rxe->usdev_lock); mutex_unlock(&rxe->usdev_lock);
return 0; out:
return rc;
err1:
return -EINVAL;
} }
static int rxe_query_gid(struct ib_device *device, static int rxe_query_gid(struct ib_device *device,

View File

@ -3555,6 +3555,7 @@ void ib_drain_qp(struct ib_qp *qp);
int ib_resolve_eth_dmac(struct ib_device *device, int ib_resolve_eth_dmac(struct ib_device *device,
struct rdma_ah_attr *ah_attr); struct rdma_ah_attr *ah_attr);
int ib_get_eth_speed(struct ib_device *dev, u8 port_num, u8 *speed, u8 *width);
static inline u8 *rdma_ah_retrieve_dmac(struct rdma_ah_attr *attr) static inline u8 *rdma_ah_retrieve_dmac(struct rdma_ah_attr *attr)
{ {