467 int ibcm_recv_tasks = 0;
468 int ibcm_max_recv_tasks = 24;
469 int ibcm_recv_timeouts = 0;
470
471 /*
472 * Tunable MAX MRA Service Timeout value in MicroSECONDS.
473 * 0 - Tunable parameter not used.
474 *
475 * Ex: 60000000 - Max MRA Service Delay is 60 Seconds.
476 */
477 clock_t ibcm_mra_service_timeout_max = 0;
478
479 #ifdef DEBUG
480
481 static void print_modify_qp(char *prefix,
482 ibt_qp_hdl_t ibt_qp,
483 ibt_cep_modify_flags_t flags,
484 ibt_qp_info_t *qp_attr);
485 #endif
486
487 /* Warlock annotations */
488
489 _NOTE(READ_ONLY_DATA(ibt_arej_info_u))
490
491 /*
492 * ibcm_process_incoming_mad:
493 * The CM callback that is invoked by IBMF, when a valid CM MAD arrives
494 * on any of the registered ibmf handles by CM.
495 *
496 * It is assumed that the incoming MAD (except for incoming REQ) belongs
497 * to a connection on the HCA, on which the MAD is received.
498 * The IBMF callback arg specifies ibcm_hca_info_t
499 *
500 * NOTE: IBMF always invokes ibcm_recv_cb() in a taskq. CM does some memory
501 * allocations and invoke ibcm_sm_funcs_tbl[i]() in the same taskq.
502 *
503 * INPUTS:
504 * ibmf_handle - IBMF Handle
505 * args - from IBMF. Is a ptr to ibcm_hca_info_t
506 * status - Callback status. Is mostly IBMF_SUCCESS
507 * madbuf - IBMF allocated MAD buffer (CM should free it)
508 * madaddr - IBMF MAD's address
509 * grhvalid - If GRH is valid or not
510 *
549 #endif
550
551 portp = cm_qp_entry->qp_port;
552 hcap = portp->port_hcap;
553
554 IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: CM MAD on "
555 "port %d", portp->port_num);
556
557 /* Increment hca ref cnt, if HCA is in attached state, else fail */
558 if (ibcm_inc_hca_acc_cnt(hcap) != IBCM_SUCCESS) {
559 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
560 "hca not in attach state");
561 /* IBMF allocates Input MAD, and ibcm free's it */
562 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
563 IBMF_SUCCESS)
564 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
565 "ibmf_free_msg failed %d", ibmf_status);
566 return;
567 }
568
569 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cm_mad_addr))
570
571 /* allocate memory for internal MAD address buffer */
572 cm_mad_addr = &loc_mad_addr;
573 bzero(cm_mad_addr, sizeof (ibcm_mad_addr_t));
574
575 cm_mad_addr->port_num = portp->port_num;
576
577 /* initialize cm_mad_addr field(s) */
578 in_mad_hdr = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
579
580 if (in_mad_hdr->MgmtClass != MAD_MGMT_CLASS_COMM_MGT) {
581 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
582 "bad mgmt class %x", in_mad_hdr->MgmtClass);
583 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
584 IBMF_SUCCESS)
585 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
586 "ibmf_free_msg failed %d", ibmf_status);
587 ibcm_dec_hca_acc_cnt(hcap);
588 return;
589 }
590
629
630 if (attr_id == (IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID))
631 ibcm_post_rej_ver_mismatch(
632 (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
633
634 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
635 IBMF_SUCCESS)
636 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
637 "ibmf_free_msg failed %d", ibmf_status);
638 ibcm_dec_hca_acc_cnt(hcap);
639 return;
640 }
641
642 IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: "
643 "Transaction Id 0x%llX", b2h64(in_mad_hdr->TransactionID));
644
645 #ifdef DEBUG
646 ibcm_decode_tranid(b2h64(in_mad_hdr->TransactionID), NULL);
647 #endif
648
649 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cm_mad_addr))
650
651 /*
652 * The following are valid combination of Method type
653 * and attribute id in the received MAD :-
654 * o ClassPortInfo with Get method
655 * o CM messages with Send method
656 */
657 if ((attr_id == MAD_ATTR_ID_CLASSPORTINFO) &&
658 ((method == MAD_METHOD_GET) ||
659 (method == MAD_METHOD_GET_RESPONSE))) {
660 if (method == MAD_METHOD_GET)
661 ibcm_process_get_classport_info(hcap,
662 (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
663 else if (method == MAD_METHOD_GET_RESPONSE)
664 ibcm_decode_classport_info(hcap,
665 (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
666 } else if ((attr_id >= IBCM_ATTR_BASE_ID) &&
667 (attr_id < (IBCM_ATTR_BASE_ID + IBCM_MAX_EVENTS)) &&
668 (method == MAD_METHOD_SEND)) {
669
670 attr_id -= IBCM_ATTR_BASE_ID; /* figure out CM message id */
693 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
694 "ibmf_free_msg failed %d", ibmf_status);
695 }
696
697 /*
698 * Structure to carry the arguments from ibcm_recv_cb() to
699 * ibcm_recv_incoming_mad() via taskq_dispatch
700 */
701 typedef struct ibcm_taskq_args_s {
702 ibmf_handle_t tq_ibmf_handle;
703 ibmf_msg_t *tq_ibmf_msgp;
704 void *tq_args;
705 } ibcm_taskq_args_t;
706
707 #define IBCM_RECV_MAX 128
708 ibcm_taskq_args_t ibcm_recv_array[IBCM_RECV_MAX + 1];
709 int ibcm_get, ibcm_put;
710 int ibcm_recv_total;
711 int ibcm_recv_queued;
712
713 _NOTE(READ_ONLY_DATA(ibcm_taskq_args_t))
714
715 static int
716 ibcm_recv_dequeue(ibmf_handle_t *ibmf_handlep, ibmf_msg_t **msgpp, void **argsp)
717 {
718 ibcm_taskq_args_t *tq;
719
720 if (ibcm_put == ibcm_get)
721 return (0);
722
723 if (++ibcm_get >= IBCM_RECV_MAX)
724 ibcm_get = 0;
725 tq = ibcm_recv_array + ibcm_get;
726 *ibmf_handlep = tq->tq_ibmf_handle;
727 *msgpp = tq->tq_ibmf_msgp;
728 *argsp = tq->tq_args;
729 return (1);
730 }
731
732 static int
733 ibcm_recv_enqueue(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
734 {
735 int next;
736 ibcm_taskq_args_t *tq;
737
738 ASSERT(MUTEX_HELD(&ibcm_recv_mutex));
739 next = ibcm_put + 1;
740 if (next >= IBCM_RECV_MAX)
741 next = 0;
742 if (next != ibcm_get) {
743 ibcm_recv_queued++;
744 ibcm_put = next;
745 tq = ibcm_recv_array + next;
746 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tq))
747 tq->tq_ibmf_handle = ibmf_handle;
748 tq->tq_ibmf_msgp = msgp;
749 tq->tq_args = args;
750 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*tq))
751 return (1);
752 } else {
753 return (0);
754 }
755 }
756
757 void
758 ibcm_drop_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp)
759 {
760 int ibmf_status;
761
762 IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: discarding MAD");
763
764 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) != IBMF_SUCCESS)
765 IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: "
766 "ibmf_free_msg failed %d", ibmf_status);
767 }
768
769 /*
770 * Processing done in taskq thread.
850
851 mutex_enter(&ibcm_recv_mutex);
852 ibcm_recv_total++;
853 if (ibcm_recv_tasks >= ibcm_max_recv_tasks) { /* just queue this one */
854 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
855 mutex_exit(&ibcm_recv_mutex);
856 return (rv);
857 } else {
858 ibcm_recv_tasks++; /* dispatch this one to a taskq thread */
859 mutex_exit(&ibcm_recv_mutex);
860 tq = kmem_alloc(sizeof (*tq), KM_NOSLEEP);
861 if (tq == NULL) {
862 mutex_enter(&ibcm_recv_mutex);
863 if (--ibcm_recv_tasks > 0)
864 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
865 else /* don't enqueue if no threads are running */
866 rv = 0;
867 mutex_exit(&ibcm_recv_mutex);
868 return (rv);
869 }
870 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tq))
871 tq->tq_ibmf_handle = ibmf_handle;
872 tq->tq_ibmf_msgp = msgp;
873 tq->tq_args = args;
874 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*tq))
875 if (taskq_dispatch(ibcm_taskq, ibcm_recv_task, tq,
876 TQ_NOQUEUE | TQ_NOSLEEP) == 0) { /* dispatch failed */
877 mutex_enter(&ibcm_recv_mutex);
878 if (--ibcm_recv_tasks == 0) {
879 /* try the dispatch again, after a tick */
880 (void) timeout(ibcm_recv_timeout_cb, tq, 1);
881 ibcm_recv_timeouts++;
882 rv = 1; /* indicate success */
883 } else {
884 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
885 kmem_free(tq, sizeof (*tq));
886 }
887 mutex_exit(&ibcm_recv_mutex);
888 return (rv);
889 } else {
890 return (1);
891 }
892 }
893 }
894
963 hcap, input_madp, cm_mad_addr);
964
965 /*
966 * Lookup for an existing state structure or create a new state struct
967 * If there is no entry, the lookup function also allocates a new
968 * state structure and inserts in the table, initializes remote qpn
969 * and hca guid from REQ
970 */
971 remote_hca_guid = b2h64(req_msgp->req_local_ca_guid);
972 remote_qpn = b2h32(req_msgp->req_local_qpn_plus) >> 8;
973 remote_comid = b2h32(req_msgp->req_local_comm_id);
974
975 IBCM_DUMP_RAW_MSG((uchar_t *)input_madp);
976
977 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_comid = %x"
978 " remote_qpn = %x", remote_comid, remote_qpn);
979
980 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_hcaguid = %llX",
981 remote_hca_guid);
982
983 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
984
985 new_req:
986 /* allocate the local_comid before proceeding */
987 if (ibcm_alloc_comid(hcap, &local_comid) != IBCM_SUCCESS) {
988 ibcm_build_n_post_rej_mad(input_madp,
989 b2h32(req_msgp->req_local_comm_id), cm_mad_addr,
990 IBT_CM_FAILURE_REQ, IBT_CM_NO_RESC);
991 return;
992 }
993
994 /* allocate ibcm_state_data_t before grabbing the WRITER lock */
995 statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
996
997 rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
998
999 /* NOTE that only a writer lock is held here */
1000
1001 state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REQ,
1002 local_comid, remote_qpn, remote_hca_guid, hcap, &statep);
1003
1004 if (state_lookup_status == IBCM_LOOKUP_NEW) {
1005 /* seeing the REQ request for the first time */
1006
1007 mutex_enter(&statep->state_mutex);
1008 /* Release the state table lock */
1009 rw_exit(&hcap->hca_state_rwlock);
1010
1011 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: New statep 0x%p"
1012 " created", statep);
1013
1014 psn24_timeout5_retry3 = b2h32(req_msgp->req_starting_psn_plus);
1015
1016 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1017
1018 /* if ibmf msg allocation fails, delete the statep */
1019 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1020 &statep->stored_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1021
1022 IBCM_REF_CNT_DECR(statep);
1023 statep->state = IBCM_STATE_DELETE;
1024 mutex_exit(&statep->state_mutex);
1025 /* HCA res cnt decremented via ibcm_delete_state_data */
1026 ibcm_inc_hca_res_cnt(hcap);
1027 ibcm_delete_state_data(statep);
1028 return;
1029 }
1030
1031 /* Allocate dreq_msg buf to be used during teardown. */
1032 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1033 &statep->dreq_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1034
1035 IBCM_REF_CNT_DECR(statep);
1036 statep->state = IBCM_STATE_DELETE;
1037 mutex_exit(&statep->state_mutex);
1236 /* REJ posted from ibcm_verify_req_gids_and_svcid */
1237 return;
1238 }
1239
1240 /* Call the QP state transition processing function */
1241 response = ibcm_cep_state_req(statep, req_msgp,
1242 &reject_reason, &arej_info_len);
1243
1244 /* If defer, return holding the statep ref cnt */
1245 if (response == IBCM_DEFER) {
1246 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1247 "statep %0xp client returned DEFER response",
1248 statep);
1249 return;
1250 }
1251
1252 /* statep ref cnt decremented in the func below */
1253 ibcm_handle_cep_req_response(statep, response,
1254 reject_reason, arej_info_len);
1255
1256 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1257
1258 return;
1259
1260 } else {
1261 rw_exit(&hcap->hca_state_rwlock);
1262 ibcm_free_comid(hcap, local_comid);
1263 }
1264
1265 if (state_lookup_status == IBCM_LOOKUP_EXISTS) {
1266 hrtime_t cur_time;
1267
1268 mutex_enter(&statep->state_mutex);
1269
1270 /*
1271 * There is an existing state structure entry
1272 * with the same active comid
1273 * Resending REP MAD is necessary only for REP/REJ/MRA Sent
1274 * states
1275 * Any other state implies the active has already received
1276 * the REP/REJ response, and this REQ is an old MAD popping
1277 * out of the fabric, hence no resend is required
1378 ibcm_build_n_post_rej_mad(input_madp,
1379 b2h32(req_msgp->req_local_comm_id),
1380 cm_mad_addr, IBT_CM_FAILURE_REQ, IBT_CM_CONN_STALE);
1381
1382 mutex_enter(&statep->state_mutex);
1383 }
1384 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
1385 mutex_exit(&statep->state_mutex);
1386 }
1387 }
1388
1389 /*
1390 * ibcm_handle_cep_req_response:
1391 * Processes the response from ibcm_cep_state_req. Called holding a
1392 * statep ref cnt. The statep ref cnt is decremented before returning.
1393 */
1394 void
1395 ibcm_handle_cep_req_response(ibcm_state_data_t *statep, ibcm_status_t response,
1396 ibt_cm_reason_t reject_reason, uint8_t arej_info_len)
1397 {
1398 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1399
1400 if (response == IBCM_SEND_REP)
1401 ibcm_post_rep_mad(statep);
1402 else {
1403 ASSERT(response == IBCM_SEND_REJ);
1404 IBTF_DPRINTF_L4(cmlog, "ibcm_handle_cep_req_response: statep %p"
1405 " posting REJ reject_reason = %d", statep, reject_reason);
1406
1407 ibcm_post_rej_mad(statep,
1408 reject_reason, IBT_CM_FAILURE_REQ,
1409 NULL, arej_info_len);
1410 }
1411
1412 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1413
1414 mutex_enter(&statep->state_mutex);
1415 IBCM_REF_CNT_DECR(statep);
1416 mutex_exit(&statep->state_mutex);
1417 }
1418
1419
1420 /*
1421 * ibcm_process_rep_msg:
1422 * ACTIVE SIDE CM
1423 * Called from ibcm_process_incoming_mad on reception of a REP message
1424 *
1425 * INPUTS:
1426 * hcap - HCA entry pointer
1427 * input_madp - CM MAD that is input to this function
1428 * cm_mad_addr - Address information for the MAD
1429 *
1430 * RETURN VALUE: NONE
1431 */
1432 void
1433 ibcm_process_rep_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
1511 ibcm_resend_mra_mad(statep);
1512 else if ((statep->state == IBCM_STATE_REQ_SENT) ||
1513 (statep->state == IBCM_STATE_REP_WAIT)) {
1514
1515 /* change state */
1516 statep->state = IBCM_STATE_REP_RCVD;
1517 statep->clnt_proceed = IBCM_BLOCK;
1518 statep->local_qp_rnr_cnt =
1519 rep_msgp->rep_rnr_retry_cnt_plus >> 5;
1520
1521 /* cancel the REQ timer */
1522 if (statep->timerid != 0) {
1523 timer_val = statep->timerid;
1524 statep->timerid = 0;
1525 mutex_exit(&statep->state_mutex);
1526 (void) untimeout(timer_val);
1527 } else {
1528 mutex_exit(&statep->state_mutex);
1529 }
1530
1531 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
1532
1533 /* Initialize the remote destination QPN for further MADs */
1534 statep->stored_reply_addr.rcvd_addr.ia_remote_qno =
1535 cm_mad_addr->rcvd_addr.ia_remote_qno;
1536 statep->remote_qpn = b2h32(rep_msgp->rep_local_qpn_plus) >> 8;
1537 statep->remote_comid = b2h32(rep_msgp->rep_local_comm_id);
1538 bcopy(rep_msgp->rep_local_ca_guid, &remote_ca_guid,
1539 sizeof (ib_guid_t));
1540 statep->remote_hca_guid = b2h64(remote_ca_guid);
1541
1542 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1543 "passive cid = %x passive qpn = %x", statep,
1544 statep->remote_comid, statep->remote_qpn);
1545
1546 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1547 "passive hcaguid = %llX", statep, statep->remote_hca_guid);
1548
1549 stale_qpn = statep;
1550 stale_comid = statep;
1551
1552 /* Handle stale connection detection on active side */
1740 /* Initialize the remote ack delay */
1741 statep->remote_ack_delay =
1742 ibt_ib2usec(rep_msgp->rep_target_delay_plus >> 3);
1743
1744 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p"
1745 " passive hca_ack_delay= %x ", statep,
1746 statep->remote_ack_delay);
1747
1748 response = ibcm_cep_state_rep(statep, rep_msgp,
1749 &reject_reason, &arej_info_len);
1750
1751 if (response == IBCM_DEFER) {
1752 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: "
1753 "statep 0x%p client returned DEFER response",
1754 statep);
1755 return;
1756 }
1757 ibcm_handle_cep_rep_response(statep, response,
1758 reject_reason, arej_info_len, rep_msgp);
1759
1760 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
1761
1762 return;
1763
1764 } else if (statep->state == IBCM_STATE_DELETE) {
1765
1766 mutex_exit(&statep->state_mutex);
1767 ibcm_build_n_post_rej_mad(input_madp,
1768 b2h32(rep_msgp->rep_local_comm_id), cm_mad_addr,
1769 IBT_CM_FAILURE_REP, IBT_CM_INVALID_CID);
1770 mutex_enter(&statep->state_mutex);
1771 } else {
1772
1773 #ifdef DEBUG
1774 if (ibcm_test_mode > 0)
1775 if (statep->state == IBCM_STATE_REP_RCVD)
1776 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1777 "REP re-send from passive for statep 0x%p"
1778 " in state %d", statep, statep->state);
1779 else
1780 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1781 "Unexpected REP for statep 0x%p in "
2622
2623 /*
2624 * ibcm_post_dreq_mad:
2625 * Posts a DREQ MAD
2626 * Post DREQ now for TIMEWAIT state and DREQ_RCVD
2627 *
2628 * INPUTS:
2629 * statep - state pointer
2630 *
2631 * RETURN VALUE:
2632 * NONE
2633 */
2634 void
2635 ibcm_post_dreq_mad(void *vstatep)
2636 {
2637 ibcm_state_data_t *statep = vstatep;
2638 ibcm_dreq_msg_t *dreq_msgp;
2639
2640 ASSERT(statep->dreq_msg != NULL);
2641
2642 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dreq_msgp))
2643
2644 /* Fill in the DREQ message */
2645 dreq_msgp = (ibcm_dreq_msg_t *)IBCM_OUT_MSGP(statep->dreq_msg);
2646 dreq_msgp->dreq_local_comm_id = h2b32(statep->local_comid);
2647 dreq_msgp->dreq_remote_comm_id = h2b32(statep->remote_comid);
2648 dreq_msgp->dreq_remote_qpn_eecn_plus = h2b32(statep->remote_qpn << 8);
2649
2650 IBCM_OUT_HDRP(statep->dreq_msg)->AttributeID =
2651 h2b16(IBCM_INCOMING_DREQ + IBCM_ATTR_BASE_ID);
2652
2653 /* wait until client knows CONN EST event */
2654 mutex_enter(&statep->state_mutex);
2655 while (statep->cep_in_rts == IBCM_BLOCK)
2656 cv_wait(&statep->block_mad_cv, &statep->state_mutex);
2657 mutex_exit(&statep->state_mutex);
2658
2659 /* Transition QP/EEC state to ERROR state */
2660 (void) ibcm_cep_to_error_state(statep);
2661
2662 IBCM_OUT_HDRP(statep->dreq_msg)->TransactionID =
2663 h2b64(ibcm_generate_tranid(IBCM_INCOMING_DREQ, statep->local_comid,
2664 0));
2665
2666 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*dreq_msgp))
2667
2668 /* post the first DREQ via timeout callback */
2669 mutex_enter(&statep->state_mutex);
2670
2671 statep->state = IBCM_STATE_DREQ_SENT;
2672 cv_broadcast(&statep->block_mad_cv);
2673
2674 statep->timer_stored_state = statep->state;
2675 /* client cannot specify more than 16 retries */
2676 statep->timer_value = statep->remote_ack_delay;
2677 if (statep->mode == IBCM_ACTIVE_MODE) {
2678 statep->timer_value += (2 * statep->pkt_life_time);
2679 }
2680 statep->remaining_retry_cnt = statep->max_cm_retries + 1;
2681 statep->timerid = IBCM_TIMEOUT(statep, 0);
2682 mutex_exit(&statep->state_mutex);
2683 }
2684
2685 /*
2686 * ibcm_post_drep_mad:
2687 * Posts a DREP MAD
2688 * Post DREP now for TIMEWAIT state and DREQ_RCVD
2689 *
2690 * INPUTS:
2691 * statep - state pointer
2692 *
2693 * RETURN VALUE:
2694 * NONE
2695 */
2696 static void
2697 ibcm_post_drep_mad(ibcm_state_data_t *statep)
2698 {
2699 ibcm_drep_msg_t *drep_msgp;
2700
2701 drep_msgp = (ibcm_drep_msg_t *)IBCM_OUT_MSGP(statep->drep_msg);
2702
2703 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*drep_msgp))
2704
2705 IBTF_DPRINTF_L4(cmlog, "ibcm_post_drep_mad:");
2706
2707 /* Fill up DREP fields */
2708 drep_msgp->drep_local_comm_id = h2b32(statep->local_comid);
2709 drep_msgp->drep_remote_comm_id = h2b32(statep->remote_comid);
2710 IBCM_OUT_HDRP(statep->drep_msg)->AttributeID =
2711 h2b16(IBCM_INCOMING_DREP + IBCM_ATTR_BASE_ID);
2712
2713 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*drep_msgp))
2714
2715 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_DREP);
2716
2717 /* Post the DREP MAD now. */
2718 ibcm_post_rc_mad(statep, statep->drep_msg, ibcm_post_drep_complete,
2719 statep);
2720 }
2721
2722 /*
2723 * ibcm_process_drep_msg:
2724 * Processes incoming DREP message on active/passive side
2725 *
2726 * INPUTS:
2727 * hcap - HCA entry pointer
2728 * input_madp - CM MAD that is input to this function
2729 * cm_mad_addr - Address information for the MAD
2730 *
2731 * RETURN VALUE: NONE
2732 */
2733 /* ARGSUSED */
2734 void
3009 * RETURN VALUE:
3010 * NONE
3011 * Notes
3012 * There is no need to hold the statep->mutex and call ibcm_post_rej_mad
3013 * REJ can be posted either in IBCM_STATE_REQ_RCVD or IBCM_STATE_REP_RCVD
3014 * In these states, there is no timer active, and an incoming REJ shall
3015 * not modify the state or cancel timers
3016 * An incoming REJ doesn't affect statep in state = IBCM_STATE_REJ_SENT/BUSY
3017 */
3018 void
3019 ibcm_post_rej_mad(ibcm_state_data_t *statep, ibt_cm_reason_t reject_reason,
3020 int which_msg, void *addl_rej_info, ibt_priv_data_len_t arej_info_len)
3021 {
3022 ibcm_rej_msg_t *rej_msg =
3023 (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3024
3025 /* Message printed if connection gets REJed */
3026 IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_mad: "
3027 "statep = %p, reject_reason = %d", statep, reject_reason);
3028
3029 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3030
3031 /* Initialize rej_msg fields */
3032 rej_msg->rej_local_comm_id = h2b32(statep->local_comid);
3033 rej_msg->rej_remote_comm_id = h2b32(statep->remote_comid);
3034 rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
3035 rej_msg->rej_reject_info_len_plus = arej_info_len << 1;
3036 rej_msg->rej_rejection_reason = h2b16((uint16_t)reject_reason);
3037
3038 if ((arej_info_len != 0) && (addl_rej_info != NULL))
3039 bcopy(addl_rej_info, rej_msg->rej_addl_rej_info, arej_info_len);
3040
3041 IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3042 h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3043
3044 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3045
3046 mutex_enter(&statep->state_mutex);
3047
3048 /* signal any waiting close channels with blocking or no callbacks */
3049 statep->close_done = B_TRUE;
3050 statep->close_nocb_state = IBCM_FAIL;
3051
3052 cv_signal(&statep->block_client_cv);
3053
3054 statep->timer_stored_state = statep->state = IBCM_STATE_REJ_SENT;
3055 statep->send_mad_flags |= IBCM_REJ_POST_BUSY;
3056
3057 IBCM_REF_CNT_INCR(statep); /* for non-blocking post */
3058 mutex_exit(&statep->state_mutex);
3059
3060 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REJ);
3061 if (ibcm_enable_trace & 2)
3062 ibcm_dump_conn_trace(statep);
3063 else
3064 IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_mad statep %p "
3065 "OUTGOING_REJ", statep);
3084 * NONE
3085 */
3086 static void
3087 ibcm_build_n_post_rej_mad(uint8_t *input_madp, ib_com_id_t remote_comid,
3088 ibcm_mad_addr_t *cm_mad_addr, int which_msg, uint16_t reject_reason)
3089 {
3090 ibcm_rej_msg_t *rej_msg;
3091 ibmf_msg_t *cm_rej_msg;
3092 ibcm_mad_addr_t rej_reply_addr;
3093
3094 IBTF_DPRINTF_L3(cmlog, "ibcm_build_n_post_rej_mad: "
3095 "remote_comid: %x reject_reason %d", remote_comid, reject_reason);
3096
3097 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3098 MAD_METHOD_SEND) != IBT_SUCCESS) {
3099 IBTF_DPRINTF_L2(cmlog, "ibcm_build_n_post_rej_mad: "
3100 "ibcm_alloc_out_msg failed");
3101 return;
3102 }
3103
3104 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3105
3106 IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3107 ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3108
3109 /* Initialize rej_msg fields */
3110 rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3111 rej_msg->rej_local_comm_id = 0;
3112 rej_msg->rej_remote_comm_id = h2b32(remote_comid);
3113 rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
3114 rej_msg->rej_reject_info_len_plus = 0;
3115 rej_msg->rej_rejection_reason = h2b16(reject_reason);
3116
3117 IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3118 h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3119
3120 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3121
3122 ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3123
3124 if (rej_reply_addr.cm_qp_entry != NULL) {
3125 (void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3126 ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3127 }
3128
3129 (void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3130 }
3131
3132 /* posts a REJ for an incoming REQ with unsupported class version */
3133
3134 static void
3135 ibcm_post_rej_ver_mismatch(uint8_t *input_madp, ibcm_mad_addr_t *cm_mad_addr)
3136 {
3137 ibcm_req_msg_t *req_msgp =
3138 (ibcm_req_msg_t *)&input_madp[IBCM_MAD_HDR_SIZE];
3139 ibcm_rej_msg_t *rej_msg;
3140 ibmf_msg_t *cm_rej_msg;
3141 ibcm_mad_addr_t rej_reply_addr;
3142
3143 IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_ver_mismatch: remote comid %x",
3144 b2h32(req_msgp->req_local_comm_id));
3145
3146 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3147 MAD_METHOD_SEND) != IBT_SUCCESS) {
3148 IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_ver_mismatch: "
3149 "ibcm_alloc_out_msg failed");
3150 return;
3151 }
3152
3153 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msg))
3154
3155 IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3156 ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3157
3158 /* Initialize rej_msg fields */
3159 rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3160 rej_msg->rej_local_comm_id = 0;
3161 rej_msg->rej_remote_comm_id = req_msgp->req_local_comm_id;
3162 rej_msg->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
3163 rej_msg->rej_rejection_reason = h2b16(IBT_CM_CLASS_NO_SUPPORT);
3164 rej_msg->rej_reject_info_len_plus = 1 << 1;
3165 rej_msg->rej_addl_rej_info[0] = IBCM_MAD_CLASS_VERSION;
3166
3167 IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3168 h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3169 IBCM_OUT_HDRP(cm_rej_msg)->Status = h2b16(MAD_STATUS_BAD_VERSION);
3170
3171 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msg))
3172
3173 ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3174 if (rej_reply_addr.cm_qp_entry != NULL) {
3175 (void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3176 ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3177 }
3178 (void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3179 }
3180
3181
3182 /*
3183 * ibcm_post_rep_mad:
3184 * Posts a REP MAD and starts timer
3185 *
3186 * INPUTS:
3187 * statep - state pointer
3188 *
3189 * RETURN VALUE:
3190 * NONE
3191 */
3192 void
3193 ibcm_post_rep_mad(ibcm_state_data_t *statep)
3194 {
3195 ibcm_rep_msg_t *rep_msgp =
3196 (ibcm_rep_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3197 ibmf_msg_t *mra_msg = NULL;
3198 boolean_t ret = B_FALSE;
3199
3200 IBTF_DPRINTF_L4(cmlog, "ibcm_post_rep_mad: statep 0x%p", statep);
3201
3202 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rep_msgp))
3203
3204 /*
3205 * All other REP fields, other that the 2 below, are filled in
3206 * the ibcm_cep_state_req() function.
3207 */
3208 rep_msgp->rep_local_comm_id = h2b32(statep->local_comid);
3209 rep_msgp->rep_remote_comm_id = h2b32(statep->remote_comid);
3210 IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3211 h2b16(IBCM_INCOMING_REP + IBCM_ATTR_BASE_ID);
3212
3213 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rep_msgp))
3214
3215 /*
3216 * Changing state and attempt to delete the mra msg must be done
3217 * together holding the state_mutex
3218 */
3219 mutex_enter(&statep->state_mutex);
3220
3221 /* Now, attempt to delete the mra_msg, if there is one allocated */
3222 if (statep->mra_msg != NULL) {
3223 if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3224 mra_msg = statep->mra_msg;
3225 statep->mra_msg = NULL;
3226 } else statep->delete_mra_msg = B_TRUE;
3227 }
3228
3229 if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3230 statep->state = IBCM_STATE_ABORTED;
3231 mutex_exit(&statep->state_mutex);
3232 ibcm_process_abort(statep);
3233
3234 /* Now post a REJ MAD, rej reason consumer abort */
3269 /*
3270 * ibcm_post_rtu_mad:
3271 * From active side post RTU MAD
3272 *
3273 * INPUTS:
3274 * statep - state pointer
3275 *
3276 * RETURN VALUE: NONE
3277 *
3278 * NOTE: No timer set after posting RTU
3279 */
3280 ibcm_status_t
3281 ibcm_post_rtu_mad(ibcm_state_data_t *statep)
3282 {
3283 ibcm_rtu_msg_t *rtu_msg;
3284 ibmf_msg_t *mra_msg = NULL;
3285 boolean_t ret = B_FALSE;
3286
3287 IBTF_DPRINTF_L4(cmlog, "ibcm_post_rtu_mad: statep 0x%p", statep);
3288
3289 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rtu_msg))
3290
3291 rtu_msg = (ibcm_rtu_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3292
3293 rtu_msg->rtu_local_comm_id = h2b32(statep->local_comid);
3294 rtu_msg->rtu_remote_comm_id = h2b32(statep->remote_comid);
3295 IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3296 h2b16(IBCM_INCOMING_RTU + IBCM_ATTR_BASE_ID);
3297
3298 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rtu_msg))
3299
3300 mutex_enter(&statep->state_mutex);
3301
3302 /* Now, attempt to delete the mra_msg, if there is one allocated */
3303 if (statep->mra_msg != NULL) {
3304 if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3305 mra_msg = statep->mra_msg;
3306 statep->mra_msg = NULL;
3307 } else statep->delete_mra_msg = B_TRUE;
3308 }
3309
3310 if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3311 statep->state = IBCM_STATE_ABORTED;
3312 mutex_exit(&statep->state_mutex);
3313
3314 ibcm_process_abort(statep);
3315
3316 /* Now post a REJ MAD */
3317 ibcm_post_rej_mad(statep, IBT_CM_CONSUMER, IBT_CM_FAILURE_REP,
3318 NULL, 0);
3319 ret = B_TRUE;
3466 mutex_exit(&statep->state_mutex);
3467
3468 /* Deallocate the CM state structure */
3469 ibcm_delete_state_data(statep);
3470 return;
3471
3472 } else if (statep->state == IBCM_STATE_TIMEWAIT) {
3473 statep->state = IBCM_STATE_DELETE;
3474
3475 /* TIME_WAIT timer expired, so cleanup */
3476 mutex_exit(&statep->state_mutex);
3477
3478 if (statep->channel)
3479 ibtl_cm_chan_is_closed(statep->channel);
3480
3481 if (statep->recycle_arg) {
3482 struct ibcm_taskq_recycle_arg_s *recycle_arg;
3483
3484 recycle_arg = statep->recycle_arg;
3485
3486 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
3487 statep->recycle_arg))
3488 statep->recycle_arg = NULL;
3489 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
3490
3491 /* if possible, do not slow down calling recycle func */
3492 if (taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
3493 recycle_arg, TQ_NOQUEUE | TQ_NOSLEEP) == 0) {
3494
3495 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(
3496 statep->recycle_arg))
3497 statep->recycle_arg = recycle_arg;
3498 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(
3499 statep->recycle_arg))
3500 ibcm_add_tlist(statep);
3501 return;
3502 }
3503 }
3504
3505 ibcm_delete_state_data(statep);
3506 return;
3507 } else if (statep->remaining_retry_cnt > 0) {
3508 ibcm_conn_state_t stored_state;
3509 ibcm_ap_state_t stored_ap_state;
3510
3511 statep->remaining_retry_cnt--;
3512 IBTF_DPRINTF_L3(cmlog, "ibcm_timeout_cb: statep 0x%p "
3513 "attr-id= 0x%x, retries remaining = 0x%x", statep,
3514 b2h16(IBCM_OUT_HDRP(statep->stored_msg)->AttributeID),
3515 statep->remaining_retry_cnt);
3516
3517 /*
3518 * REP could be resent, either because of timeout or an
3519 * incoming REQ. Any other MAD below can be resent, because
4244 ud_statep = ibcm_ud_timeout_list_hdr;
4245 ibcm_ud_timeout_list_hdr = ud_statep->ud_timeout_next;
4246
4247 if (ibcm_ud_timeout_list_hdr == NULL)
4248 ibcm_ud_timeout_list_tail = NULL;
4249
4250 ud_statep->ud_timeout_next = NULL;
4251
4252 mutex_exit(&ibcm_timeout_list_lock);
4253 IBTF_DPRINTF_L3(cmlog, "ibcm_process_tlist: "
4254 "ud scheduling state = %p", ud_statep);
4255 ibcm_ud_timeout_client_cb(ud_statep);
4256 mutex_enter(&ibcm_timeout_list_lock);
4257 } else {
4258 CALLB_CPR_SAFE_BEGIN(&cprinfo);
4259 cv_wait(&ibcm_timeout_list_cv, &ibcm_timeout_list_lock);
4260 CALLB_CPR_SAFE_END(&cprinfo, &ibcm_timeout_list_lock);
4261 }
4262 }
4263
4264 #ifndef __lock_lint
4265 CALLB_CPR_EXIT(&cprinfo); /* mutex_exit */
4266 #endif
4267 }
4268
4269
4270 /*
4271 * ibcm_timeout_client_cb:
4272 * Called from timeout thread processing
4273 * Primary purpose is to call client handler
4274 *
4275 * INPUTS:
4276 * arg - ibcm_state_data_t is passed
4277 *
4278 * RETURN VALUES: NONE
4279 */
4280 void
4281 ibcm_timeout_client_cb(ibcm_state_data_t *statep)
4282 {
4283 mutex_enter(&statep->state_mutex);
4284
4285 if ((statep->state == IBCM_STATE_DELETE) &&
4286 (statep->recycle_arg != NULL)) {
4287 struct ibcm_taskq_recycle_arg_s *recycle_arg;
4288
4289 recycle_arg = statep->recycle_arg;
4290 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
4291 statep->recycle_arg = NULL;
4292 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->recycle_arg))
4293 mutex_exit(&statep->state_mutex);
4294 (void) ibcm_process_rc_recycle(recycle_arg);
4295 ibcm_delete_state_data(statep);
4296 return;
4297 }
4298
4299 if ((statep->state == IBCM_STATE_DELETE) &&
4300 (statep->delete_state_data == B_TRUE)) {
4301 mutex_exit(&statep->state_mutex);
4302 ibcm_dealloc_state_data(statep);
4303 return;
4304 }
4305
4306 /* Else, it must be in TIMEOUT state, do the necessary processing */
4307 if (statep->state == IBCM_STATE_TIMED_OUT) {
4308 void *data;
4309 uint8_t cf_msg;
4310 ib_guid_t local_hca_guid;
4311
4312 mutex_exit(&statep->state_mutex);
4492
4493 hca_guid = hcap->hca_guid;
4494 port_num = cm_mad_addr->port_num;
4495
4496 /* Figure out LID, GID, RequestId for svc_id lookup */
4497 lid = cm_mad_addr->rcvd_addr.ia_remote_lid;
4498 req_id = b2h32(sidr_reqp->sidr_req_request_id);
4499 pkey = b2h16(sidr_reqp->sidr_req_pkey);
4500 if (cm_mad_addr->grh_exists == B_TRUE)
4501 gid = cm_mad_addr->grh_hdr.ig_sender_gid;
4502 else
4503 gid.gid_prefix = gid.gid_guid = 0;
4504
4505 /*
4506 * Lookup for an existing state structure
4507 * - if lookup fails it creates a new ud_state struct
4508 * No need to hold a lock across the call to ibcm_find_sidr_entry() as
4509 * the list lock is held in that function to find the matching entry.
4510 */
4511
4512 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srch_sidr))
4513
4514 srch_sidr.srch_lid = lid;
4515 srch_sidr.srch_gid = gid;
4516 srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4517 srch_sidr.srch_req_id = req_id;
4518 srch_sidr.srch_mode = IBCM_PASSIVE_MODE;
4519
4520 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srch_sidr))
4521
4522 rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
4523 state_lookup_status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4524 IBCM_FLAG_LOOKUP_AND_ADD);
4525 rw_exit(&hcap->hca_sidr_list_lock);
4526
4527 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: ud_statep 0x%p "
4528 "lookup status %x", ud_statep, state_lookup_status);
4529
4530 if (state_lookup_status == IBCM_LOOKUP_NEW) {
4531
4532 /* Increment hca's resource count */
4533 ibcm_inc_hca_res_cnt(hcap);
4534
4535 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ud_statep))
4536
4537 /*
4538 * Allocate CM MAD for a response
4539 * This MAD is deallocated on state structure delete
4540 * and re-used for all outgoing MADs for this connection.
4541 * If MAD allocation fails, delete the ud statep
4542 */
4543 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
4544 &ud_statep->ud_stored_msg, MAD_METHOD_SEND) !=
4545 IBT_SUCCESS) {
4546 mutex_enter(&ud_statep->ud_state_mutex);
4547 IBCM_UD_REF_CNT_DECR(ud_statep);
4548 mutex_exit(&ud_statep->ud_state_mutex);
4549 ibcm_delete_ud_state_data(ud_statep);
4550 return;
4551 }
4552
4553 /* Lookup for service */
4554 ud_statep->ud_svc_id = b2h64(sidr_reqp->sidr_req_service_id);
4555 ud_statep->ud_state = IBCM_STATE_SIDR_REQ_RCVD;
4556 ud_statep->ud_clnt_proceed = IBCM_BLOCK;
4633
4634 /* Call Client's UD handler */
4635 cm_status = ibcm_sidr_req_ud_handler(ud_statep,
4636 sidr_reqp, cm_mad_addr, &sidr_status);
4637
4638 mutex_enter(&ibcm_svc_info_lock);
4639 IBCM_SVC_DECR(svc_infop);
4640 }
4641
4642 mutex_exit(&ibcm_svc_info_lock);
4643
4644 if (cm_status == IBCM_DEFER) {
4645 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: "
4646 "ud_statep 0x%p client returned DEFER response",
4647 ud_statep);
4648 return;
4649 }
4650
4651 ibcm_post_sidr_rep_mad(ud_statep, sidr_status);
4652
4653 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ud_statep))
4654
4655 mutex_enter(&ud_statep->ud_state_mutex);
4656 IBCM_UD_REF_CNT_DECR(ud_statep);
4657 mutex_exit(&ud_statep->ud_state_mutex);
4658 } else {
4659 ASSERT(state_lookup_status == IBCM_LOOKUP_EXISTS);
4660
4661 mutex_enter(&ud_statep->ud_state_mutex);
4662
4663 if (ud_statep->ud_state == IBCM_STATE_SIDR_REP_SENT)
4664 ibcm_resend_srep_mad(ud_statep);
4665
4666 IBCM_UD_REF_CNT_DECR(ud_statep);
4667 mutex_exit(&ud_statep->ud_state_mutex);
4668 }
4669 }
4670
4671
4672 /*
4673 * ibcm_process_sidr_rep_msg:
4674 * This call processes an incoming SIDR REP
4697 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg:");
4698
4699 lid = cm_mad_addr->rcvd_addr.ia_local_lid;
4700 if (cm_mad_addr->grh_exists == B_TRUE)
4701 gid = cm_mad_addr->grh_hdr.ig_recver_gid;
4702 else
4703 gid.gid_prefix = gid.gid_guid = 0;
4704
4705 IBTF_DPRINTF_L3(cmlog, "ibcm_process_sidr_rep_msg: QPN rcvd = %x",
4706 h2b32(sidr_repp->sidr_rep_qpn_plus) >> 8);
4707
4708 /*
4709 * Lookup for an existing state structure.
4710 * No need to hold a lock as ibcm_find_sidr_entry() holds the
4711 * list lock to find the matching entry.
4712 */
4713 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep: lid=%x, (%llX, %llX), "
4714 "grh = %x, id = %x", lid, gid.gid_prefix, gid.gid_guid,
4715 cm_mad_addr->grh_exists, sidr_repp->sidr_rep_request_id);
4716
4717 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(srch_sidr))
4718
4719 srch_sidr.srch_lid = lid;
4720 srch_sidr.srch_gid = gid;
4721 srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4722 srch_sidr.srch_req_id = b2h32(sidr_repp->sidr_rep_request_id);
4723 srch_sidr.srch_mode = IBCM_ACTIVE_MODE;
4724
4725 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(srch_sidr))
4726
4727 rw_enter(&hcap->hca_sidr_list_lock, RW_READER);
4728 status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4729 IBCM_FLAG_LOOKUP);
4730 rw_exit(&hcap->hca_sidr_list_lock);
4731
4732 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg: ud_statep 0x%p "
4733 "find sidr entry status = %x", ud_statep, status);
4734
4735 if (status != IBCM_LOOKUP_EXISTS) {
4736 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4737 "No matching ud_statep for SIDR REP");
4738 return;
4739 }
4740
4741 if (IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID !=
4742 ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
4743 mutex_enter(&ud_statep->ud_state_mutex);
4744 IBCM_UD_REF_CNT_DECR(ud_statep);
4745 mutex_exit(&ud_statep->ud_state_mutex);
4746 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4844 * ibcm_post_sidr_rep_mad:
4845 * This call posts a SIDR REP MAD
4846 *
4847 * INPUTS:
4848 * ud_statep - pointer to ibcm_ud_state_data_t
4849 * status - Status information
4850 *
4851 * RETURN VALUE: NONE
4852 */
4853 void
4854 ibcm_post_sidr_rep_mad(ibcm_ud_state_data_t *ud_statep,
4855 ibt_sidr_status_t status)
4856 {
4857 ib_svc_id_t tmp_svc_id;
4858 ibcm_sidr_rep_msg_t *sidr_repp =
4859 (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
4860 clock_t timer_value;
4861
4862 IBTF_DPRINTF_L5(cmlog, "ibcm_post_sidr_rep_mad:");
4863
4864 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
4865
4866 IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
4867 h2b16(IBCM_INCOMING_SIDR_REP + IBCM_ATTR_BASE_ID);
4868
4869 /*
4870 * Initialize SIDR REP message. (Other fields were
4871 * already filled up in ibcm_sidr_req_ud_handler()
4872 */
4873 sidr_repp->sidr_rep_request_id = h2b32(ud_statep->ud_req_id);
4874 tmp_svc_id = h2b64(ud_statep->ud_svc_id);
4875 bcopy(&tmp_svc_id, sidr_repp->sidr_rep_service_id, sizeof (tmp_svc_id));
4876
4877 sidr_repp->sidr_rep_rep_status = (uint8_t)status;
4878
4879 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sidr_repp))
4880
4881 /* post the SIDR REP MAD */
4882 ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg, NULL, NULL);
4883
4884 timer_value = ibt_ib2usec(ibcm_max_sidr_rep_store_time);
4885 /*
4886 * Hold the statep lock, as a SIDR REQ may come in after setting state
4887 * but before timeout. This can result in a dangling timeout ie.,
4888 * the incoming SIDR REQ would be unable to cancel this timeout
4889 */
4890 mutex_enter(&ud_statep->ud_state_mutex);
4891
4892 ud_statep->ud_remaining_retry_cnt = 1;
4893 ud_statep->ud_timer_value = timer_value;
4894
4895 ud_statep->ud_timer_stored_state = ud_statep->ud_state =
4896 IBCM_STATE_SIDR_REP_SENT;
4897 ud_statep->ud_timerid = IBCM_UD_TIMEOUT(ud_statep,
4898 ud_statep->ud_timer_value);
4899
4900 mutex_exit(&ud_statep->ud_state_mutex);
5041 /*
5042 * ibcm_build_reply_mad_addr:
5043 * Forms the reply MAD address based on "incoming mad addr" that is
5044 * supplied as an arg.
5045 *
5046 * Swaps the source and destination gids in ib_grh_t
5047 *
5048 * INPUTS:
5049 * inp_mad_addr: Address information in the incoming MAD
5050 * out_mad_addr: Derived address for the reply MAD
5051 * The reply MAD address is derived based
5052 * address information of incoming CM MAD
5053 * RETURN VALUE: NONE
5054 */
5055 void
5056 ibcm_build_reply_mad_addr(ibcm_mad_addr_t *inp_mad_addr,
5057 ibcm_mad_addr_t *out_mad_addr)
5058 {
5059 IBTF_DPRINTF_L5(cmlog, "ibcm_build_reply_mad_addr:");
5060
5061 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_mad_addr))
5062
5063 bcopy(inp_mad_addr, out_mad_addr, sizeof (ibcm_mad_addr_t));
5064
5065 /* Swap the GIDs in the GRH */
5066 if (inp_mad_addr->grh_exists == B_TRUE) {
5067 ib_gid_t sgid = inp_mad_addr->grh_hdr.ig_sender_gid;
5068
5069 /* swap the SGID and DGID */
5070 out_mad_addr->grh_hdr.ig_sender_gid =
5071 inp_mad_addr->grh_hdr.ig_recver_gid;
5072 out_mad_addr->grh_hdr.ig_recver_gid = sgid;
5073 }
5074
5075 /*
5076 * CM posts response MAD on a new/existing internal QP on the same port
5077 * and pkey
5078 */
5079 out_mad_addr->cm_qp_entry =
5080 ibcm_find_qp(inp_mad_addr->cm_qp_entry->qp_port->port_hcap,
5081 inp_mad_addr->port_num, inp_mad_addr->rcvd_addr.ia_p_key);
5082
5083 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*out_mad_addr))
5084 }
5085
5086
5087 /*
5088 * ibcm_post_rc_mad
5089 * Posts a CM MAD associated with a RC statep
5090 *
5091 * INPUTS:
5092 * statep : RC statep associated with the post
5093 * msgp : CM MAD to be posted
5094 * post_cb : non-NULL callback address implies non-blocking post
5095 * args : Args to ibmf send callback
5096 *
5097 * RETURN VALUE: based on ibmf_send_mad
5098 */
5099 void
5100 ibcm_post_rc_mad(ibcm_state_data_t *statep, ibmf_msg_t *msgp,
5101 ibmf_msg_cb_t post_cb, void *args)
5102 {
5103 ibt_status_t status;
6256
6257 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_REQ_RCVD_EVENT);
6258
6259 /* Invoke the client handler */
6260 statep->req_msgp = cm_req_msgp;
6261 cb_status = statep->cm_handler(statep->state_cm_private, &event,
6262 &ret_args, priv_data, IBT_REP_PRIV_DATA_SZ);
6263 statep->req_msgp = NULL;
6264
6265 ibcm_insert_trace(statep, IBCM_TRACE_RET_REQ_RCVD_EVENT);
6266
6267 mutex_enter(&ibcm_svc_info_lock);
6268 IBCM_SVC_DECR(statep->state_svc_infop);
6269 mutex_exit(&ibcm_svc_info_lock);
6270
6271 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: Client handler returned %d"
6272 " statep 0x%p", cb_status, statep);
6273
6274 if (cb_status == IBT_CM_DEFER) {
6275
6276 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
6277
6278 if (statep->defer_cm_msg == NULL)
6279 statep->defer_cm_msg =
6280 kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
6281 bcopy(cm_req_msgp, statep->defer_cm_msg, IBCM_MSG_SIZE);
6282
6283 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
6284
6285 /*
6286 * unblock any blocked cm proceed api calls. Do not access
6287 * statep after cv_signal
6288 */
6289 mutex_enter(&statep->state_mutex);
6290 statep->clnt_proceed = IBCM_UNBLOCK;
6291 cv_broadcast(&statep->block_client_cv);
6292 mutex_exit(&statep->state_mutex);
6293
6294 kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6295 return (IBCM_DEFER);
6296 }
6297
6298 /* fail any blocked cm proceed api call - client bug */
6299 mutex_enter(&statep->state_mutex);
6300 statep->clnt_proceed = IBCM_FAIL;
6301 cv_broadcast(&statep->block_client_cv);
6302 mutex_exit(&statep->state_mutex);
6303
6304 clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
6342 *reject_reason = IBT_CM_CONSUMER;
6343 } else if (cb_status == IBT_CM_REDIRECT_PORT) {
6344 *reject_reason = IBT_CM_PORT_REDIRECT;
6345 } else if (cb_status == IBT_CM_REDIRECT) {
6346 *reject_reason = IBT_CM_REDIRECT_CM;
6347 } else if (cb_status == IBT_CM_NO_CHANNEL) {
6348 *reject_reason = IBT_CM_NO_CHAN;
6349 } else if (cb_status == IBT_CM_NO_RESOURCE) {
6350 *reject_reason = IBT_CM_NO_RESC;
6351 } else {
6352 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p"
6353 " Client handler unexpected return %x", statep, cb_status);
6354 *reject_reason = IBT_CM_CONSUMER;
6355 }
6356
6357 /* client handler gave CM ok */
6358 if (cb_status == IBT_CM_ACCEPT) {
6359 ibcm_rep_msg_t *rep_msgp = (ibcm_rep_msg_t *)
6360 IBCM_OUT_MSGP(statep->stored_msg);
6361
6362
6363 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6364 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rep_msgp))
6365
6366 /*
6367 * Check first if ret_args make sense. If not, bailout
6368 * here rather than going along and panicing later.
6369 */
6370 channel = clnt_info->reply_event->rep.cm_channel;
6371 if (IBCM_INVALID_CHANNEL(channel)) {
6372 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6373 "statep 0x%p server's QP handle is NULL", statep);
6374 *reject_reason = IBT_CM_NO_CHAN;
6375 }
6376
6377 IBCM_GET_CHAN_PRIVATE(channel, old_statep);
6378
6379 if ((*reject_reason == IBT_CM_SUCCESS) &&
6380 (old_statep != NULL)) {
6381 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6382 "statep 0x%p Channel being re-used on passive side",
6383 statep);
6384 *reject_reason = IBT_CM_NO_CHAN;
6385 }
6630 if (status == IBT_SUCCESS) {
6631 rep_msgp->rep_local_eecn_plus =
6632 h2b32(((uint32_t)eec_attrs.eec_eecn << 8));
6633 }
6634 }
6635 #endif
6636
6637 /* figure out Target ACK delay */
6638 rep_msgp->rep_target_delay_plus |= (status == IBT_SUCCESS) ?
6639 statep->hcap->hca_ack_delay << 3 : 0;
6640
6641 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr:statep %p "
6642 "REP priv len %x", statep, clnt_info->priv_data_len);
6643 /* Copy PrivateData from priv_data */
6644 if (clnt_info->priv_data_len != 0) {
6645 bcopy(clnt_info->priv_data, rep_msgp->rep_private_data,
6646 min(IBT_REP_PRIV_DATA_SZ,
6647 clnt_info->priv_data_len));
6648 }
6649
6650 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*statep))
6651 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rep_msgp))
6652
6653 return (IBCM_SEND_REP);
6654 }
6655
6656 /* REJ message */
6657 rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6658
6659 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p REJ "
6660 "priv len %x", statep, clnt_info->priv_data_len);
6661
6662 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp))
6663
6664 /* if priv_data_len != 0 use priv_data to copy back to rej_priv_data */
6665 if (clnt_info->priv_data_len != 0) {
6666 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6667 min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6668 }
6669
6670 if (cb_status == IBT_CM_REDIRECT_PORT) {
6671 ib_gid_t tgid;
6672
6673 tgid.gid_guid =
6674 h2b64(clnt_info->reply_event->rej.ari_gid.gid_guid);
6675 tgid.gid_prefix =
6676 h2b64(clnt_info->reply_event->rej.ari_gid.gid_prefix);
6677
6678 *arej_len = sizeof (ib_gid_t);
6679 bcopy(&tgid, &rej_msgp->rej_addl_rej_info, sizeof (ib_gid_t));
6680
6681 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: ari_gid= "
6682 "%llX:%llX", tgid.gid_prefix, tgid.gid_guid);
6683
6701
6702 /*
6703 * RDMA IP REQ was passed up to the ULP, the ULP decided to do
6704 * a "normal" consumer REJ, by the returning IBT_CM_REJECT in
6705 * the cm handler.
6706 * CM has to do some extra stuff too, it has to
6707 * a) return REJ code 28 (consumer) and b) put 0x1 in the first
6708 * byte of the ARI data, to indicate that this is a RDMA aware
6709 * ULP that is doing a consumer reject. The ULP should have
6710 * put its consumer specific data into ibt_arej_info_t(9s) at
6711 * byte 1 of the rej_ari[] array.
6712 */
6713 if (((statep->svcid & IB_SID_IPADDR_PREFIX_MASK) == 0) &&
6714 (statep->svcid & IB_SID_IPADDR_PREFIX)) {
6715 rej_msgp->rej_addl_rej_info[0] = 1;
6716 }
6717 }
6718
6719 rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
6720
6721 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp))
6722
6723 return (IBCM_SEND_REJ);
6724 }
6725
6726 /*
6727 * ibcm_cep_state_rep:
6728 * QP state transition function called for an incoming REP on active side
6729 *
6730 * INPUTS:
6731 * statep - state pointer
6732 * cm_rep_msg - REP message pointer
6733 * reject_reason - Rejection reason See Section 12.6.7.2 rev1.0a IB Spec
6734 *
6735 * RETURN VALUE:
6736 */
6737 ibcm_status_t
6738 ibcm_cep_state_rep(ibcm_state_data_t *statep, ibcm_rep_msg_t *cm_rep_msgp,
6739 ibt_cm_reason_t *reject_reason, uint8_t *arej_len)
6740 {
6741 void *priv_data = NULL;
6742 ibcm_status_t rval = IBCM_SEND_RTU;
6881
6882
6883 /* We come here if status is ACCEPT or CM handler is NULL */
6884 if (cb_status == IBT_CM_ACCEPT) {
6885 ib_time_t time;
6886
6887 time = ibt_usec2ib(statep->pkt_life_time * 2 +
6888 ibt_ib2usec(cm_rep_msgp->rep_target_delay_plus >> 3));
6889
6890 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6891 " active cep_timeout(usec) 0x%x ", statep, time);
6892
6893 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6894 " passive hca_ack_delay(ib_time) = 0x%x, ", statep,
6895 cm_rep_msgp->rep_target_delay_plus >> 3);
6896
6897 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6898 " rnr_retry_cnt = 0x%x", statep,
6899 cm_rep_msgp->rep_rnr_retry_cnt_plus >> 5);
6900
6901 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6902 statep->starting_psn =
6903 b2h32(cm_rep_msgp->rep_starting_psn_plus) >> 8;
6904
6905 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*statep))
6906
6907 /* Call IBTL CM's qp modify function from Init to RTR */
6908 if (ibcm_invoke_qp_modify(statep,
6909 (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg),
6910 cm_rep_msgp) != IBT_SUCCESS) {
6911
6912 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6913 "statep %p, ibcm_invoke_qp_modify to RTR failed",
6914 statep);
6915 *reject_reason = IBT_CM_NO_RESC;
6916 /*
6917 * Call modify qp function from RTR to RTS
6918 * RDMA initiator depth on active is same as negotiated
6919 * passive REP's responder resources
6920 */
6921 } else if (ibcm_invoke_rtu_qp_modify(statep, time, cm_rep_msgp)
6922 != IBT_SUCCESS) {
6923
6924 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6925 "statep %p ibcm_invoke_rtu_qp_modify to RTS failed",
6926 statep);
6934 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6935
6936 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6937 IBT_CM_FAILURE_REP, IBT_CM_CI_FAILURE, NULL, 0);
6938 return (IBCM_SEND_REJ); /* send REJ */
6939 }
6940
6941 if (clnt_info->priv_data_len != 0) {
6942 ibcm_rtu_msg_t *rtu_msgp;
6943 rtu_msgp = (ibcm_rtu_msg_t *)
6944 IBCM_OUT_MSGP(statep->stored_msg);
6945 bcopy(clnt_info->priv_data, rtu_msgp->rtu_private_data,
6946 min(IBT_RTU_PRIV_DATA_SZ,
6947 clnt_info->priv_data_len));
6948 }
6949
6950 *reject_reason = IBT_CM_SUCCESS;
6951 return (rval);
6952 }
6953
6954 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*rej_msgp))
6955
6956 /* Fill up the REJ fields, from ret_args */
6957 rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6958 rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REP << 6;
6959
6960 /* if priv_len != 0 use priv_data to copy back to rej_priv_data */
6961 if (clnt_info->priv_data_len != 0)
6962 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6963 min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6964
6965 if (clnt_info->reply_event != NULL)
6966 *arej_len =
6967 min(clnt_info->reply_event->rej.ari_consumer.rej_ari_len,
6968 IBT_CM_ADDL_REJ_LEN);
6969
6970 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej))
6971
6972 if (*arej_len != 0) /* asserts that clnt_info->reply_event != 0 */
6973 bcopy(clnt_info->reply_event->rej.ari_consumer.rej_ari,
6974 &rej_msgp->rej_addl_rej_info, *arej_len);
6975
6976 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(clnt_info->reply_event->rej))
6977
6978 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*rej_msgp))
6979
6980 rval = IBCM_SEND_REJ;
6981
6982 /* Disassociate statep and QP */
6983 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6984
6985 /* callback client, to enable client to do resource cleanup */
6986 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6987 IBT_CM_FAILURE_REP, *reject_reason, NULL, 0);
6988
6989 return (rval);
6990 }
6991
6992 /*
6993 * ibcm_invoke_rtu_qp_modify:
6994 * Helper function to modify QP for RTU only called from
6995 * ibcm_cep_state_rtu() and ibcm_cep_send_rtu()
6996 *
6997 * INPUTS:
6998 * statep - connection state pointer
6999 *
7335 bcopy(&event.cm_event.failed.cf_additional,
7336 &statep->open_return_data->rc_arej_info,
7337 sizeof (ibt_arej_info_t));
7338 if (ibcm_enable_trace != 0)
7339 ibcm_dump_conn_trace(statep);
7340 mutex_enter(&statep->state_mutex);
7341 ibcm_open_done(statep);
7342 mutex_exit(&statep->state_mutex);
7343 }
7344
7345 /* Used to initialize client args with addl rej information from REJ MAD */
7346 static void
7347 ibcm_copy_addl_rej(ibcm_state_data_t *statep, ibcm_rej_msg_t *rej_msgp,
7348 ibt_cm_conn_failed_t *failed)
7349 {
7350 uint16_t rej_reason = b2h16(rej_msgp->rej_rejection_reason);
7351 uint8_t ari_len = rej_msgp->rej_reject_info_len_plus >> 1;
7352 ibcm_classportinfo_msg_t tclp;
7353 ibt_arej_info_t *cf_addl = &failed->cf_additional;
7354
7355 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cf_addl))
7356 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid))
7357
7358 failed->cf_arej_info_valid = B_FALSE;
7359
7360 IBTF_DPRINTF_L3(cmlog, "ibcm_copy_addl_rej: rej_reason = %d "
7361 "ari_len = %d", rej_reason, ari_len);
7362
7363 if ((statep->mode == IBCM_PASSIVE_MODE) &&
7364 (rej_reason != IBT_CM_CONSUMER))
7365 return;
7366
7367 switch (rej_reason) {
7368 case IBT_CM_PRIM_GID:
7369 case IBT_CM_ALT_GID:
7370 case IBT_CM_PORT_REDIRECT:
7371 if (ari_len < sizeof (ib_gid_t))
7372 break;
7373 failed->cf_arej_info_valid = B_TRUE;
7374 bcopy(rej_msgp->rej_addl_rej_info, &cf_addl->ari_gid,
7375 sizeof (ib_gid_t));
7376 cf_addl->ari_gid.gid_guid = b2h64(cf_addl->ari_gid.gid_guid);
7377 cf_addl->ari_gid.gid_prefix =
7444 break;
7445 failed->cf_arej_info_valid = B_TRUE;
7446 if (ari_len > IBT_CM_ADDL_REJ_LEN)
7447 ari_len = IBT_CM_ADDL_REJ_LEN;
7448 bcopy(&rej_msgp->rej_addl_rej_info,
7449 cf_addl->ari_consumer.rej_ari, ari_len);
7450 cf_addl->ari_consumer.rej_ari_len = ari_len;
7451 break;
7452 case IBT_CM_INVALID_PRIM_FLOW:
7453 case IBT_CM_INVALID_ALT_FLOW:
7454 if (ari_len < 3) /* 3 bytes needed for 20 bits */
7455 break;
7456 failed->cf_arej_info_valid = B_TRUE;
7457 /* take the first 20 bits */
7458 cf_addl->ari_flow =
7459 b2h32(*(uint32_t *)&rej_msgp->rej_addl_rej_info) >> 12;
7460 break;
7461 default:
7462 break;
7463 }
7464
7465 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(failed->cf_arej_info_valid))
7466 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cf_addl))
7467 }
7468
7469
7470 /* Used to copy classportinfo to MAD from client initialized args */
7471 static void
7472 ibcm_init_clp_to_mad(ibcm_classportinfo_msg_t *clp, ibt_redirect_info_t *rinfo)
7473 {
7474
7475 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*clp))
7476
7477 bcopy(&ibcm_clpinfo, clp, sizeof (ibcm_clpinfo));
7478
7479 clp->RedirectGID_hi = h2b64(rinfo->rdi_gid.gid_prefix);
7480 clp->RedirectGID_lo = h2b64(rinfo->rdi_gid.gid_guid);
7481 clp->RedirectTC_plus =
7482 h2b32((rinfo->rdi_tclass << 24) | (rinfo->rdi_sl << 20) |
7483 (rinfo->rdi_flow & 0xfffff));
7484 clp->RedirectLID = h2b16(rinfo->rdi_dlid);
7485 clp->RedirectQP_plus = h2b32(rinfo->rdi_qpn & 0xffffff);
7486 clp->RedirectQ_Key = h2b32(rinfo->rdi_qkey);
7487 clp->RedirectP_Key = h2b16(rinfo->rdi_pkey);
7488
7489 IBTF_DPRINTF_L4(cmlog, "ibcm_init_clp_to_mad: RedirectGID= %llX:%llX,"
7490 " RedirectLID= 0x%lX", clp->RedirectGID_hi, clp->RedirectGID_lo,
7491 clp->RedirectLID);
7492
7493 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*clp))
7494 }
7495
7496
7497 /* Used to initialize classportinfo to be returned to clients, from MAD */
7498 static void
7499 ibcm_init_clp_from_mad(ibcm_classportinfo_msg_t *clp,
7500 ibt_redirect_info_t *rinfo)
7501 {
7502 uint32_t temp32;
7503
7504 rinfo->rdi_gid.gid_prefix = b2h64(clp->RedirectGID_hi);
7505 rinfo->rdi_gid.gid_guid = b2h64(clp->RedirectGID_lo);
7506 temp32 = b2h32(clp->RedirectTC_plus);
7507 rinfo->rdi_tclass = temp32 >> 24;
7508 rinfo->rdi_sl = (temp32 >> 20) & 0xf;
7509 rinfo->rdi_flow = temp32 & 0xffff;
7510 rinfo->rdi_dlid = b2h16(clp->RedirectLID);
7511 rinfo->rdi_qpn = b2h32(clp->RedirectQP_plus & 0xffffff);
7512 rinfo->rdi_qkey = b2h32(clp->RedirectQ_Key);
7513 rinfo->rdi_pkey = b2h16(clp->RedirectP_Key);
7709 min(ud_clnt_info->priv_data_len,
7710 IBT_SIDR_REP_PRIV_DATA_SZ));
7711 }
7712
7713 if (*sidr_status != IBT_CM_SREP_CHAN_VALID) {
7714 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_req_cm_hdlr: "
7715 "ud_handler return a failure: %d", cb_status);
7716 if (*sidr_status == IBT_CM_SREP_REDIRECT) {
7717 /*
7718 * typecasting to ibcm_classportinfo_msg_t is ok, as addl info
7719 * begins at offset 24 in sidr rep
7720 */
7721 ibcm_init_clp_to_mad(
7722 (ibcm_classportinfo_msg_t *)
7723 &sidr_repp->sidr_rep_class_port_info,
7724 ud_clnt_info->redirect_infop);
7725 }
7726 return;
7727 }
7728
7729
7730 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
7731
7732 sidr_repp->sidr_rep_qkey =
7733 h2b32(ud_clnt_info->ud_qkey);
7734 sidr_repp->sidr_rep_qpn_plus = h2b32(ud_clnt_info->ud_qpn << 8);
7735
7736 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sidr_repp))
7737 }
7738
7739 /*
7740 * ibcm_sidr_rep_ud_handler:
7741 * Invoke Client's UD handler For SIDR_REP msg
7742 *
7743 * INPUTS:
7744 * ud_statep - ud_state pointer
7745 * sidr_rep_msgp - SIDR_REQ message pointer
7746 *
7747 */
7748 static void
7749 ibcm_sidr_rep_ud_handler(ibcm_ud_state_data_t *ud_statep,
7750 ibcm_sidr_rep_msg_t *sidr_rep_msgp)
7751 {
7752 ibt_cm_ud_event_t ud_event;
7753
7754 IBTF_DPRINTF_L5(cmlog, "ibcm_sidr_rep_ud_handler: ud_statep 0x%p",
7755 ud_statep);
7756
7960 *
7961 * INPUTS:
7962 * statep - pointer to ibcm_state_data_t
7963 * lap_msg - lap msg received
7964 * apr_msg - apr msg to be sent
7965 *
7966 * RETURN VALUE: NONE
7967 */
7968 ibcm_status_t
7969 ibcm_cep_state_lap(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
7970 ibcm_apr_msg_t *apr_msg)
7971 {
7972 ibt_cm_event_t event;
7973 ibt_cm_return_args_t ret_args;
7974 ibt_cm_status_t cb_status;
7975 ibcm_clnt_reply_info_t clnt_info;
7976
7977
7978 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: statep 0x%p", statep);
7979
7980 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg))
7981
7982 /* If APM is not supported, return error */
7983 if (!(statep->hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) {
7984 apr_msg->apr_ap_status = IBT_CM_AP_NOT_SUPPORTED;
7985 return (IBCM_SEND_APR);
7986 }
7987
7988 if (statep->local_qpn !=
7989 b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8) {
7990 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7991 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: local_qpn %x does "
7992 "not match remote's remote_qpn %x", statep->local_qpn,
7993 b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8);
7994 return (IBCM_SEND_APR);
7995 }
7996
7997 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg))
7998
7999 /* Fill up the event */
8000 bzero(&event, sizeof (event));
8001 event.cm_type = IBT_CM_EVENT_LAP_RCV;
8002 event.cm_channel = statep->channel;
8003 event.cm_session_id = statep;
8004 event.cm_priv_data = lap_msg->lap_private_data;
8005 event.cm_priv_data_len = IBT_LAP_PRIV_DATA_SZ;
8006 event.cm_event.lap.lap_timeout = ibt_ib2usec(
8007 ((uint8_t *)&lap_msg->lap_remote_qpn_eecn_plus)[3] >> 3);
8008
8009 ibcm_fill_adds_from_lap(&event.cm_event.lap.lap_alternate_path,
8010 lap_msg, IBCM_PASSIVE_MODE);
8011
8012 cb_status = statep->cm_handler(statep->state_cm_private, &event,
8013 &ret_args, apr_msg->apr_private_data, IBT_APR_PRIV_DATA_SZ);
8014
8015 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_lap: cb_status = %d", cb_status);
8016 if (cb_status == IBT_CM_DEFER) {
8017
8018 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
8019
8020 if (statep->defer_cm_msg == NULL)
8021 statep->defer_cm_msg =
8022 kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
8023 bcopy(lap_msg, statep->defer_cm_msg, IBCM_MSG_SIZE);
8024
8025 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(statep->defer_cm_msg))
8026
8027 /* unblock any blocked cm proceed api calls */
8028 mutex_enter(&statep->state_mutex);
8029 statep->clnt_proceed = IBCM_UNBLOCK;
8030 cv_broadcast(&statep->block_client_cv);
8031 mutex_exit(&statep->state_mutex);
8032
8033 return (IBCM_DEFER);
8034 }
8035
8036 clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
8037 clnt_info.priv_data = NULL;
8038 clnt_info.priv_data_len = 0;
8039
8040 ibcm_process_cep_lap_cm_hdlr(statep, cb_status, &clnt_info, lap_msg,
8041 apr_msg);
8042 return (IBCM_SEND_APR);
8043 }
8044
8045 /*
8046 * ibcm_fill_adds_from_lap:
8103
8104 /*
8105 * ibcm_process_cep_lap_cm_hdlr:
8106 * Processes the cm handler response for an incoming LAP.
8107 */
8108
8109 void
8110 ibcm_process_cep_lap_cm_hdlr(ibcm_state_data_t *statep,
8111 ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info,
8112 ibcm_lap_msg_t *lap_msg, ibcm_apr_msg_t *apr_msg)
8113 {
8114 ibtl_cm_hca_port_t port;
8115 ibt_qp_query_attr_t qp_attrs;
8116 ibt_cep_modify_flags_t cep_flags;
8117 ibt_status_t status;
8118 ibt_adds_vect_t *adds;
8119
8120 if (cb_status == IBT_CM_DEFAULT)
8121 cb_status = IBT_CM_REJECT;
8122
8123 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msg))
8124
8125 /* verify status */
8126 apr_msg->apr_addl_info_len = 0;
8127 if (cb_status == IBT_CM_ACCEPT) {
8128 apr_msg->apr_ap_status = IBT_CM_AP_LOADED;
8129 } else if (cb_status == IBT_CM_REJECT) {
8130 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8131 } else if (cb_status == IBT_CM_REDIRECT) {
8132 apr_msg->apr_ap_status = IBT_CM_AP_REDIRECT;
8133 /* copy redirect info to APR */
8134 apr_msg->apr_addl_info_len = sizeof (ibcm_classportinfo_msg_t);
8135 ibcm_init_clp_to_mad(
8136 (ibcm_classportinfo_msg_t *)apr_msg->apr_addl_info,
8137 &clnt_info->reply_event->apr);
8138 } else if (cb_status == IBT_CM_NO_RESOURCE) {
8139 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8140 } else {
8141 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p"
8142 " Client handler unexpected return %x", statep, cb_status);
8143 cb_status = IBT_CM_REJECT;
8144 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8215 status = ibt_modify_qp(statep->channel, cep_flags, &qp_attrs.qp_info,
8216 NULL);
8217
8218 if (status != IBT_SUCCESS) {
8219 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT_FAIL);
8220 } else
8221 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT);
8222
8223 #ifdef DEBUG
8224 (void) ibt_query_qp(statep->channel, &qp_attrs);
8225 print_modify_qp("PASSIVE LAP QUERY", statep->channel,
8226 cep_flags, &qp_attrs.qp_info);
8227 #endif
8228
8229 if (status != IBT_SUCCESS) {
8230 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8231 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr:"
8232 " ibt_modify_qp() returned = %d", status);
8233 return;
8234 }
8235 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msg))
8236 }
8237
8238
8239 /*
8240 * ibcm_post_apr_mad:
8241 * Posts a APR MAD and starts timer
8242 *
8243 * INPUTS:
8244 * statep - state pointer
8245 *
8246 * RETURN VALUE: NONE
8247 */
8248 void
8249 ibcm_post_apr_mad(ibcm_state_data_t *statep)
8250 {
8251 ibcm_apr_msg_t *apr_msgp;
8252
8253 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*apr_msgp))
8254
8255 apr_msgp = (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
8256
8257 apr_msgp->apr_local_comm_id = h2b32(statep->local_comid);
8258 apr_msgp->apr_remote_comm_id = h2b32(statep->remote_comid);
8259 IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
8260 h2b16(IBCM_INCOMING_APR + IBCM_ATTR_BASE_ID);
8261
8262 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*apr_msgp))
8263
8264 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_APR);
8265
8266 ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_apr_complete,
8267 statep);
8268 }
8269
8270 /*
8271 * ibcm_process_apr_msg:
8272 * This call processes an incoming APR message
8273 *
8274 * INPUTS:
8275 * hcap - HCA entry pointer
8276 * input_madp - incoming CM SIDR REP MAD
8277 * cm_mad_addr - Address information for the MAD to be posted
8278 *
8279 * RETURN VALUE: NONE
8280 */
8281 /*ARGSUSED*/
8282 void
8283 ibcm_process_apr_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
8356
8357 /* wake up blocking ibt_set_alt_path */
8358 cv_broadcast(&statep->block_client_cv);
8359
8360 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
8361 mutex_exit(&statep->state_mutex);
8362 }
8363
8364 static void
8365 ibcm_set_apr_arej(int ap_status, ibcm_apr_msg_t *apr_msgp,
8366 ibt_arej_info_t *ari, boolean_t *ari_valid)
8367 {
8368 uint8_t ari_len = apr_msgp->apr_addl_info_len;
8369 ibcm_classportinfo_msg_t tclp;
8370
8371 *ari_valid = B_FALSE;
8372
8373 IBTF_DPRINTF_L3(cmlog, "ibcm_set_apr_arej: apr_status = %d "
8374 "ari_len = %d", ap_status, ari_len);
8375
8376 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ari))
8377
8378 switch (ap_status) {
8379 case IBT_CM_AP_REDIRECT:
8380 if (ari_len < sizeof (ibcm_classportinfo_msg_t))
8381 break;
8382 *ari_valid = B_TRUE;
8383 bcopy(apr_msgp->apr_addl_info, &tclp, sizeof (tclp));
8384 ibcm_init_clp_from_mad(&tclp, &ari->ari_redirect);
8385 break;
8386 case IBT_CM_AP_RLID_REJECTED:
8387 if (ari_len < sizeof (ib_lid_t))
8388 break;
8389 *ari_valid = B_TRUE;
8390 bcopy(apr_msgp->apr_addl_info, &ari->ari_lid,
8391 sizeof (ib_lid_t));
8392 ari->ari_lid = b2h16(ari->ari_lid);
8393 break;
8394 case IBT_CM_AP_RGID_REJECTED:
8395 if (ari_len < sizeof (ib_gid_t))
8396 break;
8397 *ari_valid = B_TRUE;
8425 /* take the first byte */
8426 ari->ari_hop = apr_msgp->apr_addl_info[0];
8427 break;
8428 case IBT_CM_AP_RATE_REJECTED:
8429 if (ari_len < 1)
8430 break;
8431 *ari_valid = B_TRUE;
8432 /* take the first 6 bits */
8433 ari->ari_rate = apr_msgp->apr_addl_info[0] >> 2;
8434 break;
8435 case IBT_CM_AP_SL_REJECTED:
8436 if (ari_len < 1)
8437 break;
8438 *ari_valid = B_TRUE;
8439 /* take the first 4 bits */
8440 ari->ari_sl = apr_msgp->apr_addl_info[0] >> 4;
8441 break;
8442 default:
8443 break;
8444 }
8445 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*ari))
8446 }
8447
8448 /*
8449 * ibcm_cep_state_apr:
8450 * This call processes an incoming APR message
8451 *
8452 * INPUTS:
8453 * statep - pointer to ibcm_state_data_t
8454 * lap_msg - lap msg sent earlier
8455 * apr_msg - apr msg received
8456 *
8457 * RETURN VALUE: NONE
8458 */
8459 void
8460 ibcm_cep_state_apr(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
8461 ibcm_apr_msg_t *apr_msg)
8462 {
8463 ibt_cm_event_t event;
8464 ibcm_status_t status = IBCM_SUCCESS;
8465 uint8_t ap_status = apr_msg->apr_ap_status;
8643 *
8644 * INPUTS:
8645 * statep Pointer to ibcm_state_data_t
8646 *
8647 * RETURN VALUE: NONE
8648 *
8649 * This function is called holding state mutex
8650 * This function returns, releasing the state mutex
8651 */
8652 void
8653 ibcm_sync_lapr_idle(ibcm_state_data_t *statep)
8654 {
8655 timeout_id_t timer_val = statep->timerid;
8656 ibt_cm_event_t event;
8657
8658 IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:"
8659 "statep %p state %d ap_state %d", statep, statep->state,
8660 statep->ap_state);
8661
8662 ASSERT(MUTEX_HELD(&statep->state_mutex));
8663 _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&statep->state_mutex))
8664
8665 /* Busy AP states on active/passive sides */
8666 if ((statep->ap_state == IBCM_AP_STATE_LAP_RCVD) ||
8667 (statep->ap_state == IBCM_AP_STATE_APR_RCVD) ||
8668 (statep->ap_state == IBCM_AP_STATE_MRA_LAP_SENT) ||
8669 (statep->ap_state == IBCM_AP_STATE_TIMED_OUT)) {
8670
8671 /* wait till ap_state becomes IBCM_AP_STATE_IDLE */
8672 while (statep->ap_state != IBCM_AP_STATE_IDLE)
8673 cv_wait(&statep->block_mad_cv, &statep->state_mutex);
8674
8675 mutex_exit(&statep->state_mutex);
8676
8677 } else if ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) ||
8678 (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) {
8679
8680 /* fail the client's ibt_set_alt_path */
8681
8682 /* blocking ibt_set_alt_path */
8683 if (statep->ap_return_data != NULL) {
|
467 int ibcm_recv_tasks = 0;
468 int ibcm_max_recv_tasks = 24;
469 int ibcm_recv_timeouts = 0;
470
471 /*
472 * Tunable MAX MRA Service Timeout value in MicroSECONDS.
473 * 0 - Tunable parameter not used.
474 *
475 * Ex: 60000000 - Max MRA Service Delay is 60 Seconds.
476 */
477 clock_t ibcm_mra_service_timeout_max = 0;
478
479 #ifdef DEBUG
480
481 static void print_modify_qp(char *prefix,
482 ibt_qp_hdl_t ibt_qp,
483 ibt_cep_modify_flags_t flags,
484 ibt_qp_info_t *qp_attr);
485 #endif
486
487 /*
488 * ibcm_process_incoming_mad:
489 * The CM callback that is invoked by IBMF, when a valid CM MAD arrives
490 * on any of the registered ibmf handles by CM.
491 *
492 * It is assumed that the incoming MAD (except for incoming REQ) belongs
493 * to a connection on the HCA, on which the MAD is received.
494 * The IBMF callback arg specifies ibcm_hca_info_t
495 *
496 * NOTE: IBMF always invokes ibcm_recv_cb() in a taskq. CM does some memory
497 * allocations and invoke ibcm_sm_funcs_tbl[i]() in the same taskq.
498 *
499 * INPUTS:
500 * ibmf_handle - IBMF Handle
501 * args - from IBMF. Is a ptr to ibcm_hca_info_t
502 * status - Callback status. Is mostly IBMF_SUCCESS
503 * madbuf - IBMF allocated MAD buffer (CM should free it)
504 * madaddr - IBMF MAD's address
505 * grhvalid - If GRH is valid or not
506 *
545 #endif
546
547 portp = cm_qp_entry->qp_port;
548 hcap = portp->port_hcap;
549
550 IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: CM MAD on "
551 "port %d", portp->port_num);
552
553 /* Increment hca ref cnt, if HCA is in attached state, else fail */
554 if (ibcm_inc_hca_acc_cnt(hcap) != IBCM_SUCCESS) {
555 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
556 "hca not in attach state");
557 /* IBMF allocates Input MAD, and ibcm free's it */
558 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
559 IBMF_SUCCESS)
560 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
561 "ibmf_free_msg failed %d", ibmf_status);
562 return;
563 }
564
565 /* allocate memory for internal MAD address buffer */
566 cm_mad_addr = &loc_mad_addr;
567 bzero(cm_mad_addr, sizeof (ibcm_mad_addr_t));
568
569 cm_mad_addr->port_num = portp->port_num;
570
571 /* initialize cm_mad_addr field(s) */
572 in_mad_hdr = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
573
574 if (in_mad_hdr->MgmtClass != MAD_MGMT_CLASS_COMM_MGT) {
575 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
576 "bad mgmt class %x", in_mad_hdr->MgmtClass);
577 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
578 IBMF_SUCCESS)
579 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
580 "ibmf_free_msg failed %d", ibmf_status);
581 ibcm_dec_hca_acc_cnt(hcap);
582 return;
583 }
584
623
624 if (attr_id == (IBCM_INCOMING_REQ + IBCM_ATTR_BASE_ID))
625 ibcm_post_rej_ver_mismatch(
626 (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
627
628 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) !=
629 IBMF_SUCCESS)
630 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
631 "ibmf_free_msg failed %d", ibmf_status);
632 ibcm_dec_hca_acc_cnt(hcap);
633 return;
634 }
635
636 IBTF_DPRINTF_L4(cmlog, "ibcm_process_incoming_mad: "
637 "Transaction Id 0x%llX", b2h64(in_mad_hdr->TransactionID));
638
639 #ifdef DEBUG
640 ibcm_decode_tranid(b2h64(in_mad_hdr->TransactionID), NULL);
641 #endif
642
643 /*
644 * The following are valid combination of Method type
645 * and attribute id in the received MAD :-
646 * o ClassPortInfo with Get method
647 * o CM messages with Send method
648 */
649 if ((attr_id == MAD_ATTR_ID_CLASSPORTINFO) &&
650 ((method == MAD_METHOD_GET) ||
651 (method == MAD_METHOD_GET_RESPONSE))) {
652 if (method == MAD_METHOD_GET)
653 ibcm_process_get_classport_info(hcap,
654 (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
655 else if (method == MAD_METHOD_GET_RESPONSE)
656 ibcm_decode_classport_info(hcap,
657 (uint8_t *)IBCM_IN_HDRP(msgp), cm_mad_addr);
658 } else if ((attr_id >= IBCM_ATTR_BASE_ID) &&
659 (attr_id < (IBCM_ATTR_BASE_ID + IBCM_MAX_EVENTS)) &&
660 (method == MAD_METHOD_SEND)) {
661
662 attr_id -= IBCM_ATTR_BASE_ID; /* figure out CM message id */
685 IBTF_DPRINTF_L2(cmlog, "ibcm_process_incoming_mad: "
686 "ibmf_free_msg failed %d", ibmf_status);
687 }
688
689 /*
690 * Structure to carry the arguments from ibcm_recv_cb() to
691 * ibcm_recv_incoming_mad() via taskq_dispatch
692 */
693 typedef struct ibcm_taskq_args_s {
694 ibmf_handle_t tq_ibmf_handle;
695 ibmf_msg_t *tq_ibmf_msgp;
696 void *tq_args;
697 } ibcm_taskq_args_t;
698
699 #define IBCM_RECV_MAX 128
700 ibcm_taskq_args_t ibcm_recv_array[IBCM_RECV_MAX + 1];
701 int ibcm_get, ibcm_put;
702 int ibcm_recv_total;
703 int ibcm_recv_queued;
704
705 static int
706 ibcm_recv_dequeue(ibmf_handle_t *ibmf_handlep, ibmf_msg_t **msgpp, void **argsp)
707 {
708 ibcm_taskq_args_t *tq;
709
710 if (ibcm_put == ibcm_get)
711 return (0);
712
713 if (++ibcm_get >= IBCM_RECV_MAX)
714 ibcm_get = 0;
715 tq = ibcm_recv_array + ibcm_get;
716 *ibmf_handlep = tq->tq_ibmf_handle;
717 *msgpp = tq->tq_ibmf_msgp;
718 *argsp = tq->tq_args;
719 return (1);
720 }
721
722 static int
723 ibcm_recv_enqueue(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp, void *args)
724 {
725 int next;
726 ibcm_taskq_args_t *tq;
727
728 ASSERT(MUTEX_HELD(&ibcm_recv_mutex));
729 next = ibcm_put + 1;
730 if (next >= IBCM_RECV_MAX)
731 next = 0;
732 if (next != ibcm_get) {
733 ibcm_recv_queued++;
734 ibcm_put = next;
735 tq = ibcm_recv_array + next;
736 tq->tq_ibmf_handle = ibmf_handle;
737 tq->tq_ibmf_msgp = msgp;
738 tq->tq_args = args;
739 return (1);
740 } else {
741 return (0);
742 }
743 }
744
745 void
746 ibcm_drop_msg(ibmf_handle_t ibmf_handle, ibmf_msg_t *msgp)
747 {
748 int ibmf_status;
749
750 IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: discarding MAD");
751
752 if ((ibmf_status = ibmf_free_msg(ibmf_handle, &msgp)) != IBMF_SUCCESS)
753 IBTF_DPRINTF_L2(cmlog, "ibcm_drop_msg: "
754 "ibmf_free_msg failed %d", ibmf_status);
755 }
756
757 /*
758 * Processing done in taskq thread.
838
839 mutex_enter(&ibcm_recv_mutex);
840 ibcm_recv_total++;
841 if (ibcm_recv_tasks >= ibcm_max_recv_tasks) { /* just queue this one */
842 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
843 mutex_exit(&ibcm_recv_mutex);
844 return (rv);
845 } else {
846 ibcm_recv_tasks++; /* dispatch this one to a taskq thread */
847 mutex_exit(&ibcm_recv_mutex);
848 tq = kmem_alloc(sizeof (*tq), KM_NOSLEEP);
849 if (tq == NULL) {
850 mutex_enter(&ibcm_recv_mutex);
851 if (--ibcm_recv_tasks > 0)
852 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
853 else /* don't enqueue if no threads are running */
854 rv = 0;
855 mutex_exit(&ibcm_recv_mutex);
856 return (rv);
857 }
858 tq->tq_ibmf_handle = ibmf_handle;
859 tq->tq_ibmf_msgp = msgp;
860 tq->tq_args = args;
861 if (taskq_dispatch(ibcm_taskq, ibcm_recv_task, tq,
862 TQ_NOQUEUE | TQ_NOSLEEP) == 0) { /* dispatch failed */
863 mutex_enter(&ibcm_recv_mutex);
864 if (--ibcm_recv_tasks == 0) {
865 /* try the dispatch again, after a tick */
866 (void) timeout(ibcm_recv_timeout_cb, tq, 1);
867 ibcm_recv_timeouts++;
868 rv = 1; /* indicate success */
869 } else {
870 rv = ibcm_recv_enqueue(ibmf_handle, msgp, args);
871 kmem_free(tq, sizeof (*tq));
872 }
873 mutex_exit(&ibcm_recv_mutex);
874 return (rv);
875 } else {
876 return (1);
877 }
878 }
879 }
880
949 hcap, input_madp, cm_mad_addr);
950
951 /*
952 * Lookup for an existing state structure or create a new state struct
953 * If there is no entry, the lookup function also allocates a new
954 * state structure and inserts in the table, initializes remote qpn
955 * and hca guid from REQ
956 */
957 remote_hca_guid = b2h64(req_msgp->req_local_ca_guid);
958 remote_qpn = b2h32(req_msgp->req_local_qpn_plus) >> 8;
959 remote_comid = b2h32(req_msgp->req_local_comm_id);
960
961 IBCM_DUMP_RAW_MSG((uchar_t *)input_madp);
962
963 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_comid = %x"
964 " remote_qpn = %x", remote_comid, remote_qpn);
965
966 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: remote_hcaguid = %llX",
967 remote_hca_guid);
968
969 new_req:
970 /* allocate the local_comid before proceeding */
971 if (ibcm_alloc_comid(hcap, &local_comid) != IBCM_SUCCESS) {
972 ibcm_build_n_post_rej_mad(input_madp,
973 b2h32(req_msgp->req_local_comm_id), cm_mad_addr,
974 IBT_CM_FAILURE_REQ, IBT_CM_NO_RESC);
975 return;
976 }
977
978 /* allocate ibcm_state_data_t before grabbing the WRITER lock */
979 statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
980
981 rw_enter(&hcap->hca_state_rwlock, RW_WRITER);
982
983 /* NOTE that only a writer lock is held here */
984
985 state_lookup_status = ibcm_lookup_msg(IBCM_INCOMING_REQ,
986 local_comid, remote_qpn, remote_hca_guid, hcap, &statep);
987
988 if (state_lookup_status == IBCM_LOOKUP_NEW) {
989 /* seeing the REQ request for the first time */
990
991 mutex_enter(&statep->state_mutex);
992 /* Release the state table lock */
993 rw_exit(&hcap->hca_state_rwlock);
994
995 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: New statep 0x%p"
996 " created", statep);
997
998 psn24_timeout5_retry3 = b2h32(req_msgp->req_starting_psn_plus);
999
1000 /* if ibmf msg allocation fails, delete the statep */
1001 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1002 &statep->stored_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1003
1004 IBCM_REF_CNT_DECR(statep);
1005 statep->state = IBCM_STATE_DELETE;
1006 mutex_exit(&statep->state_mutex);
1007 /* HCA res cnt decremented via ibcm_delete_state_data */
1008 ibcm_inc_hca_res_cnt(hcap);
1009 ibcm_delete_state_data(statep);
1010 return;
1011 }
1012
1013 /* Allocate dreq_msg buf to be used during teardown. */
1014 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
1015 &statep->dreq_msg, MAD_METHOD_SEND) != IBT_SUCCESS) {
1016
1017 IBCM_REF_CNT_DECR(statep);
1018 statep->state = IBCM_STATE_DELETE;
1019 mutex_exit(&statep->state_mutex);
1218 /* REJ posted from ibcm_verify_req_gids_and_svcid */
1219 return;
1220 }
1221
1222 /* Call the QP state transition processing function */
1223 response = ibcm_cep_state_req(statep, req_msgp,
1224 &reject_reason, &arej_info_len);
1225
1226 /* If defer, return holding the statep ref cnt */
1227 if (response == IBCM_DEFER) {
1228 IBTF_DPRINTF_L4(cmlog, "ibcm_process_req_msg: "
1229 "statep %0xp client returned DEFER response",
1230 statep);
1231 return;
1232 }
1233
1234 /* statep ref cnt decremented in the func below */
1235 ibcm_handle_cep_req_response(statep, response,
1236 reject_reason, arej_info_len);
1237
1238 return;
1239
1240 } else {
1241 rw_exit(&hcap->hca_state_rwlock);
1242 ibcm_free_comid(hcap, local_comid);
1243 }
1244
1245 if (state_lookup_status == IBCM_LOOKUP_EXISTS) {
1246 hrtime_t cur_time;
1247
1248 mutex_enter(&statep->state_mutex);
1249
1250 /*
1251 * There is an existing state structure entry
1252 * with the same active comid
1253 * Resending REP MAD is necessary only for REP/REJ/MRA Sent
1254 * states
1255 * Any other state implies the active has already received
1256 * the REP/REJ response, and this REQ is an old MAD popping
1257 * out of the fabric, hence no resend is required
1358 ibcm_build_n_post_rej_mad(input_madp,
1359 b2h32(req_msgp->req_local_comm_id),
1360 cm_mad_addr, IBT_CM_FAILURE_REQ, IBT_CM_CONN_STALE);
1361
1362 mutex_enter(&statep->state_mutex);
1363 }
1364 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
1365 mutex_exit(&statep->state_mutex);
1366 }
1367 }
1368
1369 /*
1370 * ibcm_handle_cep_req_response:
1371 * Processes the response from ibcm_cep_state_req. Called holding a
1372 * statep ref cnt. The statep ref cnt is decremented before returning.
1373 */
1374 void
1375 ibcm_handle_cep_req_response(ibcm_state_data_t *statep, ibcm_status_t response,
1376 ibt_cm_reason_t reject_reason, uint8_t arej_info_len)
1377 {
1378 if (response == IBCM_SEND_REP)
1379 ibcm_post_rep_mad(statep);
1380 else {
1381 ASSERT(response == IBCM_SEND_REJ);
1382 IBTF_DPRINTF_L4(cmlog, "ibcm_handle_cep_req_response: statep %p"
1383 " posting REJ reject_reason = %d", statep, reject_reason);
1384
1385 ibcm_post_rej_mad(statep,
1386 reject_reason, IBT_CM_FAILURE_REQ,
1387 NULL, arej_info_len);
1388 }
1389
1390 mutex_enter(&statep->state_mutex);
1391 IBCM_REF_CNT_DECR(statep);
1392 mutex_exit(&statep->state_mutex);
1393 }
1394
1395
1396 /*
1397 * ibcm_process_rep_msg:
1398 * ACTIVE SIDE CM
1399 * Called from ibcm_process_incoming_mad on reception of a REP message
1400 *
1401 * INPUTS:
1402 * hcap - HCA entry pointer
1403 * input_madp - CM MAD that is input to this function
1404 * cm_mad_addr - Address information for the MAD
1405 *
1406 * RETURN VALUE: NONE
1407 */
1408 void
1409 ibcm_process_rep_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
1487 ibcm_resend_mra_mad(statep);
1488 else if ((statep->state == IBCM_STATE_REQ_SENT) ||
1489 (statep->state == IBCM_STATE_REP_WAIT)) {
1490
1491 /* change state */
1492 statep->state = IBCM_STATE_REP_RCVD;
1493 statep->clnt_proceed = IBCM_BLOCK;
1494 statep->local_qp_rnr_cnt =
1495 rep_msgp->rep_rnr_retry_cnt_plus >> 5;
1496
1497 /* cancel the REQ timer */
1498 if (statep->timerid != 0) {
1499 timer_val = statep->timerid;
1500 statep->timerid = 0;
1501 mutex_exit(&statep->state_mutex);
1502 (void) untimeout(timer_val);
1503 } else {
1504 mutex_exit(&statep->state_mutex);
1505 }
1506
1507 /* Initialize the remote destination QPN for further MADs */
1508 statep->stored_reply_addr.rcvd_addr.ia_remote_qno =
1509 cm_mad_addr->rcvd_addr.ia_remote_qno;
1510 statep->remote_qpn = b2h32(rep_msgp->rep_local_qpn_plus) >> 8;
1511 statep->remote_comid = b2h32(rep_msgp->rep_local_comm_id);
1512 bcopy(rep_msgp->rep_local_ca_guid, &remote_ca_guid,
1513 sizeof (ib_guid_t));
1514 statep->remote_hca_guid = b2h64(remote_ca_guid);
1515
1516 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1517 "passive cid = %x passive qpn = %x", statep,
1518 statep->remote_comid, statep->remote_qpn);
1519
1520 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p "
1521 "passive hcaguid = %llX", statep, statep->remote_hca_guid);
1522
1523 stale_qpn = statep;
1524 stale_comid = statep;
1525
1526 /* Handle stale connection detection on active side */
1714 /* Initialize the remote ack delay */
1715 statep->remote_ack_delay =
1716 ibt_ib2usec(rep_msgp->rep_target_delay_plus >> 3);
1717
1718 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: statep 0x%p"
1719 " passive hca_ack_delay= %x ", statep,
1720 statep->remote_ack_delay);
1721
1722 response = ibcm_cep_state_rep(statep, rep_msgp,
1723 &reject_reason, &arej_info_len);
1724
1725 if (response == IBCM_DEFER) {
1726 IBTF_DPRINTF_L4(cmlog, "ibcm_process_rep_msg: "
1727 "statep 0x%p client returned DEFER response",
1728 statep);
1729 return;
1730 }
1731 ibcm_handle_cep_rep_response(statep, response,
1732 reject_reason, arej_info_len, rep_msgp);
1733
1734 return;
1735
1736 } else if (statep->state == IBCM_STATE_DELETE) {
1737
1738 mutex_exit(&statep->state_mutex);
1739 ibcm_build_n_post_rej_mad(input_madp,
1740 b2h32(rep_msgp->rep_local_comm_id), cm_mad_addr,
1741 IBT_CM_FAILURE_REP, IBT_CM_INVALID_CID);
1742 mutex_enter(&statep->state_mutex);
1743 } else {
1744
1745 #ifdef DEBUG
1746 if (ibcm_test_mode > 0)
1747 if (statep->state == IBCM_STATE_REP_RCVD)
1748 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1749 "REP re-send from passive for statep 0x%p"
1750 " in state %d", statep, statep->state);
1751 else
1752 IBTF_DPRINTF_L2(cmlog, "ibcm_process_rep_msg: "
1753 "Unexpected REP for statep 0x%p in "
2594
2595 /*
2596 * ibcm_post_dreq_mad:
2597 * Posts a DREQ MAD
2598 * Post DREQ now for TIMEWAIT state and DREQ_RCVD
2599 *
2600 * INPUTS:
2601 * statep - state pointer
2602 *
2603 * RETURN VALUE:
2604 * NONE
2605 */
2606 void
2607 ibcm_post_dreq_mad(void *vstatep)
2608 {
2609 ibcm_state_data_t *statep = vstatep;
2610 ibcm_dreq_msg_t *dreq_msgp;
2611
2612 ASSERT(statep->dreq_msg != NULL);
2613
2614 /* Fill in the DREQ message */
2615 dreq_msgp = (ibcm_dreq_msg_t *)IBCM_OUT_MSGP(statep->dreq_msg);
2616 dreq_msgp->dreq_local_comm_id = h2b32(statep->local_comid);
2617 dreq_msgp->dreq_remote_comm_id = h2b32(statep->remote_comid);
2618 dreq_msgp->dreq_remote_qpn_eecn_plus = h2b32(statep->remote_qpn << 8);
2619
2620 IBCM_OUT_HDRP(statep->dreq_msg)->AttributeID =
2621 h2b16(IBCM_INCOMING_DREQ + IBCM_ATTR_BASE_ID);
2622
2623 /* wait until client knows CONN EST event */
2624 mutex_enter(&statep->state_mutex);
2625 while (statep->cep_in_rts == IBCM_BLOCK)
2626 cv_wait(&statep->block_mad_cv, &statep->state_mutex);
2627 mutex_exit(&statep->state_mutex);
2628
2629 /* Transition QP/EEC state to ERROR state */
2630 (void) ibcm_cep_to_error_state(statep);
2631
2632 IBCM_OUT_HDRP(statep->dreq_msg)->TransactionID =
2633 h2b64(ibcm_generate_tranid(IBCM_INCOMING_DREQ, statep->local_comid,
2634 0));
2635
2636 /* post the first DREQ via timeout callback */
2637 mutex_enter(&statep->state_mutex);
2638
2639 statep->state = IBCM_STATE_DREQ_SENT;
2640 cv_broadcast(&statep->block_mad_cv);
2641
2642 statep->timer_stored_state = statep->state;
2643 /* client cannot specify more than 16 retries */
2644 statep->timer_value = statep->remote_ack_delay;
2645 if (statep->mode == IBCM_ACTIVE_MODE) {
2646 statep->timer_value += (2 * statep->pkt_life_time);
2647 }
2648 statep->remaining_retry_cnt = statep->max_cm_retries + 1;
2649 statep->timerid = IBCM_TIMEOUT(statep, 0);
2650 mutex_exit(&statep->state_mutex);
2651 }
2652
2653 /*
2654 * ibcm_post_drep_mad:
2655 * Posts a DREP MAD
2656 * Post DREP now for TIMEWAIT state and DREQ_RCVD
2657 *
2658 * INPUTS:
2659 * statep - state pointer
2660 *
2661 * RETURN VALUE:
2662 * NONE
2663 */
2664 static void
2665 ibcm_post_drep_mad(ibcm_state_data_t *statep)
2666 {
2667 ibcm_drep_msg_t *drep_msgp;
2668
2669 drep_msgp = (ibcm_drep_msg_t *)IBCM_OUT_MSGP(statep->drep_msg);
2670
2671 IBTF_DPRINTF_L4(cmlog, "ibcm_post_drep_mad:");
2672
2673 /* Fill up DREP fields */
2674 drep_msgp->drep_local_comm_id = h2b32(statep->local_comid);
2675 drep_msgp->drep_remote_comm_id = h2b32(statep->remote_comid);
2676 IBCM_OUT_HDRP(statep->drep_msg)->AttributeID =
2677 h2b16(IBCM_INCOMING_DREP + IBCM_ATTR_BASE_ID);
2678
2679 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_DREP);
2680
2681 /* Post the DREP MAD now. */
2682 ibcm_post_rc_mad(statep, statep->drep_msg, ibcm_post_drep_complete,
2683 statep);
2684 }
2685
2686 /*
2687 * ibcm_process_drep_msg:
2688 * Processes incoming DREP message on active/passive side
2689 *
2690 * INPUTS:
2691 * hcap - HCA entry pointer
2692 * input_madp - CM MAD that is input to this function
2693 * cm_mad_addr - Address information for the MAD
2694 *
2695 * RETURN VALUE: NONE
2696 */
2697 /* ARGSUSED */
2698 void
2973 * RETURN VALUE:
2974 * NONE
2975 * Notes
2976 * There is no need to hold the statep->mutex and call ibcm_post_rej_mad
2977 * REJ can be posted either in IBCM_STATE_REQ_RCVD or IBCM_STATE_REP_RCVD
2978 * In these states, there is no timer active, and an incoming REJ shall
2979 * not modify the state or cancel timers
2980 * An incoming REJ doesn't affect statep in state = IBCM_STATE_REJ_SENT/BUSY
2981 */
2982 void
2983 ibcm_post_rej_mad(ibcm_state_data_t *statep, ibt_cm_reason_t reject_reason,
2984 int which_msg, void *addl_rej_info, ibt_priv_data_len_t arej_info_len)
2985 {
2986 ibcm_rej_msg_t *rej_msg =
2987 (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
2988
2989 /* Message printed if connection gets REJed */
2990 IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_mad: "
2991 "statep = %p, reject_reason = %d", statep, reject_reason);
2992
2993 /* Initialize rej_msg fields */
2994 rej_msg->rej_local_comm_id = h2b32(statep->local_comid);
2995 rej_msg->rej_remote_comm_id = h2b32(statep->remote_comid);
2996 rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
2997 rej_msg->rej_reject_info_len_plus = arej_info_len << 1;
2998 rej_msg->rej_rejection_reason = h2b16((uint16_t)reject_reason);
2999
3000 if ((arej_info_len != 0) && (addl_rej_info != NULL))
3001 bcopy(addl_rej_info, rej_msg->rej_addl_rej_info, arej_info_len);
3002
3003 IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3004 h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3005
3006 mutex_enter(&statep->state_mutex);
3007
3008 /* signal any waiting close channels with blocking or no callbacks */
3009 statep->close_done = B_TRUE;
3010 statep->close_nocb_state = IBCM_FAIL;
3011
3012 cv_signal(&statep->block_client_cv);
3013
3014 statep->timer_stored_state = statep->state = IBCM_STATE_REJ_SENT;
3015 statep->send_mad_flags |= IBCM_REJ_POST_BUSY;
3016
3017 IBCM_REF_CNT_INCR(statep); /* for non-blocking post */
3018 mutex_exit(&statep->state_mutex);
3019
3020 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_REJ);
3021 if (ibcm_enable_trace & 2)
3022 ibcm_dump_conn_trace(statep);
3023 else
3024 IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_mad statep %p "
3025 "OUTGOING_REJ", statep);
3044 * NONE
3045 */
3046 static void
3047 ibcm_build_n_post_rej_mad(uint8_t *input_madp, ib_com_id_t remote_comid,
3048 ibcm_mad_addr_t *cm_mad_addr, int which_msg, uint16_t reject_reason)
3049 {
3050 ibcm_rej_msg_t *rej_msg;
3051 ibmf_msg_t *cm_rej_msg;
3052 ibcm_mad_addr_t rej_reply_addr;
3053
3054 IBTF_DPRINTF_L3(cmlog, "ibcm_build_n_post_rej_mad: "
3055 "remote_comid: %x reject_reason %d", remote_comid, reject_reason);
3056
3057 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3058 MAD_METHOD_SEND) != IBT_SUCCESS) {
3059 IBTF_DPRINTF_L2(cmlog, "ibcm_build_n_post_rej_mad: "
3060 "ibcm_alloc_out_msg failed");
3061 return;
3062 }
3063
3064 IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3065 ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3066
3067 /* Initialize rej_msg fields */
3068 rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3069 rej_msg->rej_local_comm_id = 0;
3070 rej_msg->rej_remote_comm_id = h2b32(remote_comid);
3071 rej_msg->rej_msg_type_plus = (which_msg & 0x3) << 6;
3072 rej_msg->rej_reject_info_len_plus = 0;
3073 rej_msg->rej_rejection_reason = h2b16(reject_reason);
3074
3075 IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3076 h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3077
3078 ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3079
3080 if (rej_reply_addr.cm_qp_entry != NULL) {
3081 (void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3082 ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3083 }
3084
3085 (void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3086 }
3087
3088 /* posts a REJ for an incoming REQ with unsupported class version */
3089
3090 static void
3091 ibcm_post_rej_ver_mismatch(uint8_t *input_madp, ibcm_mad_addr_t *cm_mad_addr)
3092 {
3093 ibcm_req_msg_t *req_msgp =
3094 (ibcm_req_msg_t *)&input_madp[IBCM_MAD_HDR_SIZE];
3095 ibcm_rej_msg_t *rej_msg;
3096 ibmf_msg_t *cm_rej_msg;
3097 ibcm_mad_addr_t rej_reply_addr;
3098
3099 IBTF_DPRINTF_L3(cmlog, "ibcm_post_rej_ver_mismatch: remote comid %x",
3100 b2h32(req_msgp->req_local_comm_id));
3101
3102 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg,
3103 MAD_METHOD_SEND) != IBT_SUCCESS) {
3104 IBTF_DPRINTF_L2(cmlog, "ibcm_post_rej_ver_mismatch: "
3105 "ibcm_alloc_out_msg failed");
3106 return;
3107 }
3108
3109 IBCM_OUT_HDRP(cm_rej_msg)->TransactionID =
3110 ((ib_mad_hdr_t *)(input_madp))->TransactionID;
3111
3112 /* Initialize rej_msg fields */
3113 rej_msg = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(cm_rej_msg);
3114 rej_msg->rej_local_comm_id = 0;
3115 rej_msg->rej_remote_comm_id = req_msgp->req_local_comm_id;
3116 rej_msg->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
3117 rej_msg->rej_rejection_reason = h2b16(IBT_CM_CLASS_NO_SUPPORT);
3118 rej_msg->rej_reject_info_len_plus = 1 << 1;
3119 rej_msg->rej_addl_rej_info[0] = IBCM_MAD_CLASS_VERSION;
3120
3121 IBCM_OUT_HDRP(cm_rej_msg)->AttributeID =
3122 h2b16(IBCM_INCOMING_REJ + IBCM_ATTR_BASE_ID);
3123 IBCM_OUT_HDRP(cm_rej_msg)->Status = h2b16(MAD_STATUS_BAD_VERSION);
3124
3125 ibcm_build_reply_mad_addr(cm_mad_addr, &rej_reply_addr);
3126 if (rej_reply_addr.cm_qp_entry != NULL) {
3127 (void) ibcm_post_mad(cm_rej_msg, &rej_reply_addr, NULL, NULL);
3128 ibcm_release_qp(rej_reply_addr.cm_qp_entry);
3129 }
3130 (void) ibcm_free_out_msg(cm_mad_addr->ibmf_hdl, &cm_rej_msg);
3131 }
3132
3133
3134 /*
3135 * ibcm_post_rep_mad:
3136 * Posts a REP MAD and starts timer
3137 *
3138 * INPUTS:
3139 * statep - state pointer
3140 *
3141 * RETURN VALUE:
3142 * NONE
3143 */
3144 void
3145 ibcm_post_rep_mad(ibcm_state_data_t *statep)
3146 {
3147 ibcm_rep_msg_t *rep_msgp =
3148 (ibcm_rep_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3149 ibmf_msg_t *mra_msg = NULL;
3150 boolean_t ret = B_FALSE;
3151
3152 IBTF_DPRINTF_L4(cmlog, "ibcm_post_rep_mad: statep 0x%p", statep);
3153
3154 /*
3155 * All other REP fields, other that the 2 below, are filled in
3156 * the ibcm_cep_state_req() function.
3157 */
3158 rep_msgp->rep_local_comm_id = h2b32(statep->local_comid);
3159 rep_msgp->rep_remote_comm_id = h2b32(statep->remote_comid);
3160 IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3161 h2b16(IBCM_INCOMING_REP + IBCM_ATTR_BASE_ID);
3162
3163 /*
3164 * Changing state and attempt to delete the mra msg must be done
3165 * together holding the state_mutex
3166 */
3167 mutex_enter(&statep->state_mutex);
3168
3169 /* Now, attempt to delete the mra_msg, if there is one allocated */
3170 if (statep->mra_msg != NULL) {
3171 if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3172 mra_msg = statep->mra_msg;
3173 statep->mra_msg = NULL;
3174 } else statep->delete_mra_msg = B_TRUE;
3175 }
3176
3177 if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3178 statep->state = IBCM_STATE_ABORTED;
3179 mutex_exit(&statep->state_mutex);
3180 ibcm_process_abort(statep);
3181
3182 /* Now post a REJ MAD, rej reason consumer abort */
3217 /*
3218 * ibcm_post_rtu_mad:
3219 * From active side post RTU MAD
3220 *
3221 * INPUTS:
3222 * statep - state pointer
3223 *
3224 * RETURN VALUE: NONE
3225 *
3226 * NOTE: No timer set after posting RTU
3227 */
3228 ibcm_status_t
3229 ibcm_post_rtu_mad(ibcm_state_data_t *statep)
3230 {
3231 ibcm_rtu_msg_t *rtu_msg;
3232 ibmf_msg_t *mra_msg = NULL;
3233 boolean_t ret = B_FALSE;
3234
3235 IBTF_DPRINTF_L4(cmlog, "ibcm_post_rtu_mad: statep 0x%p", statep);
3236
3237 rtu_msg = (ibcm_rtu_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
3238
3239 rtu_msg->rtu_local_comm_id = h2b32(statep->local_comid);
3240 rtu_msg->rtu_remote_comm_id = h2b32(statep->remote_comid);
3241 IBCM_OUT_HDRP(statep->stored_msg)->AttributeID =
3242 h2b16(IBCM_INCOMING_RTU + IBCM_ATTR_BASE_ID);
3243
3244 mutex_enter(&statep->state_mutex);
3245
3246 /* Now, attempt to delete the mra_msg, if there is one allocated */
3247 if (statep->mra_msg != NULL) {
3248 if (!(statep->send_mad_flags & IBCM_MRA_POST_BUSY)) {
3249 mra_msg = statep->mra_msg;
3250 statep->mra_msg = NULL;
3251 } else statep->delete_mra_msg = B_TRUE;
3252 }
3253
3254 if (statep->abort_flag == IBCM_ABORT_CLIENT) {
3255 statep->state = IBCM_STATE_ABORTED;
3256 mutex_exit(&statep->state_mutex);
3257
3258 ibcm_process_abort(statep);
3259
3260 /* Now post a REJ MAD */
3261 ibcm_post_rej_mad(statep, IBT_CM_CONSUMER, IBT_CM_FAILURE_REP,
3262 NULL, 0);
3263 ret = B_TRUE;
3410 mutex_exit(&statep->state_mutex);
3411
3412 /* Deallocate the CM state structure */
3413 ibcm_delete_state_data(statep);
3414 return;
3415
3416 } else if (statep->state == IBCM_STATE_TIMEWAIT) {
3417 statep->state = IBCM_STATE_DELETE;
3418
3419 /* TIME_WAIT timer expired, so cleanup */
3420 mutex_exit(&statep->state_mutex);
3421
3422 if (statep->channel)
3423 ibtl_cm_chan_is_closed(statep->channel);
3424
3425 if (statep->recycle_arg) {
3426 struct ibcm_taskq_recycle_arg_s *recycle_arg;
3427
3428 recycle_arg = statep->recycle_arg;
3429
3430 statep->recycle_arg = NULL;
3431
3432 /* if possible, do not slow down calling recycle func */
3433 if (taskq_dispatch(ibcm_taskq, ibcm_process_rc_recycle,
3434 recycle_arg, TQ_NOQUEUE | TQ_NOSLEEP) == 0) {
3435 statep->recycle_arg = recycle_arg;
3436 ibcm_add_tlist(statep);
3437 return;
3438 }
3439 }
3440
3441 ibcm_delete_state_data(statep);
3442 return;
3443 } else if (statep->remaining_retry_cnt > 0) {
3444 ibcm_conn_state_t stored_state;
3445 ibcm_ap_state_t stored_ap_state;
3446
3447 statep->remaining_retry_cnt--;
3448 IBTF_DPRINTF_L3(cmlog, "ibcm_timeout_cb: statep 0x%p "
3449 "attr-id= 0x%x, retries remaining = 0x%x", statep,
3450 b2h16(IBCM_OUT_HDRP(statep->stored_msg)->AttributeID),
3451 statep->remaining_retry_cnt);
3452
3453 /*
3454 * REP could be resent, either because of timeout or an
3455 * incoming REQ. Any other MAD below can be resent, because
4180 ud_statep = ibcm_ud_timeout_list_hdr;
4181 ibcm_ud_timeout_list_hdr = ud_statep->ud_timeout_next;
4182
4183 if (ibcm_ud_timeout_list_hdr == NULL)
4184 ibcm_ud_timeout_list_tail = NULL;
4185
4186 ud_statep->ud_timeout_next = NULL;
4187
4188 mutex_exit(&ibcm_timeout_list_lock);
4189 IBTF_DPRINTF_L3(cmlog, "ibcm_process_tlist: "
4190 "ud scheduling state = %p", ud_statep);
4191 ibcm_ud_timeout_client_cb(ud_statep);
4192 mutex_enter(&ibcm_timeout_list_lock);
4193 } else {
4194 CALLB_CPR_SAFE_BEGIN(&cprinfo);
4195 cv_wait(&ibcm_timeout_list_cv, &ibcm_timeout_list_lock);
4196 CALLB_CPR_SAFE_END(&cprinfo, &ibcm_timeout_list_lock);
4197 }
4198 }
4199
4200 CALLB_CPR_EXIT(&cprinfo); /* mutex_exit */
4201 }
4202
4203
4204 /*
4205 * ibcm_timeout_client_cb:
4206 * Called from timeout thread processing
4207 * Primary purpose is to call client handler
4208 *
4209 * INPUTS:
4210 * arg - ibcm_state_data_t is passed
4211 *
4212 * RETURN VALUES: NONE
4213 */
4214 void
4215 ibcm_timeout_client_cb(ibcm_state_data_t *statep)
4216 {
4217 mutex_enter(&statep->state_mutex);
4218
4219 if ((statep->state == IBCM_STATE_DELETE) &&
4220 (statep->recycle_arg != NULL)) {
4221 struct ibcm_taskq_recycle_arg_s *recycle_arg;
4222
4223 recycle_arg = statep->recycle_arg;
4224 statep->recycle_arg = NULL;
4225 mutex_exit(&statep->state_mutex);
4226 (void) ibcm_process_rc_recycle(recycle_arg);
4227 ibcm_delete_state_data(statep);
4228 return;
4229 }
4230
4231 if ((statep->state == IBCM_STATE_DELETE) &&
4232 (statep->delete_state_data == B_TRUE)) {
4233 mutex_exit(&statep->state_mutex);
4234 ibcm_dealloc_state_data(statep);
4235 return;
4236 }
4237
4238 /* Else, it must be in TIMEOUT state, do the necessary processing */
4239 if (statep->state == IBCM_STATE_TIMED_OUT) {
4240 void *data;
4241 uint8_t cf_msg;
4242 ib_guid_t local_hca_guid;
4243
4244 mutex_exit(&statep->state_mutex);
4424
4425 hca_guid = hcap->hca_guid;
4426 port_num = cm_mad_addr->port_num;
4427
4428 /* Figure out LID, GID, RequestId for svc_id lookup */
4429 lid = cm_mad_addr->rcvd_addr.ia_remote_lid;
4430 req_id = b2h32(sidr_reqp->sidr_req_request_id);
4431 pkey = b2h16(sidr_reqp->sidr_req_pkey);
4432 if (cm_mad_addr->grh_exists == B_TRUE)
4433 gid = cm_mad_addr->grh_hdr.ig_sender_gid;
4434 else
4435 gid.gid_prefix = gid.gid_guid = 0;
4436
4437 /*
4438 * Lookup for an existing state structure
4439 * - if lookup fails it creates a new ud_state struct
4440 * No need to hold a lock across the call to ibcm_find_sidr_entry() as
4441 * the list lock is held in that function to find the matching entry.
4442 */
4443
4444 srch_sidr.srch_lid = lid;
4445 srch_sidr.srch_gid = gid;
4446 srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4447 srch_sidr.srch_req_id = req_id;
4448 srch_sidr.srch_mode = IBCM_PASSIVE_MODE;
4449
4450 rw_enter(&hcap->hca_sidr_list_lock, RW_WRITER);
4451 state_lookup_status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4452 IBCM_FLAG_LOOKUP_AND_ADD);
4453 rw_exit(&hcap->hca_sidr_list_lock);
4454
4455 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: ud_statep 0x%p "
4456 "lookup status %x", ud_statep, state_lookup_status);
4457
4458 if (state_lookup_status == IBCM_LOOKUP_NEW) {
4459
4460 /* Increment hca's resource count */
4461 ibcm_inc_hca_res_cnt(hcap);
4462
4463 /*
4464 * Allocate CM MAD for a response
4465 * This MAD is deallocated on state structure delete
4466 * and re-used for all outgoing MADs for this connection.
4467 * If MAD allocation fails, delete the ud statep
4468 */
4469 if (ibcm_alloc_out_msg(cm_mad_addr->ibmf_hdl,
4470 &ud_statep->ud_stored_msg, MAD_METHOD_SEND) !=
4471 IBT_SUCCESS) {
4472 mutex_enter(&ud_statep->ud_state_mutex);
4473 IBCM_UD_REF_CNT_DECR(ud_statep);
4474 mutex_exit(&ud_statep->ud_state_mutex);
4475 ibcm_delete_ud_state_data(ud_statep);
4476 return;
4477 }
4478
4479 /* Lookup for service */
4480 ud_statep->ud_svc_id = b2h64(sidr_reqp->sidr_req_service_id);
4481 ud_statep->ud_state = IBCM_STATE_SIDR_REQ_RCVD;
4482 ud_statep->ud_clnt_proceed = IBCM_BLOCK;
4559
4560 /* Call Client's UD handler */
4561 cm_status = ibcm_sidr_req_ud_handler(ud_statep,
4562 sidr_reqp, cm_mad_addr, &sidr_status);
4563
4564 mutex_enter(&ibcm_svc_info_lock);
4565 IBCM_SVC_DECR(svc_infop);
4566 }
4567
4568 mutex_exit(&ibcm_svc_info_lock);
4569
4570 if (cm_status == IBCM_DEFER) {
4571 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_req_msg: "
4572 "ud_statep 0x%p client returned DEFER response",
4573 ud_statep);
4574 return;
4575 }
4576
4577 ibcm_post_sidr_rep_mad(ud_statep, sidr_status);
4578
4579 mutex_enter(&ud_statep->ud_state_mutex);
4580 IBCM_UD_REF_CNT_DECR(ud_statep);
4581 mutex_exit(&ud_statep->ud_state_mutex);
4582 } else {
4583 ASSERT(state_lookup_status == IBCM_LOOKUP_EXISTS);
4584
4585 mutex_enter(&ud_statep->ud_state_mutex);
4586
4587 if (ud_statep->ud_state == IBCM_STATE_SIDR_REP_SENT)
4588 ibcm_resend_srep_mad(ud_statep);
4589
4590 IBCM_UD_REF_CNT_DECR(ud_statep);
4591 mutex_exit(&ud_statep->ud_state_mutex);
4592 }
4593 }
4594
4595
4596 /*
4597 * ibcm_process_sidr_rep_msg:
4598 * This call processes an incoming SIDR REP
4621 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg:");
4622
4623 lid = cm_mad_addr->rcvd_addr.ia_local_lid;
4624 if (cm_mad_addr->grh_exists == B_TRUE)
4625 gid = cm_mad_addr->grh_hdr.ig_recver_gid;
4626 else
4627 gid.gid_prefix = gid.gid_guid = 0;
4628
4629 IBTF_DPRINTF_L3(cmlog, "ibcm_process_sidr_rep_msg: QPN rcvd = %x",
4630 h2b32(sidr_repp->sidr_rep_qpn_plus) >> 8);
4631
4632 /*
4633 * Lookup for an existing state structure.
4634 * No need to hold a lock as ibcm_find_sidr_entry() holds the
4635 * list lock to find the matching entry.
4636 */
4637 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep: lid=%x, (%llX, %llX), "
4638 "grh = %x, id = %x", lid, gid.gid_prefix, gid.gid_guid,
4639 cm_mad_addr->grh_exists, sidr_repp->sidr_rep_request_id);
4640
4641 srch_sidr.srch_lid = lid;
4642 srch_sidr.srch_gid = gid;
4643 srch_sidr.srch_grh_exists = cm_mad_addr->grh_exists;
4644 srch_sidr.srch_req_id = b2h32(sidr_repp->sidr_rep_request_id);
4645 srch_sidr.srch_mode = IBCM_ACTIVE_MODE;
4646
4647 rw_enter(&hcap->hca_sidr_list_lock, RW_READER);
4648 status = ibcm_find_sidr_entry(&srch_sidr, hcap, &ud_statep,
4649 IBCM_FLAG_LOOKUP);
4650 rw_exit(&hcap->hca_sidr_list_lock);
4651
4652 IBTF_DPRINTF_L4(cmlog, "ibcm_process_sidr_rep_msg: ud_statep 0x%p "
4653 "find sidr entry status = %x", ud_statep, status);
4654
4655 if (status != IBCM_LOOKUP_EXISTS) {
4656 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4657 "No matching ud_statep for SIDR REP");
4658 return;
4659 }
4660
4661 if (IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->TransactionID !=
4662 ((ib_mad_hdr_t *)(input_madp))->TransactionID) {
4663 mutex_enter(&ud_statep->ud_state_mutex);
4664 IBCM_UD_REF_CNT_DECR(ud_statep);
4665 mutex_exit(&ud_statep->ud_state_mutex);
4666 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_rep_msg: "
4764 * ibcm_post_sidr_rep_mad:
4765 * This call posts a SIDR REP MAD
4766 *
4767 * INPUTS:
4768 * ud_statep - pointer to ibcm_ud_state_data_t
4769 * status - Status information
4770 *
4771 * RETURN VALUE: NONE
4772 */
4773 void
4774 ibcm_post_sidr_rep_mad(ibcm_ud_state_data_t *ud_statep,
4775 ibt_sidr_status_t status)
4776 {
4777 ib_svc_id_t tmp_svc_id;
4778 ibcm_sidr_rep_msg_t *sidr_repp =
4779 (ibcm_sidr_rep_msg_t *)IBCM_OUT_MSGP(ud_statep->ud_stored_msg);
4780 clock_t timer_value;
4781
4782 IBTF_DPRINTF_L5(cmlog, "ibcm_post_sidr_rep_mad:");
4783
4784 IBCM_OUT_HDRP(ud_statep->ud_stored_msg)->AttributeID =
4785 h2b16(IBCM_INCOMING_SIDR_REP + IBCM_ATTR_BASE_ID);
4786
4787 /*
4788 * Initialize SIDR REP message. (Other fields were
4789 * already filled up in ibcm_sidr_req_ud_handler()
4790 */
4791 sidr_repp->sidr_rep_request_id = h2b32(ud_statep->ud_req_id);
4792 tmp_svc_id = h2b64(ud_statep->ud_svc_id);
4793 bcopy(&tmp_svc_id, sidr_repp->sidr_rep_service_id, sizeof (tmp_svc_id));
4794
4795 sidr_repp->sidr_rep_rep_status = (uint8_t)status;
4796
4797 /* post the SIDR REP MAD */
4798 ibcm_post_ud_mad(ud_statep, ud_statep->ud_stored_msg, NULL, NULL);
4799
4800 timer_value = ibt_ib2usec(ibcm_max_sidr_rep_store_time);
4801 /*
4802 * Hold the statep lock, as a SIDR REQ may come in after setting state
4803 * but before timeout. This can result in a dangling timeout ie.,
4804 * the incoming SIDR REQ would be unable to cancel this timeout
4805 */
4806 mutex_enter(&ud_statep->ud_state_mutex);
4807
4808 ud_statep->ud_remaining_retry_cnt = 1;
4809 ud_statep->ud_timer_value = timer_value;
4810
4811 ud_statep->ud_timer_stored_state = ud_statep->ud_state =
4812 IBCM_STATE_SIDR_REP_SENT;
4813 ud_statep->ud_timerid = IBCM_UD_TIMEOUT(ud_statep,
4814 ud_statep->ud_timer_value);
4815
4816 mutex_exit(&ud_statep->ud_state_mutex);
4957 /*
4958 * ibcm_build_reply_mad_addr:
4959 * Forms the reply MAD address based on "incoming mad addr" that is
4960 * supplied as an arg.
4961 *
4962 * Swaps the source and destination gids in ib_grh_t
4963 *
4964 * INPUTS:
4965 * inp_mad_addr: Address information in the incoming MAD
4966 * out_mad_addr: Derived address for the reply MAD
4967 * The reply MAD address is derived based
4968 * address information of incoming CM MAD
4969 * RETURN VALUE: NONE
4970 */
4971 void
4972 ibcm_build_reply_mad_addr(ibcm_mad_addr_t *inp_mad_addr,
4973 ibcm_mad_addr_t *out_mad_addr)
4974 {
4975 IBTF_DPRINTF_L5(cmlog, "ibcm_build_reply_mad_addr:");
4976
4977 bcopy(inp_mad_addr, out_mad_addr, sizeof (ibcm_mad_addr_t));
4978
4979 /* Swap the GIDs in the GRH */
4980 if (inp_mad_addr->grh_exists == B_TRUE) {
4981 ib_gid_t sgid = inp_mad_addr->grh_hdr.ig_sender_gid;
4982
4983 /* swap the SGID and DGID */
4984 out_mad_addr->grh_hdr.ig_sender_gid =
4985 inp_mad_addr->grh_hdr.ig_recver_gid;
4986 out_mad_addr->grh_hdr.ig_recver_gid = sgid;
4987 }
4988
4989 /*
4990 * CM posts response MAD on a new/existing internal QP on the same port
4991 * and pkey
4992 */
4993 out_mad_addr->cm_qp_entry =
4994 ibcm_find_qp(inp_mad_addr->cm_qp_entry->qp_port->port_hcap,
4995 inp_mad_addr->port_num, inp_mad_addr->rcvd_addr.ia_p_key);
4996 }
4997
4998
4999 /*
5000 * ibcm_post_rc_mad
5001 * Posts a CM MAD associated with a RC statep
5002 *
5003 * INPUTS:
5004 * statep : RC statep associated with the post
5005 * msgp : CM MAD to be posted
5006 * post_cb : non-NULL callback address implies non-blocking post
5007 * args : Args to ibmf send callback
5008 *
5009 * RETURN VALUE: based on ibmf_send_mad
5010 */
5011 void
5012 ibcm_post_rc_mad(ibcm_state_data_t *statep, ibmf_msg_t *msgp,
5013 ibmf_msg_cb_t post_cb, void *args)
5014 {
5015 ibt_status_t status;
6168
6169 ibcm_insert_trace(statep, IBCM_TRACE_CALLED_REQ_RCVD_EVENT);
6170
6171 /* Invoke the client handler */
6172 statep->req_msgp = cm_req_msgp;
6173 cb_status = statep->cm_handler(statep->state_cm_private, &event,
6174 &ret_args, priv_data, IBT_REP_PRIV_DATA_SZ);
6175 statep->req_msgp = NULL;
6176
6177 ibcm_insert_trace(statep, IBCM_TRACE_RET_REQ_RCVD_EVENT);
6178
6179 mutex_enter(&ibcm_svc_info_lock);
6180 IBCM_SVC_DECR(statep->state_svc_infop);
6181 mutex_exit(&ibcm_svc_info_lock);
6182
6183 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_req: Client handler returned %d"
6184 " statep 0x%p", cb_status, statep);
6185
6186 if (cb_status == IBT_CM_DEFER) {
6187
6188 if (statep->defer_cm_msg == NULL)
6189 statep->defer_cm_msg =
6190 kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
6191 bcopy(cm_req_msgp, statep->defer_cm_msg, IBCM_MSG_SIZE);
6192
6193 /*
6194 * unblock any blocked cm proceed api calls. Do not access
6195 * statep after cv_signal
6196 */
6197 mutex_enter(&statep->state_mutex);
6198 statep->clnt_proceed = IBCM_UNBLOCK;
6199 cv_broadcast(&statep->block_client_cv);
6200 mutex_exit(&statep->state_mutex);
6201
6202 kmem_free(priv_data, IBT_MAX_PRIV_DATA_SZ);
6203 return (IBCM_DEFER);
6204 }
6205
6206 /* fail any blocked cm proceed api call - client bug */
6207 mutex_enter(&statep->state_mutex);
6208 statep->clnt_proceed = IBCM_FAIL;
6209 cv_broadcast(&statep->block_client_cv);
6210 mutex_exit(&statep->state_mutex);
6211
6212 clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
6250 *reject_reason = IBT_CM_CONSUMER;
6251 } else if (cb_status == IBT_CM_REDIRECT_PORT) {
6252 *reject_reason = IBT_CM_PORT_REDIRECT;
6253 } else if (cb_status == IBT_CM_REDIRECT) {
6254 *reject_reason = IBT_CM_REDIRECT_CM;
6255 } else if (cb_status == IBT_CM_NO_CHANNEL) {
6256 *reject_reason = IBT_CM_NO_CHAN;
6257 } else if (cb_status == IBT_CM_NO_RESOURCE) {
6258 *reject_reason = IBT_CM_NO_RESC;
6259 } else {
6260 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p"
6261 " Client handler unexpected return %x", statep, cb_status);
6262 *reject_reason = IBT_CM_CONSUMER;
6263 }
6264
6265 /* client handler gave CM ok */
6266 if (cb_status == IBT_CM_ACCEPT) {
6267 ibcm_rep_msg_t *rep_msgp = (ibcm_rep_msg_t *)
6268 IBCM_OUT_MSGP(statep->stored_msg);
6269
6270 /*
6271 * Check first if ret_args make sense. If not, bailout
6272 * here rather than going along and panicing later.
6273 */
6274 channel = clnt_info->reply_event->rep.cm_channel;
6275 if (IBCM_INVALID_CHANNEL(channel)) {
6276 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6277 "statep 0x%p server's QP handle is NULL", statep);
6278 *reject_reason = IBT_CM_NO_CHAN;
6279 }
6280
6281 IBCM_GET_CHAN_PRIVATE(channel, old_statep);
6282
6283 if ((*reject_reason == IBT_CM_SUCCESS) &&
6284 (old_statep != NULL)) {
6285 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_req_cm_hdlr: "
6286 "statep 0x%p Channel being re-used on passive side",
6287 statep);
6288 *reject_reason = IBT_CM_NO_CHAN;
6289 }
6534 if (status == IBT_SUCCESS) {
6535 rep_msgp->rep_local_eecn_plus =
6536 h2b32(((uint32_t)eec_attrs.eec_eecn << 8));
6537 }
6538 }
6539 #endif
6540
6541 /* figure out Target ACK delay */
6542 rep_msgp->rep_target_delay_plus |= (status == IBT_SUCCESS) ?
6543 statep->hcap->hca_ack_delay << 3 : 0;
6544
6545 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr:statep %p "
6546 "REP priv len %x", statep, clnt_info->priv_data_len);
6547 /* Copy PrivateData from priv_data */
6548 if (clnt_info->priv_data_len != 0) {
6549 bcopy(clnt_info->priv_data, rep_msgp->rep_private_data,
6550 min(IBT_REP_PRIV_DATA_SZ,
6551 clnt_info->priv_data_len));
6552 }
6553
6554 return (IBCM_SEND_REP);
6555 }
6556
6557 /* REJ message */
6558 rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6559
6560 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_req_cm_hdlr: statep %p REJ "
6561 "priv len %x", statep, clnt_info->priv_data_len);
6562
6563 /* if priv_data_len != 0 use priv_data to copy back to rej_priv_data */
6564 if (clnt_info->priv_data_len != 0) {
6565 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6566 min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6567 }
6568
6569 if (cb_status == IBT_CM_REDIRECT_PORT) {
6570 ib_gid_t tgid;
6571
6572 tgid.gid_guid =
6573 h2b64(clnt_info->reply_event->rej.ari_gid.gid_guid);
6574 tgid.gid_prefix =
6575 h2b64(clnt_info->reply_event->rej.ari_gid.gid_prefix);
6576
6577 *arej_len = sizeof (ib_gid_t);
6578 bcopy(&tgid, &rej_msgp->rej_addl_rej_info, sizeof (ib_gid_t));
6579
6580 IBTF_DPRINTF_L3(cmlog, "ibcm_process_cep_req_cm_hdlr: ari_gid= "
6581 "%llX:%llX", tgid.gid_prefix, tgid.gid_guid);
6582
6600
6601 /*
6602 * RDMA IP REQ was passed up to the ULP, the ULP decided to do
6603 * a "normal" consumer REJ, by the returning IBT_CM_REJECT in
6604 * the cm handler.
6605 * CM has to do some extra stuff too, it has to
6606 * a) return REJ code 28 (consumer) and b) put 0x1 in the first
6607 * byte of the ARI data, to indicate that this is a RDMA aware
6608 * ULP that is doing a consumer reject. The ULP should have
6609 * put its consumer specific data into ibt_arej_info_t(9s) at
6610 * byte 1 of the rej_ari[] array.
6611 */
6612 if (((statep->svcid & IB_SID_IPADDR_PREFIX_MASK) == 0) &&
6613 (statep->svcid & IB_SID_IPADDR_PREFIX)) {
6614 rej_msgp->rej_addl_rej_info[0] = 1;
6615 }
6616 }
6617
6618 rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REQ << 6;
6619
6620 return (IBCM_SEND_REJ);
6621 }
6622
6623 /*
6624 * ibcm_cep_state_rep:
6625 * QP state transition function called for an incoming REP on active side
6626 *
6627 * INPUTS:
6628 * statep - state pointer
6629 * cm_rep_msg - REP message pointer
6630 * reject_reason - Rejection reason See Section 12.6.7.2 rev1.0a IB Spec
6631 *
6632 * RETURN VALUE:
6633 */
6634 ibcm_status_t
6635 ibcm_cep_state_rep(ibcm_state_data_t *statep, ibcm_rep_msg_t *cm_rep_msgp,
6636 ibt_cm_reason_t *reject_reason, uint8_t *arej_len)
6637 {
6638 void *priv_data = NULL;
6639 ibcm_status_t rval = IBCM_SEND_RTU;
6778
6779
6780 /* We come here if status is ACCEPT or CM handler is NULL */
6781 if (cb_status == IBT_CM_ACCEPT) {
6782 ib_time_t time;
6783
6784 time = ibt_usec2ib(statep->pkt_life_time * 2 +
6785 ibt_ib2usec(cm_rep_msgp->rep_target_delay_plus >> 3));
6786
6787 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6788 " active cep_timeout(usec) 0x%x ", statep, time);
6789
6790 IBTF_DPRINTF_L4(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6791 " passive hca_ack_delay(ib_time) = 0x%x, ", statep,
6792 cm_rep_msgp->rep_target_delay_plus >> 3);
6793
6794 IBTF_DPRINTF_L5(cmlog, "ibcm_process_cep_rep_cm_hdlr: statep %p"
6795 " rnr_retry_cnt = 0x%x", statep,
6796 cm_rep_msgp->rep_rnr_retry_cnt_plus >> 5);
6797
6798 statep->starting_psn =
6799 b2h32(cm_rep_msgp->rep_starting_psn_plus) >> 8;
6800
6801 /* Call IBTL CM's qp modify function from Init to RTR */
6802 if (ibcm_invoke_qp_modify(statep,
6803 (ibcm_req_msg_t *)IBCM_OUT_MSGP(statep->stored_msg),
6804 cm_rep_msgp) != IBT_SUCCESS) {
6805
6806 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6807 "statep %p, ibcm_invoke_qp_modify to RTR failed",
6808 statep);
6809 *reject_reason = IBT_CM_NO_RESC;
6810 /*
6811 * Call modify qp function from RTR to RTS
6812 * RDMA initiator depth on active is same as negotiated
6813 * passive REP's responder resources
6814 */
6815 } else if (ibcm_invoke_rtu_qp_modify(statep, time, cm_rep_msgp)
6816 != IBT_SUCCESS) {
6817
6818 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_rep_cm_hdlr: "
6819 "statep %p ibcm_invoke_rtu_qp_modify to RTS failed",
6820 statep);
6828 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6829
6830 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6831 IBT_CM_FAILURE_REP, IBT_CM_CI_FAILURE, NULL, 0);
6832 return (IBCM_SEND_REJ); /* send REJ */
6833 }
6834
6835 if (clnt_info->priv_data_len != 0) {
6836 ibcm_rtu_msg_t *rtu_msgp;
6837 rtu_msgp = (ibcm_rtu_msg_t *)
6838 IBCM_OUT_MSGP(statep->stored_msg);
6839 bcopy(clnt_info->priv_data, rtu_msgp->rtu_private_data,
6840 min(IBT_RTU_PRIV_DATA_SZ,
6841 clnt_info->priv_data_len));
6842 }
6843
6844 *reject_reason = IBT_CM_SUCCESS;
6845 return (rval);
6846 }
6847
6848 /* Fill up the REJ fields, from ret_args */
6849 rej_msgp = (ibcm_rej_msg_t *)IBCM_OUT_MSGP(statep->stored_msg);
6850 rej_msgp->rej_msg_type_plus = IBT_CM_FAILURE_REP << 6;
6851
6852 /* if priv_len != 0 use priv_data to copy back to rej_priv_data */
6853 if (clnt_info->priv_data_len != 0)
6854 bcopy(clnt_info->priv_data, rej_msgp->rej_private_data,
6855 min(IBT_REJ_PRIV_DATA_SZ, clnt_info->priv_data_len));
6856
6857 if (clnt_info->reply_event != NULL)
6858 *arej_len =
6859 min(clnt_info->reply_event->rej.ari_consumer.rej_ari_len,
6860 IBT_CM_ADDL_REJ_LEN);
6861
6862 if (*arej_len != 0) /* asserts that clnt_info->reply_event != 0 */
6863 bcopy(clnt_info->reply_event->rej.ari_consumer.rej_ari,
6864 &rej_msgp->rej_addl_rej_info, *arej_len);
6865
6866 rval = IBCM_SEND_REJ;
6867
6868 /* Disassociate statep and QP */
6869 IBCM_SET_CHAN_PRIVATE(statep->channel, NULL);
6870
6871 /* callback client, to enable client to do resource cleanup */
6872 ibcm_handler_conn_fail(statep, IBT_CM_FAILURE_REJ_SENT,
6873 IBT_CM_FAILURE_REP, *reject_reason, NULL, 0);
6874
6875 return (rval);
6876 }
6877
6878 /*
6879 * ibcm_invoke_rtu_qp_modify:
6880 * Helper function to modify QP for RTU only called from
6881 * ibcm_cep_state_rtu() and ibcm_cep_send_rtu()
6882 *
6883 * INPUTS:
6884 * statep - connection state pointer
6885 *
7221 bcopy(&event.cm_event.failed.cf_additional,
7222 &statep->open_return_data->rc_arej_info,
7223 sizeof (ibt_arej_info_t));
7224 if (ibcm_enable_trace != 0)
7225 ibcm_dump_conn_trace(statep);
7226 mutex_enter(&statep->state_mutex);
7227 ibcm_open_done(statep);
7228 mutex_exit(&statep->state_mutex);
7229 }
7230
7231 /* Used to initialize client args with addl rej information from REJ MAD */
7232 static void
7233 ibcm_copy_addl_rej(ibcm_state_data_t *statep, ibcm_rej_msg_t *rej_msgp,
7234 ibt_cm_conn_failed_t *failed)
7235 {
7236 uint16_t rej_reason = b2h16(rej_msgp->rej_rejection_reason);
7237 uint8_t ari_len = rej_msgp->rej_reject_info_len_plus >> 1;
7238 ibcm_classportinfo_msg_t tclp;
7239 ibt_arej_info_t *cf_addl = &failed->cf_additional;
7240
7241 failed->cf_arej_info_valid = B_FALSE;
7242
7243 IBTF_DPRINTF_L3(cmlog, "ibcm_copy_addl_rej: rej_reason = %d "
7244 "ari_len = %d", rej_reason, ari_len);
7245
7246 if ((statep->mode == IBCM_PASSIVE_MODE) &&
7247 (rej_reason != IBT_CM_CONSUMER))
7248 return;
7249
7250 switch (rej_reason) {
7251 case IBT_CM_PRIM_GID:
7252 case IBT_CM_ALT_GID:
7253 case IBT_CM_PORT_REDIRECT:
7254 if (ari_len < sizeof (ib_gid_t))
7255 break;
7256 failed->cf_arej_info_valid = B_TRUE;
7257 bcopy(rej_msgp->rej_addl_rej_info, &cf_addl->ari_gid,
7258 sizeof (ib_gid_t));
7259 cf_addl->ari_gid.gid_guid = b2h64(cf_addl->ari_gid.gid_guid);
7260 cf_addl->ari_gid.gid_prefix =
7327 break;
7328 failed->cf_arej_info_valid = B_TRUE;
7329 if (ari_len > IBT_CM_ADDL_REJ_LEN)
7330 ari_len = IBT_CM_ADDL_REJ_LEN;
7331 bcopy(&rej_msgp->rej_addl_rej_info,
7332 cf_addl->ari_consumer.rej_ari, ari_len);
7333 cf_addl->ari_consumer.rej_ari_len = ari_len;
7334 break;
7335 case IBT_CM_INVALID_PRIM_FLOW:
7336 case IBT_CM_INVALID_ALT_FLOW:
7337 if (ari_len < 3) /* 3 bytes needed for 20 bits */
7338 break;
7339 failed->cf_arej_info_valid = B_TRUE;
7340 /* take the first 20 bits */
7341 cf_addl->ari_flow =
7342 b2h32(*(uint32_t *)&rej_msgp->rej_addl_rej_info) >> 12;
7343 break;
7344 default:
7345 break;
7346 }
7347 }
7348
7349
7350 /* Used to copy classportinfo to MAD from client initialized args */
7351 static void
7352 ibcm_init_clp_to_mad(ibcm_classportinfo_msg_t *clp, ibt_redirect_info_t *rinfo)
7353 {
7354
7355 bcopy(&ibcm_clpinfo, clp, sizeof (ibcm_clpinfo));
7356
7357 clp->RedirectGID_hi = h2b64(rinfo->rdi_gid.gid_prefix);
7358 clp->RedirectGID_lo = h2b64(rinfo->rdi_gid.gid_guid);
7359 clp->RedirectTC_plus =
7360 h2b32((rinfo->rdi_tclass << 24) | (rinfo->rdi_sl << 20) |
7361 (rinfo->rdi_flow & 0xfffff));
7362 clp->RedirectLID = h2b16(rinfo->rdi_dlid);
7363 clp->RedirectQP_plus = h2b32(rinfo->rdi_qpn & 0xffffff);
7364 clp->RedirectQ_Key = h2b32(rinfo->rdi_qkey);
7365 clp->RedirectP_Key = h2b16(rinfo->rdi_pkey);
7366
7367 IBTF_DPRINTF_L4(cmlog, "ibcm_init_clp_to_mad: RedirectGID= %llX:%llX,"
7368 " RedirectLID= 0x%lX", clp->RedirectGID_hi, clp->RedirectGID_lo,
7369 clp->RedirectLID);
7370 }
7371
7372
7373 /* Used to initialize classportinfo to be returned to clients, from MAD */
7374 static void
7375 ibcm_init_clp_from_mad(ibcm_classportinfo_msg_t *clp,
7376 ibt_redirect_info_t *rinfo)
7377 {
7378 uint32_t temp32;
7379
7380 rinfo->rdi_gid.gid_prefix = b2h64(clp->RedirectGID_hi);
7381 rinfo->rdi_gid.gid_guid = b2h64(clp->RedirectGID_lo);
7382 temp32 = b2h32(clp->RedirectTC_plus);
7383 rinfo->rdi_tclass = temp32 >> 24;
7384 rinfo->rdi_sl = (temp32 >> 20) & 0xf;
7385 rinfo->rdi_flow = temp32 & 0xffff;
7386 rinfo->rdi_dlid = b2h16(clp->RedirectLID);
7387 rinfo->rdi_qpn = b2h32(clp->RedirectQP_plus & 0xffffff);
7388 rinfo->rdi_qkey = b2h32(clp->RedirectQ_Key);
7389 rinfo->rdi_pkey = b2h16(clp->RedirectP_Key);
7585 min(ud_clnt_info->priv_data_len,
7586 IBT_SIDR_REP_PRIV_DATA_SZ));
7587 }
7588
7589 if (*sidr_status != IBT_CM_SREP_CHAN_VALID) {
7590 IBTF_DPRINTF_L2(cmlog, "ibcm_process_sidr_req_cm_hdlr: "
7591 "ud_handler return a failure: %d", cb_status);
7592 if (*sidr_status == IBT_CM_SREP_REDIRECT) {
7593 /*
7594 * typecasting to ibcm_classportinfo_msg_t is ok, as addl info
7595 * begins at offset 24 in sidr rep
7596 */
7597 ibcm_init_clp_to_mad(
7598 (ibcm_classportinfo_msg_t *)
7599 &sidr_repp->sidr_rep_class_port_info,
7600 ud_clnt_info->redirect_infop);
7601 }
7602 return;
7603 }
7604
7605 sidr_repp->sidr_rep_qkey =
7606 h2b32(ud_clnt_info->ud_qkey);
7607 sidr_repp->sidr_rep_qpn_plus = h2b32(ud_clnt_info->ud_qpn << 8);
7608 }
7609
7610 /*
7611 * ibcm_sidr_rep_ud_handler:
7612 * Invoke Client's UD handler For SIDR_REP msg
7613 *
7614 * INPUTS:
7615 * ud_statep - ud_state pointer
7616 * sidr_rep_msgp - SIDR_REQ message pointer
7617 *
7618 */
7619 static void
7620 ibcm_sidr_rep_ud_handler(ibcm_ud_state_data_t *ud_statep,
7621 ibcm_sidr_rep_msg_t *sidr_rep_msgp)
7622 {
7623 ibt_cm_ud_event_t ud_event;
7624
7625 IBTF_DPRINTF_L5(cmlog, "ibcm_sidr_rep_ud_handler: ud_statep 0x%p",
7626 ud_statep);
7627
7831 *
7832 * INPUTS:
7833 * statep - pointer to ibcm_state_data_t
7834 * lap_msg - lap msg received
7835 * apr_msg - apr msg to be sent
7836 *
7837 * RETURN VALUE: NONE
7838 */
7839 ibcm_status_t
7840 ibcm_cep_state_lap(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
7841 ibcm_apr_msg_t *apr_msg)
7842 {
7843 ibt_cm_event_t event;
7844 ibt_cm_return_args_t ret_args;
7845 ibt_cm_status_t cb_status;
7846 ibcm_clnt_reply_info_t clnt_info;
7847
7848
7849 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: statep 0x%p", statep);
7850
7851 /* If APM is not supported, return error */
7852 if (!(statep->hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) {
7853 apr_msg->apr_ap_status = IBT_CM_AP_NOT_SUPPORTED;
7854 return (IBCM_SEND_APR);
7855 }
7856
7857 if (statep->local_qpn !=
7858 b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8) {
7859 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7860 IBTF_DPRINTF_L4(cmlog, "ibcm_cep_state_lap: local_qpn %x does "
7861 "not match remote's remote_qpn %x", statep->local_qpn,
7862 b2h32(lap_msg->lap_remote_qpn_eecn_plus) >> 8);
7863 return (IBCM_SEND_APR);
7864 }
7865
7866 /* Fill up the event */
7867 bzero(&event, sizeof (event));
7868 event.cm_type = IBT_CM_EVENT_LAP_RCV;
7869 event.cm_channel = statep->channel;
7870 event.cm_session_id = statep;
7871 event.cm_priv_data = lap_msg->lap_private_data;
7872 event.cm_priv_data_len = IBT_LAP_PRIV_DATA_SZ;
7873 event.cm_event.lap.lap_timeout = ibt_ib2usec(
7874 ((uint8_t *)&lap_msg->lap_remote_qpn_eecn_plus)[3] >> 3);
7875
7876 ibcm_fill_adds_from_lap(&event.cm_event.lap.lap_alternate_path,
7877 lap_msg, IBCM_PASSIVE_MODE);
7878
7879 cb_status = statep->cm_handler(statep->state_cm_private, &event,
7880 &ret_args, apr_msg->apr_private_data, IBT_APR_PRIV_DATA_SZ);
7881
7882 IBTF_DPRINTF_L3(cmlog, "ibcm_cep_state_lap: cb_status = %d", cb_status);
7883 if (cb_status == IBT_CM_DEFER) {
7884 if (statep->defer_cm_msg == NULL)
7885 statep->defer_cm_msg =
7886 kmem_zalloc(IBCM_MSG_SIZE, KM_SLEEP);
7887 bcopy(lap_msg, statep->defer_cm_msg, IBCM_MSG_SIZE);
7888 /* unblock any blocked cm proceed api calls */
7889 mutex_enter(&statep->state_mutex);
7890 statep->clnt_proceed = IBCM_UNBLOCK;
7891 cv_broadcast(&statep->block_client_cv);
7892 mutex_exit(&statep->state_mutex);
7893
7894 return (IBCM_DEFER);
7895 }
7896
7897 clnt_info.reply_event = (ibt_cm_proceed_reply_t *)&ret_args.cm_ret;
7898 clnt_info.priv_data = NULL;
7899 clnt_info.priv_data_len = 0;
7900
7901 ibcm_process_cep_lap_cm_hdlr(statep, cb_status, &clnt_info, lap_msg,
7902 apr_msg);
7903 return (IBCM_SEND_APR);
7904 }
7905
7906 /*
7907 * ibcm_fill_adds_from_lap:
7964
7965 /*
7966 * ibcm_process_cep_lap_cm_hdlr:
7967 * Processes the cm handler response for an incoming LAP.
7968 */
7969
7970 void
7971 ibcm_process_cep_lap_cm_hdlr(ibcm_state_data_t *statep,
7972 ibt_cm_status_t cb_status, ibcm_clnt_reply_info_t *clnt_info,
7973 ibcm_lap_msg_t *lap_msg, ibcm_apr_msg_t *apr_msg)
7974 {
7975 ibtl_cm_hca_port_t port;
7976 ibt_qp_query_attr_t qp_attrs;
7977 ibt_cep_modify_flags_t cep_flags;
7978 ibt_status_t status;
7979 ibt_adds_vect_t *adds;
7980
7981 if (cb_status == IBT_CM_DEFAULT)
7982 cb_status = IBT_CM_REJECT;
7983
7984 /* verify status */
7985 apr_msg->apr_addl_info_len = 0;
7986 if (cb_status == IBT_CM_ACCEPT) {
7987 apr_msg->apr_ap_status = IBT_CM_AP_LOADED;
7988 } else if (cb_status == IBT_CM_REJECT) {
7989 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7990 } else if (cb_status == IBT_CM_REDIRECT) {
7991 apr_msg->apr_ap_status = IBT_CM_AP_REDIRECT;
7992 /* copy redirect info to APR */
7993 apr_msg->apr_addl_info_len = sizeof (ibcm_classportinfo_msg_t);
7994 ibcm_init_clp_to_mad(
7995 (ibcm_classportinfo_msg_t *)apr_msg->apr_addl_info,
7996 &clnt_info->reply_event->apr);
7997 } else if (cb_status == IBT_CM_NO_RESOURCE) {
7998 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
7999 } else {
8000 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr: statep %p"
8001 " Client handler unexpected return %x", statep, cb_status);
8002 cb_status = IBT_CM_REJECT;
8003 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8074 status = ibt_modify_qp(statep->channel, cep_flags, &qp_attrs.qp_info,
8075 NULL);
8076
8077 if (status != IBT_SUCCESS) {
8078 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT_FAIL);
8079 } else
8080 ibcm_insert_trace(statep, IBCM_TRACE_SET_ALT);
8081
8082 #ifdef DEBUG
8083 (void) ibt_query_qp(statep->channel, &qp_attrs);
8084 print_modify_qp("PASSIVE LAP QUERY", statep->channel,
8085 cep_flags, &qp_attrs.qp_info);
8086 #endif
8087
8088 if (status != IBT_SUCCESS) {
8089 apr_msg->apr_ap_status = IBT_CM_AP_REJECT;
8090 IBTF_DPRINTF_L2(cmlog, "ibcm_process_cep_lap_cm_hdlr:"
8091 " ibt_modify_qp() returned = %d", status);
8092 return;
8093 }
8094 }
8095
8096
8097 /*
8098 * ibcm_post_apr_mad:
8099 * Posts a APR MAD and starts timer
8100 *
8101 * INPUTS:
8102 * statep - state pointer
8103 *
8104 * RETURN VALUE: NONE
8105 */
8106 void
8107 ibcm_post_apr_mad(ibcm_state_data_t *statep)
8108 {
8109 ibcm_apr_msg_t *apr_msgp;
8110
8111 apr_msgp = (ibcm_apr_msg_t *)IBCM_OUT_MSGP(statep->lapr_msg);
8112
8113 apr_msgp->apr_local_comm_id = h2b32(statep->local_comid);
8114 apr_msgp->apr_remote_comm_id = h2b32(statep->remote_comid);
8115 IBCM_OUT_HDRP(statep->lapr_msg)->AttributeID =
8116 h2b16(IBCM_INCOMING_APR + IBCM_ATTR_BASE_ID);
8117
8118 ibcm_insert_trace(statep, IBCM_TRACE_OUTGOING_APR);
8119
8120 ibcm_post_rc_mad(statep, statep->lapr_msg, ibcm_post_apr_complete,
8121 statep);
8122 }
8123
8124 /*
8125 * ibcm_process_apr_msg:
8126 * This call processes an incoming APR message
8127 *
8128 * INPUTS:
8129 * hcap - HCA entry pointer
8130 * input_madp - incoming CM SIDR REP MAD
8131 * cm_mad_addr - Address information for the MAD to be posted
8132 *
8133 * RETURN VALUE: NONE
8134 */
8135 /*ARGSUSED*/
8136 void
8137 ibcm_process_apr_msg(ibcm_hca_info_t *hcap, uint8_t *input_madp,
8210
8211 /* wake up blocking ibt_set_alt_path */
8212 cv_broadcast(&statep->block_client_cv);
8213
8214 IBCM_REF_CNT_DECR(statep); /* decrement the ref count */
8215 mutex_exit(&statep->state_mutex);
8216 }
8217
8218 static void
8219 ibcm_set_apr_arej(int ap_status, ibcm_apr_msg_t *apr_msgp,
8220 ibt_arej_info_t *ari, boolean_t *ari_valid)
8221 {
8222 uint8_t ari_len = apr_msgp->apr_addl_info_len;
8223 ibcm_classportinfo_msg_t tclp;
8224
8225 *ari_valid = B_FALSE;
8226
8227 IBTF_DPRINTF_L3(cmlog, "ibcm_set_apr_arej: apr_status = %d "
8228 "ari_len = %d", ap_status, ari_len);
8229
8230 switch (ap_status) {
8231 case IBT_CM_AP_REDIRECT:
8232 if (ari_len < sizeof (ibcm_classportinfo_msg_t))
8233 break;
8234 *ari_valid = B_TRUE;
8235 bcopy(apr_msgp->apr_addl_info, &tclp, sizeof (tclp));
8236 ibcm_init_clp_from_mad(&tclp, &ari->ari_redirect);
8237 break;
8238 case IBT_CM_AP_RLID_REJECTED:
8239 if (ari_len < sizeof (ib_lid_t))
8240 break;
8241 *ari_valid = B_TRUE;
8242 bcopy(apr_msgp->apr_addl_info, &ari->ari_lid,
8243 sizeof (ib_lid_t));
8244 ari->ari_lid = b2h16(ari->ari_lid);
8245 break;
8246 case IBT_CM_AP_RGID_REJECTED:
8247 if (ari_len < sizeof (ib_gid_t))
8248 break;
8249 *ari_valid = B_TRUE;
8277 /* take the first byte */
8278 ari->ari_hop = apr_msgp->apr_addl_info[0];
8279 break;
8280 case IBT_CM_AP_RATE_REJECTED:
8281 if (ari_len < 1)
8282 break;
8283 *ari_valid = B_TRUE;
8284 /* take the first 6 bits */
8285 ari->ari_rate = apr_msgp->apr_addl_info[0] >> 2;
8286 break;
8287 case IBT_CM_AP_SL_REJECTED:
8288 if (ari_len < 1)
8289 break;
8290 *ari_valid = B_TRUE;
8291 /* take the first 4 bits */
8292 ari->ari_sl = apr_msgp->apr_addl_info[0] >> 4;
8293 break;
8294 default:
8295 break;
8296 }
8297 }
8298
8299 /*
8300 * ibcm_cep_state_apr:
8301 * This call processes an incoming APR message
8302 *
8303 * INPUTS:
8304 * statep - pointer to ibcm_state_data_t
8305 * lap_msg - lap msg sent earlier
8306 * apr_msg - apr msg received
8307 *
8308 * RETURN VALUE: NONE
8309 */
8310 void
8311 ibcm_cep_state_apr(ibcm_state_data_t *statep, ibcm_lap_msg_t *lap_msg,
8312 ibcm_apr_msg_t *apr_msg)
8313 {
8314 ibt_cm_event_t event;
8315 ibcm_status_t status = IBCM_SUCCESS;
8316 uint8_t ap_status = apr_msg->apr_ap_status;
8494 *
8495 * INPUTS:
8496 * statep Pointer to ibcm_state_data_t
8497 *
8498 * RETURN VALUE: NONE
8499 *
8500 * This function is called holding state mutex
8501 * This function returns, releasing the state mutex
8502 */
8503 void
8504 ibcm_sync_lapr_idle(ibcm_state_data_t *statep)
8505 {
8506 timeout_id_t timer_val = statep->timerid;
8507 ibt_cm_event_t event;
8508
8509 IBTF_DPRINTF_L3(cmlog, "ibcm_sync_lapr_idle:"
8510 "statep %p state %d ap_state %d", statep, statep->state,
8511 statep->ap_state);
8512
8513 ASSERT(MUTEX_HELD(&statep->state_mutex));
8514
8515 /* Busy AP states on active/passive sides */
8516 if ((statep->ap_state == IBCM_AP_STATE_LAP_RCVD) ||
8517 (statep->ap_state == IBCM_AP_STATE_APR_RCVD) ||
8518 (statep->ap_state == IBCM_AP_STATE_MRA_LAP_SENT) ||
8519 (statep->ap_state == IBCM_AP_STATE_TIMED_OUT)) {
8520
8521 /* wait till ap_state becomes IBCM_AP_STATE_IDLE */
8522 while (statep->ap_state != IBCM_AP_STATE_IDLE)
8523 cv_wait(&statep->block_mad_cv, &statep->state_mutex);
8524
8525 mutex_exit(&statep->state_mutex);
8526
8527 } else if ((statep->ap_state == IBCM_AP_STATE_LAP_SENT) ||
8528 (statep->ap_state == IBCM_AP_STATE_MRA_LAP_RCVD)) {
8529
8530 /* fail the client's ibt_set_alt_path */
8531
8532 /* blocking ibt_set_alt_path */
8533 if (statep->ap_return_data != NULL) {
|