251 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)2/*3 * Copyright(c) 2020 Intel Corporation.4 *5 */6 7/*8 * This file contains HFI1 support for ipoib functionality9 */10 11#include "ipoib.h"12#include "hfi.h"13 14static u32 qpn_from_mac(const u8 *mac_arr)15{16 return (u32)mac_arr[1] << 16 | mac_arr[2] << 8 | mac_arr[3];17}18 19static int hfi1_ipoib_dev_init(struct net_device *dev)20{21 struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);22 int ret;23 24 ret = priv->netdev_ops->ndo_init(dev);25 if (ret)26 return ret;27 28 ret = hfi1_netdev_add_data(priv->dd,29 qpn_from_mac(priv->netdev->dev_addr),30 dev);31 if (ret < 0) {32 priv->netdev_ops->ndo_uninit(dev);33 return ret;34 }35 36 return 0;37}38 39static void hfi1_ipoib_dev_uninit(struct net_device *dev)40{41 struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);42 43 hfi1_netdev_remove_data(priv->dd, qpn_from_mac(priv->netdev->dev_addr));44 45 priv->netdev_ops->ndo_uninit(dev);46}47 48static int hfi1_ipoib_dev_open(struct net_device *dev)49{50 struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);51 int ret;52 53 ret = priv->netdev_ops->ndo_open(dev);54 if (!ret) {55 struct hfi1_ibport *ibp = to_iport(priv->device,56 priv->port_num);57 struct rvt_qp *qp;58 u32 qpn = qpn_from_mac(priv->netdev->dev_addr);59 60 rcu_read_lock();61 qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);62 if (!qp) {63 rcu_read_unlock();64 priv->netdev_ops->ndo_stop(dev);65 return -EINVAL;66 }67 rvt_get_qp(qp);68 priv->qp = qp;69 rcu_read_unlock();70 71 hfi1_netdev_enable_queues(priv->dd);72 hfi1_ipoib_napi_tx_enable(dev);73 }74 75 return ret;76}77 78static int hfi1_ipoib_dev_stop(struct net_device *dev)79{80 struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);81 82 if (!priv->qp)83 return 0;84 85 hfi1_ipoib_napi_tx_disable(dev);86 hfi1_netdev_disable_queues(priv->dd);87 88 rvt_put_qp(priv->qp);89 priv->qp = NULL;90 91 return priv->netdev_ops->ndo_stop(dev);92}93 94static const struct net_device_ops hfi1_ipoib_netdev_ops = {95 .ndo_init = hfi1_ipoib_dev_init,96 .ndo_uninit = hfi1_ipoib_dev_uninit,97 .ndo_open = hfi1_ipoib_dev_open,98 .ndo_stop = hfi1_ipoib_dev_stop,99};100 101static int hfi1_ipoib_mcast_attach(struct net_device *dev,102 struct ib_device *device,103 union ib_gid *mgid,104 u16 mlid,105 int set_qkey,106 u32 qkey)107{108 struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);109 u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);110 struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);111 struct rvt_qp *qp;112 int ret = -EINVAL;113 114 rcu_read_lock();115 116 qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);117 if (qp) {118 rvt_get_qp(qp);119 rcu_read_unlock();120 if (set_qkey)121 priv->qkey = qkey;122 123 /* attach QP to multicast group */124 ret = ib_attach_mcast(&qp->ibqp, mgid, mlid);125 rvt_put_qp(qp);126 } else {127 rcu_read_unlock();128 }129 130 return ret;131}132 133static int hfi1_ipoib_mcast_detach(struct net_device *dev,134 struct ib_device *device,135 union ib_gid *mgid,136 u16 mlid)137{138 struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);139 u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);140 struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);141 struct rvt_qp *qp;142 int ret = -EINVAL;143 144 rcu_read_lock();145 146 qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);147 if (qp) {148 rvt_get_qp(qp);149 rcu_read_unlock();150 ret = ib_detach_mcast(&qp->ibqp, mgid, mlid);151 rvt_put_qp(qp);152 } else {153 rcu_read_unlock();154 }155 return ret;156}157 158static void hfi1_ipoib_netdev_dtor(struct net_device *dev)159{160 struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);161 162 hfi1_ipoib_txreq_deinit(priv);163 hfi1_ipoib_rxq_deinit(priv->netdev);164}165 166static void hfi1_ipoib_set_id(struct net_device *dev, int id)167{168 struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);169 170 priv->pkey_index = (u16)id;171 ib_query_pkey(priv->device,172 priv->port_num,173 priv->pkey_index,174 &priv->pkey);175}176 177static int hfi1_ipoib_setup_rn(struct ib_device *device,178 u32 port_num,179 struct net_device *netdev,180 void *param)181{182 struct hfi1_devdata *dd = dd_from_ibdev(device);183 struct rdma_netdev *rn = netdev_priv(netdev);184 struct hfi1_ipoib_dev_priv *priv;185 int rc;186 187 rn->send = hfi1_ipoib_send;188 rn->tx_timeout = hfi1_ipoib_tx_timeout;189 rn->attach_mcast = hfi1_ipoib_mcast_attach;190 rn->detach_mcast = hfi1_ipoib_mcast_detach;191 rn->set_id = hfi1_ipoib_set_id;192 rn->hca = device;193 rn->port_num = port_num;194 rn->mtu = netdev->mtu;195 196 priv = hfi1_ipoib_priv(netdev);197 priv->dd = dd;198 priv->netdev = netdev;199 priv->device = device;200 priv->port_num = port_num;201 priv->netdev_ops = netdev->netdev_ops;202 203 ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey);204 205 rc = hfi1_ipoib_txreq_init(priv);206 if (rc) {207 dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc);208 return rc;209 }210 211 rc = hfi1_ipoib_rxq_init(netdev);212 if (rc) {213 dd_dev_err(dd, "IPoIB netdev RX init - failed(%d)\n", rc);214 hfi1_ipoib_txreq_deinit(priv);215 return rc;216 }217 218 netdev->netdev_ops = &hfi1_ipoib_netdev_ops;219 220 netdev->priv_destructor = hfi1_ipoib_netdev_dtor;221 netdev->needs_free_netdev = true;222 netdev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;223 224 return 0;225}226 227int hfi1_ipoib_rn_get_params(struct ib_device *device,228 u32 port_num,229 enum rdma_netdev_t type,230 struct rdma_netdev_alloc_params *params)231{232 struct hfi1_devdata *dd = dd_from_ibdev(device);233 234 if (type != RDMA_NETDEV_IPOIB)235 return -EOPNOTSUPP;236 237 if (!HFI1_CAP_IS_KSET(AIP) || !dd->num_netdev_contexts)238 return -EOPNOTSUPP;239 240 if (!port_num || port_num > dd->num_pports)241 return -EINVAL;242 243 params->sizeof_priv = sizeof(struct hfi1_ipoib_rdma_netdev);244 params->txqs = dd->num_sdma;245 params->rxqs = dd->num_netdev_contexts;246 params->param = NULL;247 params->initialize_rdma_netdev = hfi1_ipoib_setup_rn;248 249 return 0;250}251