diff options
Diffstat (limited to 'net/rds/ib_cm.c')
-rw-r--r-- | net/rds/ib_cm.c | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index da5a7fb98c77..310cabce2311 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
@@ -194,7 +194,7 @@ static void rds_ib_cm_fill_conn_param(struct rds_connection *conn, | |||
194 | dp->dp_protocol_major = RDS_PROTOCOL_MAJOR(protocol_version); | 194 | dp->dp_protocol_major = RDS_PROTOCOL_MAJOR(protocol_version); |
195 | dp->dp_protocol_minor = RDS_PROTOCOL_MINOR(protocol_version); | 195 | dp->dp_protocol_minor = RDS_PROTOCOL_MINOR(protocol_version); |
196 | dp->dp_protocol_minor_mask = cpu_to_be16(RDS_IB_SUPPORTED_PROTOCOLS); | 196 | dp->dp_protocol_minor_mask = cpu_to_be16(RDS_IB_SUPPORTED_PROTOCOLS); |
197 | dp->dp_ack_seq = rds_ib_piggyb_ack(ic); | 197 | dp->dp_ack_seq = cpu_to_be64(rds_ib_piggyb_ack(ic)); |
198 | 198 | ||
199 | /* Advertise flow control */ | 199 | /* Advertise flow control */ |
200 | if (ic->i_flowctl) { | 200 | if (ic->i_flowctl) { |
@@ -236,12 +236,10 @@ static void rds_ib_cq_comp_handler_recv(struct ib_cq *cq, void *context) | |||
236 | tasklet_schedule(&ic->i_recv_tasklet); | 236 | tasklet_schedule(&ic->i_recv_tasklet); |
237 | } | 237 | } |
238 | 238 | ||
239 | static void poll_cq(struct rds_ib_connection *ic, struct ib_cq *cq, | 239 | static void poll_scq(struct rds_ib_connection *ic, struct ib_cq *cq, |
240 | struct ib_wc *wcs, | 240 | struct ib_wc *wcs) |
241 | struct rds_ib_ack_state *ack_state) | ||
242 | { | 241 | { |
243 | int nr; | 242 | int nr, i; |
244 | int i; | ||
245 | struct ib_wc *wc; | 243 | struct ib_wc *wc; |
246 | 244 | ||
247 | while ((nr = ib_poll_cq(cq, RDS_IB_WC_MAX, wcs)) > 0) { | 245 | while ((nr = ib_poll_cq(cq, RDS_IB_WC_MAX, wcs)) > 0) { |
@@ -251,10 +249,12 @@ static void poll_cq(struct rds_ib_connection *ic, struct ib_cq *cq, | |||
251 | (unsigned long long)wc->wr_id, wc->status, | 249 | (unsigned long long)wc->wr_id, wc->status, |
252 | wc->byte_len, be32_to_cpu(wc->ex.imm_data)); | 250 | wc->byte_len, be32_to_cpu(wc->ex.imm_data)); |
253 | 251 | ||
254 | if (wc->wr_id & RDS_IB_SEND_OP) | 252 | if (wc->wr_id <= ic->i_send_ring.w_nr || |
253 | wc->wr_id == RDS_IB_ACK_WR_ID) | ||
255 | rds_ib_send_cqe_handler(ic, wc); | 254 | rds_ib_send_cqe_handler(ic, wc); |
256 | else | 255 | else |
257 | rds_ib_recv_cqe_handler(ic, wc, ack_state); | 256 | rds_ib_mr_cqe_handler(ic, wc); |
257 | |||
258 | } | 258 | } |
259 | } | 259 | } |
260 | } | 260 | } |
@@ -263,14 +263,12 @@ static void rds_ib_tasklet_fn_send(unsigned long data) | |||
263 | { | 263 | { |
264 | struct rds_ib_connection *ic = (struct rds_ib_connection *)data; | 264 | struct rds_ib_connection *ic = (struct rds_ib_connection *)data; |
265 | struct rds_connection *conn = ic->conn; | 265 | struct rds_connection *conn = ic->conn; |
266 | struct rds_ib_ack_state state; | ||
267 | 266 | ||
268 | rds_ib_stats_inc(s_ib_tasklet_call); | 267 | rds_ib_stats_inc(s_ib_tasklet_call); |
269 | 268 | ||
270 | memset(&state, 0, sizeof(state)); | 269 | poll_scq(ic, ic->i_send_cq, ic->i_send_wc); |
271 | poll_cq(ic, ic->i_send_cq, ic->i_send_wc, &state); | ||
272 | ib_req_notify_cq(ic->i_send_cq, IB_CQ_NEXT_COMP); | 270 | ib_req_notify_cq(ic->i_send_cq, IB_CQ_NEXT_COMP); |
273 | poll_cq(ic, ic->i_send_cq, ic->i_send_wc, &state); | 271 | poll_scq(ic, ic->i_send_cq, ic->i_send_wc); |
274 | 272 | ||
275 | if (rds_conn_up(conn) && | 273 | if (rds_conn_up(conn) && |
276 | (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags) || | 274 | (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags) || |
@@ -278,6 +276,25 @@ static void rds_ib_tasklet_fn_send(unsigned long data) | |||
278 | rds_send_xmit(ic->conn); | 276 | rds_send_xmit(ic->conn); |
279 | } | 277 | } |
280 | 278 | ||
279 | static void poll_rcq(struct rds_ib_connection *ic, struct ib_cq *cq, | ||
280 | struct ib_wc *wcs, | ||
281 | struct rds_ib_ack_state *ack_state) | ||
282 | { | ||
283 | int nr, i; | ||
284 | struct ib_wc *wc; | ||
285 | |||
286 | while ((nr = ib_poll_cq(cq, RDS_IB_WC_MAX, wcs)) > 0) { | ||
287 | for (i = 0; i < nr; i++) { | ||
288 | wc = wcs + i; | ||
289 | rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n", | ||
290 | (unsigned long long)wc->wr_id, wc->status, | ||
291 | wc->byte_len, be32_to_cpu(wc->ex.imm_data)); | ||
292 | |||
293 | rds_ib_recv_cqe_handler(ic, wc, ack_state); | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | |||
281 | static void rds_ib_tasklet_fn_recv(unsigned long data) | 298 | static void rds_ib_tasklet_fn_recv(unsigned long data) |
282 | { | 299 | { |
283 | struct rds_ib_connection *ic = (struct rds_ib_connection *)data; | 300 | struct rds_ib_connection *ic = (struct rds_ib_connection *)data; |
@@ -291,9 +308,9 @@ static void rds_ib_tasklet_fn_recv(unsigned long data) | |||
291 | rds_ib_stats_inc(s_ib_tasklet_call); | 308 | rds_ib_stats_inc(s_ib_tasklet_call); |
292 | 309 | ||
293 | memset(&state, 0, sizeof(state)); | 310 | memset(&state, 0, sizeof(state)); |
294 | poll_cq(ic, ic->i_recv_cq, ic->i_recv_wc, &state); | 311 | poll_rcq(ic, ic->i_recv_cq, ic->i_recv_wc, &state); |
295 | ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED); | 312 | ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED); |
296 | poll_cq(ic, ic->i_recv_cq, ic->i_recv_wc, &state); | 313 | poll_rcq(ic, ic->i_recv_cq, ic->i_recv_wc, &state); |
297 | 314 | ||
298 | if (state.ack_next_valid) | 315 | if (state.ack_next_valid) |
299 | rds_ib_set_ack(ic, state.ack_next, state.ack_required); | 316 | rds_ib_set_ack(ic, state.ack_next, state.ack_required); |
@@ -351,7 +368,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) | |||
351 | struct ib_qp_init_attr attr; | 368 | struct ib_qp_init_attr attr; |
352 | struct ib_cq_init_attr cq_attr = {}; | 369 | struct ib_cq_init_attr cq_attr = {}; |
353 | struct rds_ib_device *rds_ibdev; | 370 | struct rds_ib_device *rds_ibdev; |
354 | int ret; | 371 | int ret, fr_queue_space; |
355 | 372 | ||
356 | /* | 373 | /* |
357 | * It's normal to see a null device if an incoming connection races | 374 | * It's normal to see a null device if an incoming connection races |
@@ -361,6 +378,12 @@ static int rds_ib_setup_qp(struct rds_connection *conn) | |||
361 | if (!rds_ibdev) | 378 | if (!rds_ibdev) |
362 | return -EOPNOTSUPP; | 379 | return -EOPNOTSUPP; |
363 | 380 | ||
381 | /* The fr_queue_space is currently set to 512, to add extra space on | ||
382 | * completion queue and send queue. This extra space is used for FRMR | ||
383 | * registration and invalidation work requests | ||
384 | */ | ||
385 | fr_queue_space = (rds_ibdev->use_fastreg ? RDS_IB_DEFAULT_FR_WR : 0); | ||
386 | |||
364 | /* add the conn now so that connection establishment has the dev */ | 387 | /* add the conn now so that connection establishment has the dev */ |
365 | rds_ib_add_conn(rds_ibdev, conn); | 388 | rds_ib_add_conn(rds_ibdev, conn); |
366 | 389 | ||
@@ -372,7 +395,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) | |||
372 | /* Protection domain and memory range */ | 395 | /* Protection domain and memory range */ |
373 | ic->i_pd = rds_ibdev->pd; | 396 | ic->i_pd = rds_ibdev->pd; |
374 | 397 | ||
375 | cq_attr.cqe = ic->i_send_ring.w_nr + 1; | 398 | cq_attr.cqe = ic->i_send_ring.w_nr + fr_queue_space + 1; |
376 | 399 | ||
377 | ic->i_send_cq = ib_create_cq(dev, rds_ib_cq_comp_handler_send, | 400 | ic->i_send_cq = ib_create_cq(dev, rds_ib_cq_comp_handler_send, |
378 | rds_ib_cq_event_handler, conn, | 401 | rds_ib_cq_event_handler, conn, |
@@ -412,7 +435,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) | |||
412 | attr.event_handler = rds_ib_qp_event_handler; | 435 | attr.event_handler = rds_ib_qp_event_handler; |
413 | attr.qp_context = conn; | 436 | attr.qp_context = conn; |
414 | /* + 1 to allow for the single ack message */ | 437 | /* + 1 to allow for the single ack message */ |
415 | attr.cap.max_send_wr = ic->i_send_ring.w_nr + 1; | 438 | attr.cap.max_send_wr = ic->i_send_ring.w_nr + fr_queue_space + 1; |
416 | attr.cap.max_recv_wr = ic->i_recv_ring.w_nr + 1; | 439 | attr.cap.max_recv_wr = ic->i_recv_ring.w_nr + 1; |
417 | attr.cap.max_send_sge = rds_ibdev->max_sge; | 440 | attr.cap.max_send_sge = rds_ibdev->max_sge; |
418 | attr.cap.max_recv_sge = RDS_IB_RECV_SGE; | 441 | attr.cap.max_recv_sge = RDS_IB_RECV_SGE; |
@@ -420,6 +443,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) | |||
420 | attr.qp_type = IB_QPT_RC; | 443 | attr.qp_type = IB_QPT_RC; |
421 | attr.send_cq = ic->i_send_cq; | 444 | attr.send_cq = ic->i_send_cq; |
422 | attr.recv_cq = ic->i_recv_cq; | 445 | attr.recv_cq = ic->i_recv_cq; |
446 | atomic_set(&ic->i_fastreg_wrs, RDS_IB_DEFAULT_FR_WR); | ||
423 | 447 | ||
424 | /* | 448 | /* |
425 | * XXX this can fail if max_*_wr is too large? Are we supposed | 449 | * XXX this can fail if max_*_wr is too large? Are we supposed |
@@ -739,7 +763,8 @@ void rds_ib_conn_shutdown(struct rds_connection *conn) | |||
739 | */ | 763 | */ |
740 | wait_event(rds_ib_ring_empty_wait, | 764 | wait_event(rds_ib_ring_empty_wait, |
741 | rds_ib_ring_empty(&ic->i_recv_ring) && | 765 | rds_ib_ring_empty(&ic->i_recv_ring) && |
742 | (atomic_read(&ic->i_signaled_sends) == 0)); | 766 | (atomic_read(&ic->i_signaled_sends) == 0) && |
767 | (atomic_read(&ic->i_fastreg_wrs) == RDS_IB_DEFAULT_FR_WR)); | ||
743 | tasklet_kill(&ic->i_send_tasklet); | 768 | tasklet_kill(&ic->i_send_tasklet); |
744 | tasklet_kill(&ic->i_recv_tasklet); | 769 | tasklet_kill(&ic->i_recv_tasklet); |
745 | 770 | ||