|
@@ -39,22 +39,38 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
39
|
39
|
/** List of connections */
|
40
|
40
|
static LIST_HEAD ( ib_cm_conns );
|
41
|
41
|
|
|
42
|
+/**
|
|
43
|
+ * Find connection by local communication ID
|
|
44
|
+ *
|
|
45
|
+ * @v local_id Local communication ID
|
|
46
|
+ * @ret conn Connection, or NULL
|
|
47
|
+ */
|
|
48
|
+static struct ib_connection * ib_cm_find ( uint32_t local_id ) {
|
|
49
|
+ struct ib_connection *conn;
|
|
50
|
+
|
|
51
|
+ list_for_each_entry ( conn, &ib_cm_conns, list ) {
|
|
52
|
+ if ( conn->local_id == local_id )
|
|
53
|
+ return conn;
|
|
54
|
+ }
|
|
55
|
+ return NULL;
|
|
56
|
+}
|
|
57
|
+
|
42
|
58
|
/**
|
43
|
59
|
* Send "ready to use" response
|
44
|
60
|
*
|
45
|
61
|
* @v ibdev Infiniband device
|
46
|
62
|
* @v mi Management interface
|
47
|
|
- * @v conn Connection
|
48
|
63
|
* @v av Address vector
|
|
64
|
+ * @v local_id Local communication ID
|
|
65
|
+ * @v remote_id Remote communication ID
|
49
|
66
|
* @ret rc Return status code
|
50
|
67
|
*/
|
51
|
68
|
static int ib_cm_send_rtu ( struct ib_device *ibdev,
|
52
|
69
|
struct ib_mad_interface *mi,
|
53
|
|
- struct ib_connection *conn,
|
54
|
|
- struct ib_address_vector *av ) {
|
|
70
|
+ struct ib_address_vector *av,
|
|
71
|
+ uint32_t local_id, uint32_t remote_id ) {
|
55
|
72
|
union ib_mad mad;
|
56
|
|
- struct ib_cm_ready_to_use *ready =
|
57
|
|
- &mad.cm.cm_data.ready_to_use;
|
|
73
|
+ struct ib_cm_ready_to_use *rtu = &mad.cm.cm_data.ready_to_use;
|
58
|
74
|
int rc;
|
59
|
75
|
|
60
|
76
|
/* Construct "ready to use" response */
|
|
@@ -63,11 +79,10 @@ static int ib_cm_send_rtu ( struct ib_device *ibdev,
|
63
|
79
|
mad.hdr.class_version = IB_CM_CLASS_VERSION;
|
64
|
80
|
mad.hdr.method = IB_MGMT_METHOD_SEND;
|
65
|
81
|
mad.hdr.attr_id = htons ( IB_CM_ATTR_READY_TO_USE );
|
66
|
|
- ready->local_id = htonl ( conn->local_id );
|
67
|
|
- ready->remote_id = htonl ( conn->remote_id );
|
|
82
|
+ rtu->local_id = htonl ( local_id );
|
|
83
|
+ rtu->remote_id = htonl ( remote_id );
|
68
|
84
|
if ( ( rc = ib_mi_send ( ibdev, mi, &mad, av ) ) != 0 ){
|
69
|
|
- DBGC ( conn, "CM %p could not send RTU: %s\n",
|
70
|
|
- conn, strerror ( rc ) );
|
|
85
|
+ DBG ( "CM could not send RTU: %s\n", strerror ( rc ) );
|
71
|
86
|
return rc;
|
72
|
87
|
}
|
73
|
88
|
|
|
@@ -87,38 +102,113 @@ static int ib_cm_send_rtu ( struct ib_device *ibdev,
|
87
|
102
|
* reply. We have to respond to these with duplicate "ready to use"
|
88
|
103
|
* MADs, otherwise the peer may time out and drop the connection.
|
89
|
104
|
*/
|
90
|
|
-static void ib_cm_connect_rep ( struct ib_device *ibdev,
|
91
|
|
- struct ib_mad_interface *mi,
|
92
|
|
- union ib_mad *mad,
|
93
|
|
- struct ib_address_vector *av ) {
|
94
|
|
- struct ib_cm_connect_reply *connect_rep =
|
95
|
|
- &mad->cm.cm_data.connect_reply;
|
|
105
|
+static void ib_cm_recv_rep ( struct ib_device *ibdev,
|
|
106
|
+ struct ib_mad_interface *mi,
|
|
107
|
+ union ib_mad *mad,
|
|
108
|
+ struct ib_address_vector *av ) {
|
|
109
|
+ struct ib_cm_connect_reply *rep = &mad->cm.cm_data.connect_reply;
|
96
|
110
|
struct ib_connection *conn;
|
|
111
|
+ uint32_t local_id = ntohl ( rep->remote_id );
|
97
|
112
|
int rc;
|
98
|
113
|
|
99
|
114
|
/* Identify connection */
|
100
|
|
- list_for_each_entry ( conn, &ib_cm_conns, list ) {
|
101
|
|
- if ( ntohl ( connect_rep->remote_id ) != conn->local_id )
|
102
|
|
- continue;
|
|
115
|
+ conn = ib_cm_find ( local_id );
|
|
116
|
+ if ( conn ) {
|
103
|
117
|
/* Try to send "ready to use" reply */
|
104
|
|
- if ( ( rc = ib_cm_send_rtu ( ibdev, mi, conn, av ) ) != 0 ) {
|
105
|
|
- /* Ignore errors */
|
106
|
|
- return;
|
|
118
|
+ if ( ( rc = ib_cm_send_rtu ( ibdev, mi, av, conn->local_id,
|
|
119
|
+ conn->remote_id ) ) != 0 ) {
|
|
120
|
+ /* Ignore errors; the remote end will retry */
|
107
|
121
|
}
|
108
|
|
- return;
|
|
122
|
+ } else {
|
|
123
|
+ DBG ( "CM unidentified connection %08x\n", local_id );
|
|
124
|
+ }
|
|
125
|
+}
|
|
126
|
+
|
|
127
|
+/**
|
|
128
|
+ * Send reply to disconnection request
|
|
129
|
+ *
|
|
130
|
+ * @v ibdev Infiniband device
|
|
131
|
+ * @v mi Management interface
|
|
132
|
+ * @v av Address vector
|
|
133
|
+ * @v local_id Local communication ID
|
|
134
|
+ * @v remote_id Remote communication ID
|
|
135
|
+ * @ret rc Return status code
|
|
136
|
+ */
|
|
137
|
+static int ib_cm_send_drep ( struct ib_device *ibdev,
|
|
138
|
+ struct ib_mad_interface *mi,
|
|
139
|
+ struct ib_address_vector *av,
|
|
140
|
+ uint32_t local_id, uint32_t remote_id ) {
|
|
141
|
+ union ib_mad mad;
|
|
142
|
+ struct ib_cm_disconnect_reply *drep = &mad.cm.cm_data.disconnect_reply;
|
|
143
|
+ int rc;
|
|
144
|
+
|
|
145
|
+ /* Construct reply to disconnection request */
|
|
146
|
+ memset ( &mad, 0, sizeof ( mad ) );
|
|
147
|
+ mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
|
|
148
|
+ mad.hdr.class_version = IB_CM_CLASS_VERSION;
|
|
149
|
+ mad.hdr.method = IB_MGMT_METHOD_SEND;
|
|
150
|
+ mad.hdr.attr_id = htons ( IB_CM_ATTR_DISCONNECT_REPLY );
|
|
151
|
+ drep->local_id = htonl ( local_id );
|
|
152
|
+ drep->remote_id = htonl ( remote_id );
|
|
153
|
+ if ( ( rc = ib_mi_send ( ibdev, mi, &mad, av ) ) != 0 ){
|
|
154
|
+ DBG ( "CM could not send DREP: %s\n", strerror ( rc ) );
|
|
155
|
+ return rc;
|
109
|
156
|
}
|
110
|
157
|
|
111
|
|
- DBG ( "CM unidentified connection %08x\n",
|
112
|
|
- ntohl ( connect_rep->remote_id ) );
|
|
158
|
+ return 0;
|
113
|
159
|
}
|
114
|
160
|
|
|
161
|
+/**
|
|
162
|
+ * Handle disconnection requests
|
|
163
|
+ *
|
|
164
|
+ * @v ibdev Infiniband device
|
|
165
|
+ * @v mi Management interface
|
|
166
|
+ * @v mad Received MAD
|
|
167
|
+ * @v av Source address vector
|
|
168
|
+ * @ret rc Return status code
|
|
169
|
+ */
|
|
170
|
+static void ib_cm_recv_dreq ( struct ib_device *ibdev,
|
|
171
|
+ struct ib_mad_interface *mi,
|
|
172
|
+ union ib_mad *mad,
|
|
173
|
+ struct ib_address_vector *av ) {
|
|
174
|
+ struct ib_cm_disconnect_request *dreq =
|
|
175
|
+ &mad->cm.cm_data.disconnect_request;
|
|
176
|
+ struct ib_connection *conn;
|
|
177
|
+ uint32_t local_id = ntohl ( dreq->remote_id );
|
|
178
|
+ uint32_t remote_id = ntohl ( dreq->local_id );
|
|
179
|
+ int rc;
|
|
180
|
+
|
|
181
|
+ /* Identify connection */
|
|
182
|
+ conn = ib_cm_find ( local_id );
|
|
183
|
+ if ( conn ) {
|
|
184
|
+ /* Notify upper layer */
|
|
185
|
+ conn->op->changed ( ibdev, conn->qp, conn, -ENOTCONN,
|
|
186
|
+ &dreq->private_data,
|
|
187
|
+ sizeof ( dreq->private_data ) );
|
|
188
|
+ } else {
|
|
189
|
+ DBG ( "CM unidentified connection %08x\n", local_id );
|
|
190
|
+ }
|
|
191
|
+
|
|
192
|
+ /* Send reply */
|
|
193
|
+ if ( ( rc = ib_cm_send_drep ( ibdev, mi, av, local_id,
|
|
194
|
+ remote_id ) ) != 0 ) {
|
|
195
|
+ /* Ignore errors; the remote end will retry */
|
|
196
|
+ }
|
|
197
|
+};
|
|
198
|
+
|
115
|
199
|
/** Communication management agents */
|
116
|
200
|
struct ib_mad_agent ib_cm_agent[] __ib_mad_agent = {
|
117
|
201
|
{
|
118
|
202
|
.mgmt_class = IB_MGMT_CLASS_CM,
|
119
|
203
|
.class_version = IB_CM_CLASS_VERSION,
|
120
|
204
|
.attr_id = htons ( IB_CM_ATTR_CONNECT_REPLY ),
|
121
|
|
- .handle = ib_cm_connect_rep,
|
|
205
|
+ .handle = ib_cm_recv_rep,
|
|
206
|
+ },
|
|
207
|
+ {
|
|
208
|
+ .mgmt_class = IB_MGMT_CLASS_CM,
|
|
209
|
+ .class_version = IB_CM_CLASS_VERSION,
|
|
210
|
+ .attr_id = htons ( IB_CM_ATTR_DISCONNECT_REQUEST ),
|
|
211
|
+ .handle = ib_cm_recv_dreq,
|
122
|
212
|
},
|
123
|
213
|
};
|
124
|
214
|
|
|
@@ -159,10 +249,8 @@ static void ib_cm_req_complete ( struct ib_device *ibdev,
|
159
|
249
|
struct ib_connection *conn = ib_madx_get_ownerdata ( madx );
|
160
|
250
|
struct ib_queue_pair *qp = conn->qp;
|
161
|
251
|
struct ib_cm_common *common = &mad->cm.cm_data.common;
|
162
|
|
- struct ib_cm_connect_reply *connect_rep =
|
163
|
|
- &mad->cm.cm_data.connect_reply;
|
164
|
|
- struct ib_cm_connect_reject *connect_rej =
|
165
|
|
- &mad->cm.cm_data.connect_reject;
|
|
252
|
+ struct ib_cm_connect_reply *rep = &mad->cm.cm_data.connect_reply;
|
|
253
|
+ struct ib_cm_connect_reject *rej = &mad->cm.cm_data.connect_reject;
|
166
|
254
|
void *private_data = NULL;
|
167
|
255
|
size_t private_data_len = 0;
|
168
|
256
|
|
|
@@ -183,10 +271,10 @@ static void ib_cm_req_complete ( struct ib_device *ibdev,
|
183
|
271
|
|
184
|
272
|
case htons ( IB_CM_ATTR_CONNECT_REPLY ) :
|
185
|
273
|
/* Extract fields */
|
186
|
|
- qp->av.qpn = ( ntohl ( connect_rep->local_qpn ) >> 8 );
|
187
|
|
- qp->send.psn = ( ntohl ( connect_rep->starting_psn ) >> 8 );
|
188
|
|
- private_data = &connect_rep->private_data;
|
189
|
|
- private_data_len = sizeof ( connect_rep->private_data );
|
|
274
|
+ qp->av.qpn = ( ntohl ( rep->local_qpn ) >> 8 );
|
|
275
|
+ qp->send.psn = ( ntohl ( rep->starting_psn ) >> 8 );
|
|
276
|
+ private_data = &rep->private_data;
|
|
277
|
+ private_data_len = sizeof ( rep->private_data );
|
190
|
278
|
DBGC ( conn, "CM %p connected to QPN %lx PSN %x\n",
|
191
|
279
|
conn, qp->av.qpn, qp->send.psn );
|
192
|
280
|
|
|
@@ -198,7 +286,8 @@ static void ib_cm_req_complete ( struct ib_device *ibdev,
|
198
|
286
|
}
|
199
|
287
|
|
200
|
288
|
/* Send "ready to use" reply */
|
201
|
|
- if ( ( rc = ib_cm_send_rtu ( ibdev, mi, conn, av ) ) != 0 ) {
|
|
289
|
+ if ( ( rc = ib_cm_send_rtu ( ibdev, mi, av, conn->local_id,
|
|
290
|
+ conn->remote_id ) ) != 0 ) {
|
202
|
291
|
/* Treat as non-fatal */
|
203
|
292
|
rc = 0;
|
204
|
293
|
}
|
|
@@ -207,13 +296,13 @@ static void ib_cm_req_complete ( struct ib_device *ibdev,
|
207
|
296
|
case htons ( IB_CM_ATTR_CONNECT_REJECT ) :
|
208
|
297
|
/* Extract fields */
|
209
|
298
|
DBGC ( conn, "CM %p connection rejected (reason %d)\n",
|
210
|
|
- conn, ntohs ( connect_rej->reason ) );
|
|
299
|
+ conn, ntohs ( rej->reason ) );
|
211
|
300
|
/* Private data is valid only for a Consumer Reject */
|
212
|
|
- if ( connect_rej->reason == htons ( IB_CM_REJECT_CONSUMER ) ) {
|
213
|
|
- private_data = &connect_rej->private_data;
|
214
|
|
- private_data_len = sizeof (connect_rej->private_data);
|
|
301
|
+ if ( rej->reason == htons ( IB_CM_REJECT_CONSUMER ) ) {
|
|
302
|
+ private_data = &rej->private_data;
|
|
303
|
+ private_data_len = sizeof ( rej->private_data );
|
215
|
304
|
}
|
216
|
|
- rc = ib_cm_rejection_reason_to_rc ( connect_rej->reason );
|
|
305
|
+ rc = ib_cm_rejection_reason_to_rc ( rej->reason );
|
217
|
306
|
break;
|
218
|
307
|
|
219
|
308
|
default:
|
|
@@ -252,8 +341,7 @@ static void ib_cm_path_complete ( struct ib_device *ibdev,
|
252
|
341
|
struct ib_connection *conn = ib_path_get_ownerdata ( path );
|
253
|
342
|
struct ib_queue_pair *qp = conn->qp;
|
254
|
343
|
union ib_mad mad;
|
255
|
|
- struct ib_cm_connect_request *connect_req =
|
256
|
|
- &mad.cm.cm_data.connect_request;
|
|
344
|
+ struct ib_cm_connect_request *req = &mad.cm.cm_data.connect_request;
|
257
|
345
|
size_t private_data_len;
|
258
|
346
|
|
259
|
347
|
/* Report failures */
|
|
@@ -273,41 +361,38 @@ static void ib_cm_path_complete ( struct ib_device *ibdev,
|
273
|
361
|
mad.hdr.class_version = IB_CM_CLASS_VERSION;
|
274
|
362
|
mad.hdr.method = IB_MGMT_METHOD_SEND;
|
275
|
363
|
mad.hdr.attr_id = htons ( IB_CM_ATTR_CONNECT_REQUEST );
|
276
|
|
- connect_req->local_id = htonl ( conn->local_id );
|
277
|
|
- memcpy ( &connect_req->service_id, &conn->service_id,
|
278
|
|
- sizeof ( connect_req->service_id ) );
|
279
|
|
- ib_get_hca_info ( ibdev, &connect_req->local_ca );
|
280
|
|
- connect_req->local_qpn__responder_resources =
|
281
|
|
- htonl ( ( qp->qpn << 8 ) | 1 );
|
282
|
|
- connect_req->local_eecn__initiator_depth = htonl ( ( 0 << 8 ) | 1 );
|
283
|
|
- connect_req->remote_eecn__remote_timeout__service_type__ee_flow_ctrl =
|
|
364
|
+ req->local_id = htonl ( conn->local_id );
|
|
365
|
+ memcpy ( &req->service_id, &conn->service_id,
|
|
366
|
+ sizeof ( req->service_id ) );
|
|
367
|
+ ib_get_hca_info ( ibdev, &req->local_ca );
|
|
368
|
+ req->local_qpn__responder_resources = htonl ( ( qp->qpn << 8 ) | 1 );
|
|
369
|
+ req->local_eecn__initiator_depth = htonl ( ( 0 << 8 ) | 1 );
|
|
370
|
+ req->remote_eecn__remote_timeout__service_type__ee_flow_ctrl =
|
284
|
371
|
htonl ( ( 0x14 << 3 ) | ( IB_CM_TRANSPORT_RC << 1 ) |
|
285
|
372
|
( 0 << 0 ) );
|
286
|
|
- connect_req->starting_psn__local_timeout__retry_count =
|
|
373
|
+ req->starting_psn__local_timeout__retry_count =
|
287
|
374
|
htonl ( ( qp->recv.psn << 8 ) | ( 0x14 << 3 ) |
|
288
|
375
|
( 0x07 << 0 ) );
|
289
|
|
- connect_req->pkey = htons ( ibdev->pkey );
|
290
|
|
- connect_req->payload_mtu__rdc_exists__rnr_retry =
|
|
376
|
+ req->pkey = htons ( ibdev->pkey );
|
|
377
|
+ req->payload_mtu__rdc_exists__rnr_retry =
|
291
|
378
|
( ( IB_MTU_2048 << 4 ) | ( 1 << 3 ) | ( 0x07 << 0 ) );
|
292
|
|
- connect_req->max_cm_retries__srq =
|
293
|
|
- ( ( 0x0f << 4 ) | ( 0 << 3 ) );
|
294
|
|
- connect_req->primary.local_lid = htons ( ibdev->lid );
|
295
|
|
- connect_req->primary.remote_lid = htons ( conn->qp->av.lid );
|
296
|
|
- memcpy ( &connect_req->primary.local_gid, &ibdev->gid,
|
297
|
|
- sizeof ( connect_req->primary.local_gid ) );
|
298
|
|
- memcpy ( &connect_req->primary.remote_gid, &conn->qp->av.gid,
|
299
|
|
- sizeof ( connect_req->primary.remote_gid ) );
|
300
|
|
- connect_req->primary.flow_label__rate =
|
|
379
|
+ req->max_cm_retries__srq = ( ( 0x0f << 4 ) | ( 0 << 3 ) );
|
|
380
|
+ req->primary.local_lid = htons ( ibdev->lid );
|
|
381
|
+ req->primary.remote_lid = htons ( conn->qp->av.lid );
|
|
382
|
+ memcpy ( &req->primary.local_gid, &ibdev->gid,
|
|
383
|
+ sizeof ( req->primary.local_gid ) );
|
|
384
|
+ memcpy ( &req->primary.remote_gid, &conn->qp->av.gid,
|
|
385
|
+ sizeof ( req->primary.remote_gid ) );
|
|
386
|
+ req->primary.flow_label__rate =
|
301
|
387
|
htonl ( ( 0 << 12 ) | ( conn->qp->av.rate << 0 ) );
|
302
|
|
- connect_req->primary.hop_limit = 0;
|
303
|
|
- connect_req->primary.sl__subnet_local =
|
|
388
|
+ req->primary.hop_limit = 0;
|
|
389
|
+ req->primary.sl__subnet_local =
|
304
|
390
|
( ( conn->qp->av.sl << 4 ) | ( 1 << 3 ) );
|
305
|
|
- connect_req->primary.local_ack_timeout = ( 0x13 << 3 );
|
|
391
|
+ req->primary.local_ack_timeout = ( 0x13 << 3 );
|
306
|
392
|
private_data_len = conn->private_data_len;
|
307
|
|
- if ( private_data_len > sizeof ( connect_req->private_data ) )
|
308
|
|
- private_data_len = sizeof ( connect_req->private_data );
|
309
|
|
- memcpy ( &connect_req->private_data, &conn->private_data,
|
310
|
|
- private_data_len );
|
|
393
|
+ if ( private_data_len > sizeof ( req->private_data ) )
|
|
394
|
+ private_data_len = sizeof ( req->private_data );
|
|
395
|
+ memcpy ( &req->private_data, &conn->private_data, private_data_len );
|
311
|
396
|
|
312
|
397
|
/* Create connection request */
|
313
|
398
|
av->qpn = IB_QPN_GSI;
|