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