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        dev->tstats = 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 const struct net_device_ops hfi1_ipoib_netdev_ops = {
  97        .ndo_init         = hfi1_ipoib_dev_init,
  98        .ndo_uninit       = hfi1_ipoib_dev_uninit,
  99        .ndo_open         = hfi1_ipoib_dev_open,
 100        .ndo_stop         = hfi1_ipoib_dev_stop,
 101        .ndo_get_stats64  = dev_get_tstats64,
 102};
 103
 104static int hfi1_ipoib_send(struct net_device *dev,
 105                           struct sk_buff *skb,
 106                           struct ib_ah *address,
 107                           u32 dqpn)
 108{
 109        return hfi1_ipoib_send_dma(dev, skb, address, dqpn);
 110}
 111
 112static int hfi1_ipoib_mcast_attach(struct net_device *dev,
 113                                   struct ib_device *device,
 114                                   union ib_gid *mgid,
 115                                   u16 mlid,
 116                                   int set_qkey,
 117                                   u32 qkey)
 118{
 119        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
 120        u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);
 121        struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);
 122        struct rvt_qp *qp;
 123        int ret = -EINVAL;
 124
 125        rcu_read_lock();
 126
 127        qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
 128        if (qp) {
 129                rvt_get_qp(qp);
 130                rcu_read_unlock();
 131                if (set_qkey)
 132                        priv->qkey = qkey;
 133
 134                /* attach QP to multicast group */
 135                ret = ib_attach_mcast(&qp->ibqp, mgid, mlid);
 136                rvt_put_qp(qp);
 137        } else {
 138                rcu_read_unlock();
 139        }
 140
 141        return ret;
 142}
 143
 144static int hfi1_ipoib_mcast_detach(struct net_device *dev,
 145                                   struct ib_device *device,
 146                                   union ib_gid *mgid,
 147                                   u16 mlid)
 148{
 149        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
 150        u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);
 151        struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);
 152        struct rvt_qp *qp;
 153        int ret = -EINVAL;
 154
 155        rcu_read_lock();
 156
 157        qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
 158        if (qp) {
 159                rvt_get_qp(qp);
 160                rcu_read_unlock();
 161                ret = ib_detach_mcast(&qp->ibqp, mgid, mlid);
 162                rvt_put_qp(qp);
 163        } else {
 164                rcu_read_unlock();
 165        }
 166        return ret;
 167}
 168
 169static void hfi1_ipoib_netdev_dtor(struct net_device *dev)
 170{
 171        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
 172
 173        hfi1_ipoib_txreq_deinit(priv);
 174        hfi1_ipoib_rxq_deinit(priv->netdev);
 175
 176        free_percpu(dev->tstats);
 177}
 178
 179static void hfi1_ipoib_free_rdma_netdev(struct net_device *dev)
 180{
 181        hfi1_ipoib_netdev_dtor(dev);
 182        free_netdev(dev);
 183}
 184
 185static void hfi1_ipoib_set_id(struct net_device *dev, int id)
 186{
 187        struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
 188
 189        priv->pkey_index = (u16)id;
 190        ib_query_pkey(priv->device,
 191                      priv->port_num,
 192                      priv->pkey_index,
 193                      &priv->pkey);
 194}
 195
 196static int hfi1_ipoib_setup_rn(struct ib_device *device,
 197                               u8 port_num,
 198                               struct net_device *netdev,
 199                               void *param)
 200{
 201        struct hfi1_devdata *dd = dd_from_ibdev(device);
 202        struct rdma_netdev *rn = netdev_priv(netdev);
 203        struct hfi1_ipoib_dev_priv *priv;
 204        int rc;
 205
 206        rn->send = hfi1_ipoib_send;
 207        rn->attach_mcast = hfi1_ipoib_mcast_attach;
 208        rn->detach_mcast = hfi1_ipoib_mcast_detach;
 209        rn->set_id = hfi1_ipoib_set_id;
 210        rn->hca = device;
 211        rn->port_num = port_num;
 212        rn->mtu = netdev->mtu;
 213
 214        priv = hfi1_ipoib_priv(netdev);
 215        priv->dd = dd;
 216        priv->netdev = netdev;
 217        priv->device = device;
 218        priv->port_num = port_num;
 219        priv->netdev_ops = netdev->netdev_ops;
 220
 221        netdev->netdev_ops = &hfi1_ipoib_netdev_ops;
 222
 223        ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey);
 224
 225        rc = hfi1_ipoib_txreq_init(priv);
 226        if (rc) {
 227                dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc);
 228                hfi1_ipoib_free_rdma_netdev(netdev);
 229                return rc;
 230        }
 231
 232        rc = hfi1_ipoib_rxq_init(netdev);
 233        if (rc) {
 234                dd_dev_err(dd, "IPoIB netdev RX init - failed(%d)\n", rc);
 235                hfi1_ipoib_free_rdma_netdev(netdev);
 236                return rc;
 237        }
 238
 239        netdev->priv_destructor = hfi1_ipoib_netdev_dtor;
 240        netdev->needs_free_netdev = true;
 241
 242        return 0;
 243}
 244
 245int hfi1_ipoib_rn_get_params(struct ib_device *device,
 246                             u8 port_num,
 247                             enum rdma_netdev_t type,
 248                             struct rdma_netdev_alloc_params *params)
 249{
 250        struct hfi1_devdata *dd = dd_from_ibdev(device);
 251
 252        if (type != RDMA_NETDEV_IPOIB)
 253                return -EOPNOTSUPP;
 254
 255        if (!HFI1_CAP_IS_KSET(AIP) || !dd->num_netdev_contexts)
 256                return -EOPNOTSUPP;
 257
 258        if (!port_num || port_num > dd->num_pports)
 259                return -EINVAL;
 260
 261        params->sizeof_priv = sizeof(struct hfi1_ipoib_rdma_netdev);
 262        params->txqs = dd->num_sdma;
 263        params->rxqs = dd->num_netdev_contexts;
 264        params->param = NULL;
 265        params->initialize_rdma_netdev = hfi1_ipoib_setup_rn;
 266
 267        return 0;
 268}
 269