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:
parent
44b0b7455f
commit
d41861942f
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue