ipoib_main.c 5.9 KB

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