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_set_id(struct net_device *dev, int id) 189{ 190 struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev); 191 192 priv->pkey_index = (u16)id; 193 ib_query_pkey(priv->device, 194 priv->port_num, 195 priv->pkey_index, 196 &priv->pkey); 197} 198 199static int hfi1_ipoib_setup_rn(struct ib_device *device, 200 u8 port_num, 201 struct net_device *netdev, 202 void *param) 203{ 204 struct hfi1_devdata *dd = dd_from_ibdev(device); 205 struct rdma_netdev *rn = netdev_priv(netdev); 206 struct hfi1_ipoib_dev_priv *priv; 207 int rc; 208 209 rn->send = hfi1_ipoib_send; 210 rn->attach_mcast = hfi1_ipoib_mcast_attach; 211 rn->detach_mcast = hfi1_ipoib_mcast_detach; 212 rn->set_id = hfi1_ipoib_set_id; 213 rn->hca = device; 214 rn->port_num = port_num; 215 rn->mtu = netdev->mtu; 216 217 priv = hfi1_ipoib_priv(netdev); 218 priv->dd = dd; 219 priv->netdev = netdev; 220 priv->device = device; 221 priv->port_num = port_num; 222 priv->netdev_ops = netdev->netdev_ops; 223 224 ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey); 225 226 rc = hfi1_ipoib_txreq_init(priv); 227 if (rc) { 228 dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc); 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_txreq_deinit(priv); 236 return rc; 237 } 238 239 netdev->netdev_ops = &hfi1_ipoib_netdev_ops; 240 241 netdev->priv_destructor = hfi1_ipoib_netdev_dtor; 242 netdev->needs_free_netdev = true; 243 244 return 0; 245} 246 247int hfi1_ipoib_rn_get_params(struct ib_device *device, 248 u8 port_num, 249 enum rdma_netdev_t type, 250 struct rdma_netdev_alloc_params *params) 251{ 252 struct hfi1_devdata *dd = dd_from_ibdev(device); 253 254 if (type != RDMA_NETDEV_IPOIB) 255 return -EOPNOTSUPP; 256 257 if (!HFI1_CAP_IS_KSET(AIP) || !dd->num_netdev_contexts) 258 return -EOPNOTSUPP; 259 260 if (!port_num || port_num > dd->num_pports) 261 return -EINVAL; 262 263 params->sizeof_priv = sizeof(struct hfi1_ipoib_rdma_netdev); 264 params->txqs = dd->num_sdma; 265 params->rxqs = dd->num_netdev_contexts; 266 params->param = NULL; 267 params->initialize_rdma_netdev = hfi1_ipoib_setup_rn; 268 269 return 0; 270} 271