Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
39566 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3
*
4
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
5
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
6
*
7
* This software is available to you under a choice of one of two
8
* licenses. You may choose to be licensed under the terms of the GNU
9
* General Public License (GPL) Version 2, available from the file
10
* COPYING in the main directory of this source tree, or the
11
* OpenIB.org BSD license below:
12
*
13
* Redistribution and use in source and binary forms, with or
14
* without modification, are permitted provided that the following
15
* conditions are met:
16
*
17
* - Redistributions of source code must retain the above
18
* copyright notice, this list of conditions and the following
19
* disclaimer.
20
*
21
* - Redistributions in binary form must reproduce the above
22
* copyright notice, this list of conditions and the following
23
* disclaimer in the documentation and/or other materials
24
* provided with the distribution.
25
*
26
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
* SOFTWARE.
34
*/
35
36
#include <sys/cdefs.h>
37
#include "ipoib.h"
38
39
int ipoib_mcast_attach(struct ipoib_dev_priv *priv, u16 mlid, union ib_gid *mgid, int set_qkey)
40
{
41
struct ib_qp_attr *qp_attr = NULL;
42
int ret;
43
u16 pkey_index;
44
45
if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) {
46
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
47
ret = -ENXIO;
48
goto out;
49
}
50
set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
51
52
if (set_qkey) {
53
ret = -ENOMEM;
54
qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL);
55
if (!qp_attr)
56
goto out;
57
58
/* set correct QKey for QP */
59
qp_attr->qkey = priv->qkey;
60
ret = ib_modify_qp(priv->qp, qp_attr, IB_QP_QKEY);
61
if (ret) {
62
ipoib_warn(priv, "failed to modify QP, ret = %d\n", ret);
63
goto out;
64
}
65
}
66
67
/* attach QP to multicast group */
68
ret = ib_attach_mcast(priv->qp, mgid, mlid);
69
if (ret)
70
ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret);
71
72
out:
73
kfree(qp_attr);
74
return ret;
75
}
76
77
int ipoib_init_qp(struct ipoib_dev_priv *priv)
78
{
79
int ret;
80
struct ib_qp_attr qp_attr;
81
int attr_mask;
82
83
if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
84
return -1;
85
86
qp_attr.qp_state = IB_QPS_INIT;
87
qp_attr.qkey = 0;
88
qp_attr.port_num = priv->port;
89
qp_attr.pkey_index = priv->pkey_index;
90
attr_mask =
91
IB_QP_QKEY |
92
IB_QP_PORT |
93
IB_QP_PKEY_INDEX |
94
IB_QP_STATE;
95
96
ret = ib_modify_qp(priv->qp, &qp_attr, attr_mask);
97
if (ret) {
98
ipoib_warn(priv, "failed to modify QP to init, ret = %d\n", ret);
99
goto out_fail;
100
}
101
102
qp_attr.qp_state = IB_QPS_RTR;
103
/* Can't set this in a INIT->RTR transition */
104
attr_mask &= ~IB_QP_PORT;
105
ret = ib_modify_qp(priv->qp, &qp_attr, attr_mask);
106
if (ret) {
107
ipoib_warn(priv, "failed to modify QP to RTR, ret = %d\n", ret);
108
goto out_fail;
109
}
110
111
qp_attr.qp_state = IB_QPS_RTS;
112
qp_attr.sq_psn = 0;
113
attr_mask |= IB_QP_SQ_PSN;
114
attr_mask &= ~IB_QP_PKEY_INDEX;
115
ret = ib_modify_qp(priv->qp, &qp_attr, attr_mask);
116
if (ret) {
117
ipoib_warn(priv, "failed to modify QP to RTS, ret = %d\n", ret);
118
goto out_fail;
119
}
120
121
return 0;
122
123
out_fail:
124
qp_attr.qp_state = IB_QPS_RESET;
125
if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
126
ipoib_warn(priv, "Failed to modify QP to RESET state\n");
127
128
return ret;
129
}
130
131
int ipoib_transport_dev_init(struct ipoib_dev_priv *priv, struct ib_device *ca)
132
{
133
struct ib_qp_init_attr init_attr = {
134
.cap = {
135
.max_send_wr = ipoib_sendq_size,
136
.max_recv_wr = ipoib_recvq_size,
137
.max_send_sge = 1,
138
.max_recv_sge = IPOIB_UD_RX_SG
139
},
140
.sq_sig_type = IB_SIGNAL_ALL_WR,
141
.qp_type = IB_QPT_UD
142
};
143
struct ib_cq_init_attr cq_attr = {};
144
caddr_t lla;
145
146
int ret, size;
147
int i;
148
/* XXX struct ethtool_coalesce *coal; */
149
150
priv->pd = ib_alloc_pd(priv->ca, 0);
151
if (IS_ERR(priv->pd)) {
152
printk(KERN_WARNING "%s: failed to allocate PD\n", ca->name);
153
return -ENODEV;
154
}
155
156
size = ipoib_recvq_size + 1;
157
ret = ipoib_cm_dev_init(priv);
158
if (!ret) {
159
size += ipoib_sendq_size;
160
if (ipoib_cm_has_srq(priv))
161
size += ipoib_recvq_size + 1; /* 1 extra for rx_drain_qp */
162
else
163
size += ipoib_recvq_size * ipoib_max_conn_qp;
164
}
165
166
cq_attr.cqe = size;
167
priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, priv, &cq_attr);
168
if (IS_ERR(priv->recv_cq)) {
169
printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name);
170
goto out_free_mr;
171
}
172
173
cq_attr.cqe = ipoib_sendq_size;
174
priv->send_cq = ib_create_cq(priv->ca, ipoib_send_comp_handler, NULL,
175
priv, &cq_attr);
176
if (IS_ERR(priv->send_cq)) {
177
printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name);
178
goto out_free_recv_cq;
179
}
180
181
if (ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP))
182
goto out_free_send_cq;
183
184
#if 0
185
/* XXX */
186
coal = kzalloc(sizeof *coal, GFP_KERNEL);
187
if (coal) {
188
coal->rx_coalesce_usecs = 10;
189
coal->tx_coalesce_usecs = 10;
190
coal->rx_max_coalesced_frames = 16;
191
coal->tx_max_coalesced_frames = 16;
192
dev->ethtool_ops->set_coalesce(dev, coal);
193
kfree(coal);
194
}
195
#endif
196
197
init_attr.send_cq = priv->send_cq;
198
init_attr.recv_cq = priv->recv_cq;
199
200
if (priv->hca_caps & IB_DEVICE_UD_TSO)
201
init_attr.create_flags |= IB_QP_CREATE_IPOIB_UD_LSO;
202
203
if (priv->hca_caps & IB_DEVICE_BLOCK_MULTICAST_LOOPBACK)
204
init_attr.create_flags |= IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK;
205
206
init_attr.cap.max_send_sge = IPOIB_UD_TX_SG;
207
208
priv->qp = ib_create_qp(priv->pd, &init_attr);
209
if (IS_ERR(priv->qp)) {
210
printk(KERN_WARNING "%s: failed to create QP\n", ca->name);
211
goto out_free_send_cq;
212
}
213
214
lla = if_getlladdr(priv->dev);
215
lla[1] = (priv->qp->qp_num >> 16) & 0xff;
216
lla[2] = (priv->qp->qp_num >> 8) & 0xff;
217
lla[3] = (priv->qp->qp_num ) & 0xff;
218
219
for (i = 0; i < IPOIB_MAX_TX_SG; ++i)
220
priv->tx_sge[i].lkey = priv->pd->local_dma_lkey;
221
222
priv->tx_wr.wr.opcode = IB_WR_SEND;
223
priv->tx_wr.wr.sg_list = priv->tx_sge;
224
priv->tx_wr.wr.send_flags = IB_SEND_SIGNALED;
225
226
for (i = 0; i < IPOIB_UD_RX_SG; ++i)
227
priv->rx_sge[i].lkey = priv->pd->local_dma_lkey;
228
priv->rx_wr.next = NULL;
229
priv->rx_wr.sg_list = priv->rx_sge;
230
231
return 0;
232
233
out_free_send_cq:
234
ib_destroy_cq(priv->send_cq);
235
236
out_free_recv_cq:
237
ib_destroy_cq(priv->recv_cq);
238
239
out_free_mr:
240
ipoib_cm_dev_cleanup(priv);
241
242
ib_dealloc_pd(priv->pd);
243
return -ENODEV;
244
}
245
246
void ipoib_transport_dev_cleanup(struct ipoib_dev_priv *priv)
247
{
248
249
if (priv->qp) {
250
if (ib_destroy_qp(priv->qp))
251
ipoib_warn(priv, "ib_qp_destroy failed\n");
252
253
priv->qp = NULL;
254
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
255
}
256
257
ib_destroy_cq(priv->send_cq);
258
259
ib_destroy_cq(priv->recv_cq);
260
261
ipoib_cm_dev_cleanup(priv);
262
263
ib_dealloc_pd(priv->pd);
264
}
265
266
void ipoib_event(struct ib_event_handler *handler,
267
struct ib_event *record)
268
{
269
struct ipoib_dev_priv *priv =
270
container_of(handler, struct ipoib_dev_priv, event_handler);
271
272
if (record->element.port_num != priv->port)
273
return;
274
275
ipoib_dbg(priv, "Event %d on device %s port %d\n", record->event,
276
record->device->name, record->element.port_num);
277
278
if (record->event == IB_EVENT_SM_CHANGE ||
279
record->event == IB_EVENT_CLIENT_REREGISTER) {
280
queue_work(ipoib_workqueue, &priv->flush_light);
281
} else if (record->event == IB_EVENT_PORT_ERR ||
282
record->event == IB_EVENT_PORT_ACTIVE ||
283
record->event == IB_EVENT_LID_CHANGE ||
284
record->event == IB_EVENT_DEVICE_FATAL) {
285
queue_work(ipoib_workqueue, &priv->flush_normal);
286
} else if (record->event == IB_EVENT_PKEY_CHANGE) {
287
queue_work(ipoib_workqueue, &priv->flush_heavy);
288
}
289
}
290
291