diff options
author | Tatyana Nikolova <Tatyana.E.Nikolova@intel.com> | 2014-03-11 15:17:25 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-03-17 13:03:17 -0400 |
commit | 4ac79a70033cbb9b7fa2bb2f3770308359af8c12 (patch) | |
tree | bfa2f9023e5e270bd3143ad6067d8e1c40cb5ab7 /drivers/infiniband/hw | |
parent | cfbf8d4857c26a8a307fb7cd258074c9dcd8c691 (diff) |
RDMA/nes: Fixes for IRD/ORD negotiation with MPA v2
Fixes to enable the negotiation of the supported IRD/ORD sizes with
the peer when exchanging MPA v2 messages in connection establishment.
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 119 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.h | 3 |
2 files changed, 93 insertions, 29 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 9c9f2f57e960..e852a3a42b9e 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -128,6 +128,7 @@ static void build_mpa_v1(struct nes_cm_node *, void *, u8); | |||
128 | static void build_rdma0_msg(struct nes_cm_node *, struct nes_qp **); | 128 | static void build_rdma0_msg(struct nes_cm_node *, struct nes_qp **); |
129 | 129 | ||
130 | static void print_core(struct nes_cm_core *core); | 130 | static void print_core(struct nes_cm_core *core); |
131 | static void record_ird_ord(struct nes_cm_node *, u16, u16); | ||
131 | 132 | ||
132 | /* External CM API Interface */ | 133 | /* External CM API Interface */ |
133 | /* instance of function pointers for client API */ | 134 | /* instance of function pointers for client API */ |
@@ -317,7 +318,6 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type, | |||
317 | } | 318 | } |
318 | } | 319 | } |
319 | 320 | ||
320 | |||
321 | if (priv_data_len + mpa_hdr_len != len) { | 321 | if (priv_data_len + mpa_hdr_len != len) { |
322 | nes_debug(NES_DBG_CM, "The received ietf buffer was not right" | 322 | nes_debug(NES_DBG_CM, "The received ietf buffer was not right" |
323 | " complete (%x + %x != %x)\n", | 323 | " complete (%x + %x != %x)\n", |
@@ -356,25 +356,57 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type, | |||
356 | /* send reset */ | 356 | /* send reset */ |
357 | return -EINVAL; | 357 | return -EINVAL; |
358 | } | 358 | } |
359 | if (ird_size == IETF_NO_IRD_ORD || ord_size == IETF_NO_IRD_ORD) | ||
360 | cm_node->mpav2_ird_ord = IETF_NO_IRD_ORD; | ||
359 | 361 | ||
360 | if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) { | 362 | if (cm_node->mpav2_ird_ord != IETF_NO_IRD_ORD) { |
361 | /* responder */ | 363 | /* responder */ |
362 | if (cm_node->ord_size > ird_size) | 364 | if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) { |
363 | cm_node->ord_size = ird_size; | 365 | /* we are still negotiating */ |
364 | } else { | 366 | if (ord_size > NES_MAX_IRD) { |
365 | /* initiator */ | 367 | cm_node->ird_size = NES_MAX_IRD; |
366 | if (cm_node->ord_size > ird_size) | 368 | } else { |
367 | cm_node->ord_size = ird_size; | 369 | cm_node->ird_size = ord_size; |
368 | 370 | if (ord_size == 0 && | |
369 | if (cm_node->ird_size < ord_size) { | 371 | (rtr_ctrl_ord & IETF_RDMA0_READ)) { |
370 | /* no resources available */ | 372 | cm_node->ird_size = 1; |
371 | /* send terminate message */ | 373 | nes_debug(NES_DBG_CM, |
372 | return -EINVAL; | 374 | "%s: Remote peer doesn't support RDMA0_READ (ord=%u)\n", |
375 | __func__, ord_size); | ||
376 | } | ||
377 | } | ||
378 | if (ird_size > NES_MAX_ORD) | ||
379 | cm_node->ord_size = NES_MAX_ORD; | ||
380 | else | ||
381 | cm_node->ord_size = ird_size; | ||
382 | } else { /* initiator */ | ||
383 | if (ord_size > NES_MAX_IRD) { | ||
384 | nes_debug(NES_DBG_CM, | ||
385 | "%s: Unable to support the requested (ord =%u)\n", | ||
386 | __func__, ord_size); | ||
387 | return -EINVAL; | ||
388 | } | ||
389 | cm_node->ird_size = ord_size; | ||
390 | |||
391 | if (ird_size > NES_MAX_ORD) { | ||
392 | cm_node->ord_size = NES_MAX_ORD; | ||
393 | } else { | ||
394 | if (ird_size == 0 && | ||
395 | (rtr_ctrl_ord & IETF_RDMA0_READ)) { | ||
396 | nes_debug(NES_DBG_CM, | ||
397 | "%s: Remote peer doesn't support RDMA0_READ (ird=%u)\n", | ||
398 | __func__, ird_size); | ||
399 | return -EINVAL; | ||
400 | } else { | ||
401 | cm_node->ord_size = ird_size; | ||
402 | } | ||
403 | } | ||
373 | } | 404 | } |
374 | } | 405 | } |
375 | 406 | ||
376 | if (rtr_ctrl_ord & IETF_RDMA0_READ) { | 407 | if (rtr_ctrl_ord & IETF_RDMA0_READ) { |
377 | cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO; | 408 | cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO; |
409 | |||
378 | } else if (rtr_ctrl_ord & IETF_RDMA0_WRITE) { | 410 | } else if (rtr_ctrl_ord & IETF_RDMA0_WRITE) { |
379 | cm_node->send_rdma0_op = SEND_RDMA_WRITE_ZERO; | 411 | cm_node->send_rdma0_op = SEND_RDMA_WRITE_ZERO; |
380 | } else { /* Not supported RDMA0 operation */ | 412 | } else { /* Not supported RDMA0 operation */ |
@@ -514,6 +546,19 @@ static void print_core(struct nes_cm_core *core) | |||
514 | nes_debug(NES_DBG_CM, "-------------- end core ---------------\n"); | 546 | nes_debug(NES_DBG_CM, "-------------- end core ---------------\n"); |
515 | } | 547 | } |
516 | 548 | ||
549 | static void record_ird_ord(struct nes_cm_node *cm_node, | ||
550 | u16 conn_ird, u16 conn_ord) | ||
551 | { | ||
552 | if (conn_ird > NES_MAX_IRD) | ||
553 | conn_ird = NES_MAX_IRD; | ||
554 | |||
555 | if (conn_ord > NES_MAX_ORD) | ||
556 | conn_ord = NES_MAX_ORD; | ||
557 | |||
558 | cm_node->ird_size = conn_ird; | ||
559 | cm_node->ord_size = conn_ord; | ||
560 | } | ||
561 | |||
517 | /** | 562 | /** |
518 | * cm_build_mpa_frame - build a MPA V1 frame or MPA V2 frame | 563 | * cm_build_mpa_frame - build a MPA V1 frame or MPA V2 frame |
519 | */ | 564 | */ |
@@ -557,11 +602,13 @@ static void build_mpa_v2(struct nes_cm_node *cm_node, | |||
557 | mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE); | 602 | mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE); |
558 | 603 | ||
559 | /* initialize RTR msg */ | 604 | /* initialize RTR msg */ |
560 | ctrl_ird = (cm_node->ird_size > IETF_NO_IRD_ORD) ? | 605 | if (cm_node->mpav2_ird_ord == IETF_NO_IRD_ORD) { |
561 | IETF_NO_IRD_ORD : cm_node->ird_size; | 606 | ctrl_ird = IETF_NO_IRD_ORD; |
562 | ctrl_ord = (cm_node->ord_size > IETF_NO_IRD_ORD) ? | 607 | ctrl_ord = IETF_NO_IRD_ORD; |
563 | IETF_NO_IRD_ORD : cm_node->ord_size; | 608 | } else { |
564 | 609 | ctrl_ird = cm_node->ird_size & IETF_NO_IRD_ORD; | |
610 | ctrl_ord = cm_node->ord_size & IETF_NO_IRD_ORD; | ||
611 | } | ||
565 | ctrl_ird |= IETF_PEER_TO_PEER; | 612 | ctrl_ird |= IETF_PEER_TO_PEER; |
566 | ctrl_ird |= IETF_FLPDU_ZERO_LEN; | 613 | ctrl_ird |= IETF_FLPDU_ZERO_LEN; |
567 | 614 | ||
@@ -1409,8 +1456,9 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
1409 | 1456 | ||
1410 | cm_node->mpa_frame_rev = mpa_version; | 1457 | cm_node->mpa_frame_rev = mpa_version; |
1411 | cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO; | 1458 | cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO; |
1412 | cm_node->ird_size = IETF_NO_IRD_ORD; | 1459 | cm_node->mpav2_ird_ord = 0; |
1413 | cm_node->ord_size = IETF_NO_IRD_ORD; | 1460 | cm_node->ird_size = 0; |
1461 | cm_node->ord_size = 0; | ||
1414 | 1462 | ||
1415 | nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n", | 1463 | nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n", |
1416 | &cm_node->loc_addr, cm_node->loc_port, | 1464 | &cm_node->loc_addr, cm_node->loc_port, |
@@ -3027,11 +3075,11 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3027 | rem_ref_cm_node(cm_node->cm_core, cm_node); | 3075 | rem_ref_cm_node(cm_node->cm_core, cm_node); |
3028 | return -ECONNRESET; | 3076 | return -ECONNRESET; |
3029 | } | 3077 | } |
3030 | |||
3031 | /* associate the node with the QP */ | 3078 | /* associate the node with the QP */ |
3032 | nesqp->cm_node = (void *)cm_node; | 3079 | nesqp->cm_node = (void *)cm_node; |
3033 | cm_node->nesqp = nesqp; | 3080 | cm_node->nesqp = nesqp; |
3034 | 3081 | ||
3082 | |||
3035 | nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu listener = %p\n", | 3083 | nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu listener = %p\n", |
3036 | nesqp->hwqp.qp_id, cm_node, jiffies, cm_node->listener); | 3084 | nesqp->hwqp.qp_id, cm_node, jiffies, cm_node->listener); |
3037 | atomic_inc(&cm_accepts); | 3085 | atomic_inc(&cm_accepts); |
@@ -3054,6 +3102,11 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3054 | if (cm_node->mpa_frame_rev == IETF_MPA_V1) | 3102 | if (cm_node->mpa_frame_rev == IETF_MPA_V1) |
3055 | mpa_frame_offset = 4; | 3103 | mpa_frame_offset = 4; |
3056 | 3104 | ||
3105 | if (cm_node->mpa_frame_rev == IETF_MPA_V1 || | ||
3106 | cm_node->mpav2_ird_ord == IETF_NO_IRD_ORD) { | ||
3107 | record_ird_ord(cm_node, (u16)conn_param->ird, (u16)conn_param->ord); | ||
3108 | } | ||
3109 | |||
3057 | memcpy(mpa_v2_frame->priv_data, conn_param->private_data, | 3110 | memcpy(mpa_v2_frame->priv_data, conn_param->private_data, |
3058 | conn_param->private_data_len); | 3111 | conn_param->private_data_len); |
3059 | 3112 | ||
@@ -3117,7 +3170,6 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3117 | } | 3170 | } |
3118 | nesqp->skip_lsmm = 1; | 3171 | nesqp->skip_lsmm = 1; |
3119 | 3172 | ||
3120 | |||
3121 | /* Cache the cm_id in the qp */ | 3173 | /* Cache the cm_id in the qp */ |
3122 | nesqp->cm_id = cm_id; | 3174 | nesqp->cm_id = cm_id; |
3123 | cm_node->cm_id = cm_id; | 3175 | cm_node->cm_id = cm_id; |
@@ -3154,7 +3206,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3154 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32( | 3206 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32( |
3155 | ((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT)); | 3207 | ((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT)); |
3156 | nesqp->nesqp_context->ird_ord_sizes |= | 3208 | nesqp->nesqp_context->ird_ord_sizes |= |
3157 | cpu_to_le32((u32)conn_param->ord); | 3209 | cpu_to_le32((u32)cm_node->ord_size); |
3158 | 3210 | ||
3159 | memset(&nes_quad, 0, sizeof(nes_quad)); | 3211 | memset(&nes_quad, 0, sizeof(nes_quad)); |
3160 | nes_quad.DstIpAdrIndex = | 3212 | nes_quad.DstIpAdrIndex = |
@@ -3194,6 +3246,9 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3194 | cm_event.remote_addr = cm_id->remote_addr; | 3246 | cm_event.remote_addr = cm_id->remote_addr; |
3195 | cm_event.private_data = NULL; | 3247 | cm_event.private_data = NULL; |
3196 | cm_event.private_data_len = 0; | 3248 | cm_event.private_data_len = 0; |
3249 | cm_event.ird = cm_node->ird_size; | ||
3250 | cm_event.ord = cm_node->ord_size; | ||
3251 | |||
3197 | ret = cm_id->event_handler(cm_id, &cm_event); | 3252 | ret = cm_id->event_handler(cm_id, &cm_event); |
3198 | attr.qp_state = IB_QPS_RTS; | 3253 | attr.qp_state = IB_QPS_RTS; |
3199 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); | 3254 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); |
@@ -3290,14 +3345,8 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3290 | 3345 | ||
3291 | /* cache the cm_id in the qp */ | 3346 | /* cache the cm_id in the qp */ |
3292 | nesqp->cm_id = cm_id; | 3347 | nesqp->cm_id = cm_id; |
3293 | |||
3294 | cm_id->provider_data = nesqp; | 3348 | cm_id->provider_data = nesqp; |
3295 | |||
3296 | nesqp->private_data_len = conn_param->private_data_len; | 3349 | nesqp->private_data_len = conn_param->private_data_len; |
3297 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord); | ||
3298 | /* space for rdma0 read msg */ | ||
3299 | if (conn_param->ord == 0) | ||
3300 | nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(1); | ||
3301 | 3350 | ||
3302 | nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord); | 3351 | nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord); |
3303 | nes_debug(NES_DBG_CM, "mpa private data len =%u\n", | 3352 | nes_debug(NES_DBG_CM, "mpa private data len =%u\n", |
@@ -3334,6 +3383,11 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
3334 | return -ENOMEM; | 3383 | return -ENOMEM; |
3335 | } | 3384 | } |
3336 | 3385 | ||
3386 | record_ird_ord(cm_node, (u16)conn_param->ird, (u16)conn_param->ord); | ||
3387 | if (cm_node->send_rdma0_op == SEND_RDMA_READ_ZERO && | ||
3388 | cm_node->ord_size == 0) | ||
3389 | cm_node->ord_size = 1; | ||
3390 | |||
3337 | cm_node->apbvt_set = apbvt_set; | 3391 | cm_node->apbvt_set = apbvt_set; |
3338 | nesqp->cm_node = cm_node; | 3392 | nesqp->cm_node = cm_node; |
3339 | cm_node->nesqp = nesqp; | 3393 | cm_node->nesqp = nesqp; |
@@ -3530,6 +3584,8 @@ static void cm_event_connected(struct nes_cm_event *event) | |||
3530 | nesqp->nesqp_context->ird_ord_sizes |= | 3584 | nesqp->nesqp_context->ird_ord_sizes |= |
3531 | cpu_to_le32((u32)1 << | 3585 | cpu_to_le32((u32)1 << |
3532 | NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT); | 3586 | NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT); |
3587 | nesqp->nesqp_context->ird_ord_sizes |= | ||
3588 | cpu_to_le32((u32)cm_node->ord_size); | ||
3533 | 3589 | ||
3534 | /* Adjust tail for not having a LSMM */ | 3590 | /* Adjust tail for not having a LSMM */ |
3535 | /*nesqp->hwqp.sq_tail = 1;*/ | 3591 | /*nesqp->hwqp.sq_tail = 1;*/ |
@@ -3742,8 +3798,13 @@ static void cm_event_mpa_req(struct nes_cm_event *event) | |||
3742 | cm_event_raddr->sin_addr.s_addr = htonl(event->cm_info.rem_addr); | 3798 | cm_event_raddr->sin_addr.s_addr = htonl(event->cm_info.rem_addr); |
3743 | cm_event.private_data = cm_node->mpa_frame_buf; | 3799 | cm_event.private_data = cm_node->mpa_frame_buf; |
3744 | cm_event.private_data_len = (u8)cm_node->mpa_frame_size; | 3800 | cm_event.private_data_len = (u8)cm_node->mpa_frame_size; |
3801 | if (cm_node->mpa_frame_rev == IETF_MPA_V1) { | ||
3802 | cm_event.ird = NES_MAX_IRD; | ||
3803 | cm_event.ord = NES_MAX_ORD; | ||
3804 | } else { | ||
3745 | cm_event.ird = cm_node->ird_size; | 3805 | cm_event.ird = cm_node->ird_size; |
3746 | cm_event.ord = cm_node->ord_size; | 3806 | cm_event.ord = cm_node->ord_size; |
3807 | } | ||
3747 | 3808 | ||
3748 | ret = cm_id->event_handler(cm_id, &cm_event); | 3809 | ret = cm_id->event_handler(cm_id, &cm_event); |
3749 | if (ret) | 3810 | if (ret) |
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index 4646e6666087..522c99cd07c4 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h | |||
@@ -58,6 +58,8 @@ | |||
58 | #define IETF_RDMA0_WRITE 0x8000 | 58 | #define IETF_RDMA0_WRITE 0x8000 |
59 | #define IETF_RDMA0_READ 0x4000 | 59 | #define IETF_RDMA0_READ 0x4000 |
60 | #define IETF_NO_IRD_ORD 0x3FFF | 60 | #define IETF_NO_IRD_ORD 0x3FFF |
61 | #define NES_MAX_IRD 0x40 | ||
62 | #define NES_MAX_ORD 0x7F | ||
61 | 63 | ||
62 | enum ietf_mpa_flags { | 64 | enum ietf_mpa_flags { |
63 | IETF_MPA_FLAGS_MARKERS = 0x80, /* receive Markers */ | 65 | IETF_MPA_FLAGS_MARKERS = 0x80, /* receive Markers */ |
@@ -333,6 +335,7 @@ struct nes_cm_node { | |||
333 | enum mpa_frame_version mpa_frame_rev; | 335 | enum mpa_frame_version mpa_frame_rev; |
334 | u16 ird_size; | 336 | u16 ird_size; |
335 | u16 ord_size; | 337 | u16 ord_size; |
338 | u16 mpav2_ird_ord; | ||
336 | 339 | ||
337 | u16 mpa_frame_size; | 340 | u16 mpa_frame_size; |
338 | struct iw_cm_id *cm_id; | 341 | struct iw_cm_id *cm_id; |