diff options
Diffstat (limited to 'net/rds/ib_cm.c')
-rw-r--r-- | net/rds/ib_cm.c | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index f8e40e1a6038..c2d372f13dbb 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
@@ -98,21 +98,34 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even | |||
98 | struct ib_qp_attr qp_attr; | 98 | struct ib_qp_attr qp_attr; |
99 | int err; | 99 | int err; |
100 | 100 | ||
101 | if (event->param.conn.private_data_len) { | 101 | if (event->param.conn.private_data_len >= sizeof(*dp)) { |
102 | dp = event->param.conn.private_data; | 102 | dp = event->param.conn.private_data; |
103 | 103 | ||
104 | rds_ib_set_protocol(conn, | 104 | /* make sure it isn't empty data */ |
105 | if (dp->dp_protocol_major) { | ||
106 | rds_ib_set_protocol(conn, | ||
105 | RDS_PROTOCOL(dp->dp_protocol_major, | 107 | RDS_PROTOCOL(dp->dp_protocol_major, |
106 | dp->dp_protocol_minor)); | 108 | dp->dp_protocol_minor)); |
107 | rds_ib_set_flow_control(conn, be32_to_cpu(dp->dp_credit)); | 109 | rds_ib_set_flow_control(conn, be32_to_cpu(dp->dp_credit)); |
110 | } | ||
108 | } | 111 | } |
109 | 112 | ||
110 | printk(KERN_NOTICE "RDS/IB: connected to %pI4 version %u.%u%s\n", | 113 | printk(KERN_NOTICE "RDS/IB: connected to %pI4 version %u.%u%s\n", |
111 | &conn->c_laddr, | 114 | &conn->c_faddr, |
112 | RDS_PROTOCOL_MAJOR(conn->c_version), | 115 | RDS_PROTOCOL_MAJOR(conn->c_version), |
113 | RDS_PROTOCOL_MINOR(conn->c_version), | 116 | RDS_PROTOCOL_MINOR(conn->c_version), |
114 | ic->i_flowctl ? ", flow control" : ""); | 117 | ic->i_flowctl ? ", flow control" : ""); |
115 | 118 | ||
119 | /* | ||
120 | * Init rings and fill recv. this needs to wait until protocol negotiation | ||
121 | * is complete, since ring layout is different from 3.0 to 3.1. | ||
122 | */ | ||
123 | rds_ib_send_init_ring(ic); | ||
124 | rds_ib_recv_init_ring(ic); | ||
125 | /* Post receive buffers - as a side effect, this will update | ||
126 | * the posted credit count. */ | ||
127 | rds_ib_recv_refill(conn, GFP_KERNEL, GFP_HIGHUSER, 1); | ||
128 | |||
116 | /* Tune RNR behavior */ | 129 | /* Tune RNR behavior */ |
117 | rds_ib_tune_rnr(ic, &qp_attr); | 130 | rds_ib_tune_rnr(ic, &qp_attr); |
118 | 131 | ||
@@ -145,7 +158,7 @@ static void rds_ib_cm_fill_conn_param(struct rds_connection *conn, | |||
145 | /* XXX tune these? */ | 158 | /* XXX tune these? */ |
146 | conn_param->responder_resources = 1; | 159 | conn_param->responder_resources = 1; |
147 | conn_param->initiator_depth = 1; | 160 | conn_param->initiator_depth = 1; |
148 | conn_param->retry_count = 7; | 161 | conn_param->retry_count = min_t(unsigned int, rds_ib_retry_count, 7); |
149 | conn_param->rnr_retry_count = 7; | 162 | conn_param->rnr_retry_count = 7; |
150 | 163 | ||
151 | if (dp) { | 164 | if (dp) { |
@@ -190,9 +203,9 @@ static void rds_ib_qp_event_handler(struct ib_event *event, void *data) | |||
190 | rdma_notify(ic->i_cm_id, IB_EVENT_COMM_EST); | 203 | rdma_notify(ic->i_cm_id, IB_EVENT_COMM_EST); |
191 | break; | 204 | break; |
192 | default: | 205 | default: |
193 | printk(KERN_WARNING "RDS/ib: unhandled QP event %u " | 206 | rds_ib_conn_error(conn, "RDS/IB: Fatal QP Event %u " |
194 | "on connection to %pI4\n", event->event, | 207 | "- connection %pI4->%pI4, reconnecting\n", |
195 | &conn->c_faddr); | 208 | event->event, &conn->c_laddr, &conn->c_faddr); |
196 | break; | 209 | break; |
197 | } | 210 | } |
198 | } | 211 | } |
@@ -321,7 +334,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) | |||
321 | rdsdebug("send allocation failed\n"); | 334 | rdsdebug("send allocation failed\n"); |
322 | goto out; | 335 | goto out; |
323 | } | 336 | } |
324 | rds_ib_send_init_ring(ic); | 337 | memset(ic->i_sends, 0, ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work)); |
325 | 338 | ||
326 | ic->i_recvs = vmalloc(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work)); | 339 | ic->i_recvs = vmalloc(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work)); |
327 | if (ic->i_recvs == NULL) { | 340 | if (ic->i_recvs == NULL) { |
@@ -329,14 +342,10 @@ static int rds_ib_setup_qp(struct rds_connection *conn) | |||
329 | rdsdebug("recv allocation failed\n"); | 342 | rdsdebug("recv allocation failed\n"); |
330 | goto out; | 343 | goto out; |
331 | } | 344 | } |
345 | memset(ic->i_recvs, 0, ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work)); | ||
332 | 346 | ||
333 | rds_ib_recv_init_ring(ic); | ||
334 | rds_ib_recv_init_ack(ic); | 347 | rds_ib_recv_init_ack(ic); |
335 | 348 | ||
336 | /* Post receive buffers - as a side effect, this will update | ||
337 | * the posted credit count. */ | ||
338 | rds_ib_recv_refill(conn, GFP_KERNEL, GFP_HIGHUSER, 1); | ||
339 | |||
340 | rdsdebug("conn %p pd %p mr %p cq %p %p\n", conn, ic->i_pd, ic->i_mr, | 349 | rdsdebug("conn %p pd %p mr %p cq %p %p\n", conn, ic->i_pd, ic->i_mr, |
341 | ic->i_send_cq, ic->i_recv_cq); | 350 | ic->i_send_cq, ic->i_recv_cq); |
342 | 351 | ||
@@ -344,19 +353,32 @@ out: | |||
344 | return ret; | 353 | return ret; |
345 | } | 354 | } |
346 | 355 | ||
347 | static u32 rds_ib_protocol_compatible(const struct rds_ib_connect_private *dp) | 356 | static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event) |
348 | { | 357 | { |
358 | const struct rds_ib_connect_private *dp = event->param.conn.private_data; | ||
349 | u16 common; | 359 | u16 common; |
350 | u32 version = 0; | 360 | u32 version = 0; |
351 | 361 | ||
352 | /* rdma_cm private data is odd - when there is any private data in the | 362 | /* |
363 | * rdma_cm private data is odd - when there is any private data in the | ||
353 | * request, we will be given a pretty large buffer without telling us the | 364 | * request, we will be given a pretty large buffer without telling us the |
354 | * original size. The only way to tell the difference is by looking at | 365 | * original size. The only way to tell the difference is by looking at |
355 | * the contents, which are initialized to zero. | 366 | * the contents, which are initialized to zero. |
356 | * If the protocol version fields aren't set, this is a connection attempt | 367 | * If the protocol version fields aren't set, this is a connection attempt |
357 | * from an older version. This could could be 3.0 or 2.0 - we can't tell. | 368 | * from an older version. This could could be 3.0 or 2.0 - we can't tell. |
358 | * We really should have changed this for OFED 1.3 :-( */ | 369 | * We really should have changed this for OFED 1.3 :-( |
359 | if (dp->dp_protocol_major == 0) | 370 | */ |
371 | |||
372 | /* Be paranoid. RDS always has privdata */ | ||
373 | if (!event->param.conn.private_data_len) { | ||
374 | printk(KERN_NOTICE "RDS incoming connection has no private data, " | ||
375 | "rejecting\n"); | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | /* Even if len is crap *now* I still want to check it. -ASG */ | ||
380 | if (event->param.conn.private_data_len < sizeof (*dp) | ||
381 | || dp->dp_protocol_major == 0) | ||
360 | return RDS_PROTOCOL_3_0; | 382 | return RDS_PROTOCOL_3_0; |
361 | 383 | ||
362 | common = be16_to_cpu(dp->dp_protocol_minor_mask) & RDS_IB_SUPPORTED_PROTOCOLS; | 384 | common = be16_to_cpu(dp->dp_protocol_minor_mask) & RDS_IB_SUPPORTED_PROTOCOLS; |
@@ -388,7 +410,7 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id, | |||
388 | int err, destroy = 1; | 410 | int err, destroy = 1; |
389 | 411 | ||
390 | /* Check whether the remote protocol version matches ours. */ | 412 | /* Check whether the remote protocol version matches ours. */ |
391 | version = rds_ib_protocol_compatible(dp); | 413 | version = rds_ib_protocol_compatible(event); |
392 | if (!version) | 414 | if (!version) |
393 | goto out; | 415 | goto out; |
394 | 416 | ||