linux/drivers/infiniband/hw/hfi1/ipoib_main.c
<<
>>
Prefs
   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 functionality
   9 */
  10
  11#include "ipoib.h"
  12#include "hfi.h"
  13
  14static u32 qpn_from_mac(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        priv->netstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
  25
  26        ret = priv->netdev_ops->ndo_init(dev);
  27        if (ret)
  28                return ret;
  29
  30        ret = hfi1_netdev_add_data(priv->dd,
  31                                   qpn_from_mac(priv->netdev->dev_addr),
  32                                   dev);
  33        if (ret < 0) {
  34                priv->netdev_ops->ndo_uninit(dev);
  35                return ret;
  36        }
  37
  38        return 0;
  39}
  40
  41static void hfi1_ipoib_dev_uninit(struct net_device *dev)
  42{
  43        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
  44
  45        hfi1_netdev_remove_data(priv->dd, qpn_from_mac(priv->netdev->dev_addr));
  46
  47        priv->netdev_ops->ndo_uninit(dev);
  48}
  49
  50static int hfi1_ipoib_dev_open(struct net_device *dev)
  51{
  52        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
  53        int ret;
  54
  55        ret = priv->netdev_ops->ndo_open(dev);
  56        if (!ret) {
  57                struct hfi1_ibport *ibp = to_iport(priv->device,
  58                                                   priv->port_num);
  59                struct rvt_qp *qp;
  60                u32 qpn = qpn_from_mac(priv->netdev->dev_addr);
  61
  62                rcu_read_lock();
  63                qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
  64                if (!qp) {
  65                        rcu_read_unlock();
  66                        priv->netdev_ops->ndo_stop(dev);
  67                        return -EINVAL;
  68                }
  69                rvt_get_qp(qp);
  70                priv->qp = qp;
  71                rcu_read_unlock();
  72
  73                hfi1_netdev_enable_queues(priv->dd);
  74                hfi1_ipoib_napi_tx_enable(dev);
  75        }
  76
  77        return ret;
  78}
  79
  80static int hfi1_ipoib_dev_stop(struct net_device *dev)
  81{
  82        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
  83
  84        if (!priv->qp)
  85                return 0;
  86
  87        hfi1_ipoib_napi_tx_disable(dev);
  88        hfi1_netdev_disable_queues(priv->dd);
  89
  90        rvt_put_qp(priv->qp);
  91        priv->qp = NULL;
  92
  93        return priv->netdev_ops->ndo_stop(dev);
  94}
  95
  96static void hfi1_ipoib_dev_get_stats64(struct net_device *dev,
  97                                       struct rtnl_link_stats64 *storage)
  98{
  99        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
 100
 101        netdev_stats_to_stats64(storage, &dev->stats);
 102        dev_fetch_sw_netstats(storage, priv->netstats);
 103}
 104
 105static const struct net_device_ops hfi1_ipoib_netdev_ops = {
 106        .ndo_init         = hfi1_ipoib_dev_init,
 107        .ndo_uninit       = hfi1_ipoib_dev_uninit,
 108        .ndo_open         = hfi1_ipoib_dev_open,
 109        .ndo_stop         = hfi1_ipoib_dev_stop,
 110        .ndo_get_stats64  = hfi1_ipoib_dev_get_stats64,
 111};
 112
 113static int hfi1_ipoib_send(struct net_device *dev,
 114                           struct sk_buff *skb,
 115                           struct ib_ah *address,
 116                           u32 dqpn)
 117{
 118        return hfi1_ipoib_send_dma(dev, skb, address, dqpn);
 119}
 120
 121static int hfi1_ipoib_mcast_attach(struct net_device *dev,
 122                                   struct ib_device *device,
 123                                   union ib_gid *mgid,
 124                                   u16 mlid,
 125                                   int set_qkey,
 126                                   u32 qkey)
 127{
 128        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
 129        u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);
 130        struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);
 131        struct rvt_qp *qp;
 132        int ret = -EINVAL;
 133
 134        rcu_read_lock();
 135
 136        qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
 137        if (qp) {
 138                rvt_get_qp(qp);
 139                rcu_read_unlock();
 140                if (set_qkey)
 141                        priv->qkey = qkey;
 142
 143                /* attach QP to multicast group */
 144                ret = ib_attach_mcast(&qp->ibqp, mgid, mlid);
 145                rvt_put_qp(qp);
 146        } else {
 147                rcu_read_unlock();
 148        }
 149
 150        return ret;
 151}
 152
 153static int hfi1_ipoib_mcast_detach(struct net_device *dev,
 154                                   struct ib_device *device,
 155                                   union ib_gid *mgid,
 156                                   u16 mlid)
 157{
 158        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
 159        u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);
 160        struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);
 161        struct rvt_qp *qp;
 162        int ret = -EINVAL;
 163
 164        rcu_read_lock();
 165
 166        qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
 167        if (qp) {
 168                rvt_get_qp(qp);
 169                rcu_read_unlock();
 170                ret = ib_detach_mcast(&qp->ibqp, mgid, mlid);
 171                rvt_put_qp(qp);
 172        } else {
 173                rcu_read_unlock();
 174        }
 175        return ret;
 176}
 177
 178static void hfi1_ipoib_netdev_dtor(struct net_device *dev)
 179{
 180        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
 181
 182        hfi1_ipoib_txreq_deinit(priv);
 183        hfi1_ipoib_rxq_deinit(priv->netdev);
 184
 185        free_percpu(priv->netstats);
 186}
 187
 188static void hfi1_ipoib_free_rdma_netdev(struct net_device *dev)
 189{
 190        hfi1_ipoib_netdev_dtor(dev);
 191        free_netdev(dev);
 192}
 193
 194static void hfi1_ipoib_set_id(struct net_device *dev, int id)
 195{
 196        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
 197
 198        priv->pkey_index = (u16)id;
 199        ib_query_pkey(priv->device,
 200                      priv->port_num,
 201                      priv->pkey_index,
 202                      &priv->pkey);
 203}
 204
 205static int hfi1_ipoib_setup_rn(struct ib_device *device,
 206                               u8 port_num,
 207                               struct net_device *netdev,
 208                               void *param)
 209{
 210        struct hfi1_devdata *dd = dd_from_ibdev(device);
 211        struct rdma_netdev *rn = netdev_priv(netdev);
 212        struct hfi1_ipoib_dev_priv *priv;
 213        int rc;
 214
 215        rn->send = hfi1_ipoib_send;
 216        rn->attach_mcast = hfi1_ipoib_mcast_attach;
 217        rn->detach_mcast = hfi1_ipoib_mcast_detach;
 218        rn->set_id = hfi1_ipoib_set_id;
 219        rn->hca = device;
 220        rn->port_num = port_num;
 221        rn->mtu = netdev->mtu;
 222
 223        priv = hfi1_ipoib_priv(netdev);
 224        priv->dd = dd;
 225        priv->netdev = netdev;
 226        priv->device = device;
 227        priv->port_num = port_num;
 228        priv->netdev_ops = netdev->netdev_ops;
 229
 230        netdev->netdev_ops = &hfi1_ipoib_netdev_ops;
 231
 232        ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey);
 233
 234        rc = hfi1_ipoib_txreq_init(priv);
 235        if (rc) {
 236                dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc);
 237                hfi1_ipoib_free_rdma_netdev(netdev);
 238                return rc;
 239        }
 240
 241        rc = hfi1_ipoib_rxq_init(netdev);
 242        if (rc) {
 243                dd_dev_err(dd, "IPoIB netdev RX init - failed(%d)\n", rc);
 244                hfi1_ipoib_free_rdma_netdev(netdev);
 245                return rc;
 246        }
 247
 248        netdev->priv_destructor = hfi1_ipoib_netdev_dtor;
 249        netdev->needs_free_netdev = true;
 250
 251        return 0;
 252}
 253
 254int hfi1_ipoib_rn_get_params(struct ib_device *device,
 255                             u8 port_num,
 256                             enum rdma_netdev_t type,
 257                             struct rdma_netdev_alloc_params *params)
 258{
 259        struct hfi1_devdata *dd = dd_from_ibdev(device);
 260
 261        if (type != RDMA_NETDEV_IPOIB)
 262                return -EOPNOTSUPP;
 263
 264        if (!HFI1_CAP_IS_KSET(AIP) || !dd->num_netdev_contexts)
 265                return -EOPNOTSUPP;
 266
 267        if (!port_num || port_num > dd->num_pports)
 268                return -EINVAL;
 269
 270        params->sizeof_priv = sizeof(struct hfi1_ipoib_rdma_netdev);
 271        params->txqs = dd->num_sdma;
 272        params->rxqs = dd->num_netdev_contexts;
 273        params->param = NULL;
 274        params->initialize_rdma_netdev = hfi1_ipoib_setup_rn;
 275
 276        return 0;
 277}
 278