31 *
32 * ibt_get_paths() implement the Path Informations related functionality.
33 */
34
35 /* ibcm_saa_service_rec() fills in ServiceID and DGID. */
36 typedef struct ibcm_dest_s {
37 ib_gid_t d_gid;
38 ib_svc_id_t d_sid;
39 ibt_srv_data_t d_sdata;
40 ib_pkey_t d_pkey;
41 uint_t d_tag; /* 0 = Unicast, 1 = Multicast */
42 } ibcm_dest_t;
43
44 /* Holds Destination information needed to fill in ibt_path_info_t. */
45 typedef struct ibcm_dinfo_s {
46 uint8_t num_dest;
47 ib_pkey_t p_key;
48 ibcm_dest_t dest[1];
49 } ibcm_dinfo_t;
50
51 _NOTE(SCHEME_PROTECTS_DATA("Temporary path storage", ibcm_dinfo_s))
52 _NOTE(READ_ONLY_DATA(ibt_path_attr_s))
53
54 typedef struct ibcm_path_tqargs_s {
55 ibt_path_attr_t attr;
56 ibt_path_info_t *paths;
57 uint8_t *num_paths_p;
58 ibt_path_handler_t func;
59 void *arg;
60 ibt_path_flags_t flags;
61 uint8_t max_paths;
62 } ibcm_path_tqargs_t;
63
64
65 /* Prototype Declarations. */
66 static ibt_status_t ibcm_saa_path_rec(ibcm_path_tqargs_t *,
67 ibtl_cm_port_list_t *, ibcm_dinfo_t *, uint8_t *);
68
69 static ibt_status_t ibcm_update_cep_info(sa_path_record_t *,
70 ibtl_cm_port_list_t *, ibtl_cm_hca_port_t *, ibt_cep_path_t *);
71
72 static ibt_status_t ibcm_saa_service_rec(ibcm_path_tqargs_t *,
73 ibtl_cm_port_list_t *, ibcm_dinfo_t *);
430 {
431 ibcm_path_tqargs_t *path_tq;
432 int sleep_flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
433 int len;
434 ibt_status_t retval;
435
436 retval = ibcm_validate_path_attributes(attrp, flags, max_paths);
437 if (retval != IBT_SUCCESS)
438 return (retval);
439
440 len = (attrp->pa_num_dgids * sizeof (ib_gid_t)) +
441 sizeof (ibcm_path_tqargs_t);
442
443 path_tq = kmem_alloc(len, sleep_flag);
444 if (path_tq == NULL) {
445 IBTF_DPRINTF_L2(cmlog, "ibcm_handle_get_path: "
446 "Unable to allocate memory for local usage.");
447 return (IBT_INSUFF_KERNEL_RESOURCE);
448 }
449
450 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*path_tq))
451
452 bcopy(attrp, &path_tq->attr, sizeof (ibt_path_attr_t));
453
454 if (attrp->pa_num_dgids) {
455 path_tq->attr.pa_dgids = (ib_gid_t *)(((uchar_t *)path_tq) +
456 sizeof (ibcm_path_tqargs_t));
457
458 bcopy(attrp->pa_dgids, path_tq->attr.pa_dgids,
459 sizeof (ib_gid_t) * attrp->pa_num_dgids);
460 } else {
461 path_tq->attr.pa_dgids = NULL;
462 }
463
464 /* Ignore IBT_PATH_AVAIL flag, if only one path is requested. */
465 if ((flags & IBT_PATH_AVAIL) && (max_paths == 1)) {
466 flags &= ~IBT_PATH_AVAIL;
467
468 IBTF_DPRINTF_L4(cmlog, "ibcm_handle_get_path: "
469 "Ignoring IBT_PATH_AVAIL flag, as only ONE path "
470 "information is requested.");
471 }
472
473 path_tq->flags = flags;
474 path_tq->max_paths = max_paths;
475 path_tq->paths = paths;
476 path_tq->num_paths_p = num_path_p;
477 path_tq->func = func;
478 path_tq->arg = arg;
479
480 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*path_tq))
481
482 if (func != NULL) { /* Non-Blocking */
483 IBTF_DPRINTF_L3(cmlog, "ibcm_handle_get_path: Non Blocking");
484 if (taskq_dispatch(ibcm_taskq, ibcm_process_async_get_paths,
485 path_tq, TQ_NOSLEEP) == 0) {
486 IBTF_DPRINTF_L2(cmlog, "ibcm_handle_get_path: "
487 "Failed to dispatch the TaskQ");
488 kmem_free(path_tq, len);
489 return (IBT_INSUFF_KERNEL_RESOURCE);
490 } else
491 return (IBT_SUCCESS);
492 } else { /* Blocking */
493 IBTF_DPRINTF_L3(cmlog, "ibcm_handle_get_path: Blocking");
494 return (ibcm_process_get_paths(path_tq));
495 }
496 }
497
498
499 static void
500 ibcm_process_async_get_paths(void *tq_arg)
501 {
720 len = 0;
721 }
722 num_dest = 0;
723 }
724
725 /* Allocate memory and accumulate all destination information */
726 len = (len * sizeof (ibcm_dest_t)) + sizeof (ibcm_dinfo_t);
727
728 dinfo = kmem_zalloc(len, KM_SLEEP);
729 dinfo->num_dest = num_dest;
730 if (p_arg->flags & IBT_PATH_PKEY)
731 dinfo->p_key = p_arg->attr.pa_pkey;
732
733 for (i = 0, j = 0; i < num_dest; i++) {
734 if (i < p_arg->attr.pa_num_dgids)
735 dinfo->dest[i].d_gid = p_arg->attr.pa_dgids[i];
736 else
737 dinfo->dest[i].d_gid = d_gids_p[j++];
738 }
739
740 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*p_arg))
741
742 /* IBTF allocates memory for path_info in case of Async Get Paths */
743 if (p_arg->paths == NULL)
744 p_arg->paths = kmem_zalloc(sizeof (ibt_path_info_t) * max_paths,
745 KM_SLEEP);
746
747 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*p_arg))
748
749 /*
750 * Get list of active HCA<->Port list, that matches input specified attr
751 */
752 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: Get Paths from \n HCA "
753 "(%llX:%d), SGID %llX:%llX", p_arg->attr.pa_hca_guid,
754 p_arg->attr.pa_hca_port_num, p_arg->attr.pa_sgid.gid_prefix,
755 p_arg->attr.pa_sgid.gid_guid);
756
757 retval = ibtl_cm_get_active_plist(&p_arg->attr, p_arg->flags, &slistp);
758 if (retval != IBT_SUCCESS) {
759 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: HCA capable of "
760 "requested source attributes NOT available.");
761 goto path_error;
762 }
763
764 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: HCA (%llX, %d)",
765 slistp->p_hca_guid, slistp->p_port_num);
766
767 hcap = ibcm_find_hca_entry(slistp->p_hca_guid);
768 if (hcap == NULL) {
777 if (i == 0) {
778 /* Validate whether this HCA supports APM */
779 if ((p_arg->flags & IBT_PATH_APM) &&
780 (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG))) {
781 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths:"
782 " HCA (%llX): APM NOT SUPPORTED ",
783 slistp[i].p_hca_guid);
784 retval = IBT_APM_NOT_SUPPORTED;
785 goto path_error1;
786 }
787 }
788
789 saa_handle = ibcm_get_saa_handle(hcap, slistp[i].p_port_num);
790 if (saa_handle == NULL) {
791 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: "
792 "SAA HDL NULL, HCA (%llX:%d) NOT ACTIVE",
793 slistp[i].p_hca_guid, slistp[i].p_port_num);
794 retval = IBT_HCA_PORT_NOT_ACTIVE;
795 goto path_error1;
796 }
797 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*slistp))
798 slistp[i].p_saa_hdl = saa_handle;
799 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*slistp))
800 }
801
802 /*
803 * If Service Name or Service ID are specified, first retrieve
804 * Service Records.
805 */
806 if ((p_arg->attr.pa_sid != 0) || ((p_arg->attr.pa_sname != NULL) &&
807 (strlen(p_arg->attr.pa_sname) != 0))) {
808
809 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: Get Service "
810 "Record for \n\t(%llX, \"%s\")", p_arg->attr.pa_sid,
811 ((p_arg->attr.pa_sname != NULL) ?
812 p_arg->attr.pa_sname : ""));
813
814 /* Get Service Records. */
815 retval = ibcm_saa_service_rec(p_arg, slistp, dinfo);
816 if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA)) {
817 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: Status="
818 "%d, Failed to get Service Record for \n\t"
819 "(%llX, \"%s\")", retval, p_arg->attr.pa_sid,
1420 mpr_req = kmem_zalloc(template_len, KM_SLEEP);
1421
1422 ASSERT(mpr_req != NULL);
1423
1424 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
1425 sizeof (sa_multipath_record_t));
1426
1427 /* Get the starting pointer where GIDs are stored. */
1428 gid_s_ptr = gid_ptr;
1429
1430 /* SGID */
1431 for (i = 0; i < sgid_cnt; i++) {
1432 *gid_ptr = sl[i].p_sgid;
1433
1434 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: SGID[%d] = "
1435 "(%llX:%llX)", i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
1436
1437 gid_ptr++;
1438 }
1439
1440 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req))
1441
1442 mpr_req->SGIDCount = sgid_cnt;
1443 c_mask = SA_MPR_COMPMASK_SGIDCOUNT;
1444
1445 /* DGIDs */
1446 for (i = 0; i < dinfo->num_dest; i++) {
1447 if (dinfo->dest[i].d_tag == 0) {
1448 *gid_ptr = dinfo->dest[i].d_gid;
1449
1450 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: "
1451 "DGID[%d] = (%llX:%llX)", i, gid_ptr->gid_prefix,
1452 gid_ptr->gid_guid);
1453 gid_ptr++;
1454 }
1455 }
1456
1457 mpr_req->DGIDCount = dgid_cnt;
1458 c_mask |= SA_MPR_COMPMASK_DGIDCOUNT;
1459
1460 /* Is Flow Label Specified. */
1461 if (attrp->pa_flow) {
1537 c_mask |= SA_MPR_COMPMASK_MTU |
1538 SA_MPR_COMPMASK_MTUSELECTOR;
1539 }
1540
1541 /* Is P_Key Specified or obtained during Service Look-up. */
1542 if (dinfo->p_key) {
1543 mpr_req->P_Key = dinfo->p_key;
1544 c_mask |= SA_MPR_COMPMASK_PKEY;
1545 }
1546
1547 /* We always get REVERSIBLE paths. */
1548 mpr_req->Reversible = 1;
1549 c_mask |= SA_MPR_COMPMASK_REVERSIBLE;
1550
1551 if (p_arg->flags & IBT_PATH_AVAIL) {
1552 mpr_req->IndependenceSelector = 1;
1553 c_mask |= SA_MPR_COMPMASK_INDEPSEL;
1554 }
1555
1556 /* we will not specify how many records we want. */
1557
1558 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req))
1559
1560 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: CMask: %llX Pkey: %X",
1561 c_mask, mpr_req->P_Key);
1562
1563 /* Contact SA Access to retrieve Path Records. */
1564 access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID;
1565 access_args.sq_access_type = IBMF_SAA_RETRIEVE;
1566 access_args.sq_component_mask = c_mask;
1567 access_args.sq_template = mpr_req;
1568 access_args.sq_template_length = sizeof (sa_multipath_record_t);
1569 access_args.sq_callback = NULL;
1570 access_args.sq_callback_arg = NULL;
1571
1572 retval = ibcm_contact_sa_access(sl->p_saa_hdl, &access_args, &length,
1573 &results_p);
1574 if (retval != IBT_SUCCESS) {
1575 *num_path = 0; /* Update the return count. */
1576 kmem_free(mpr_req, template_len);
1577 return (retval);
1578 }
1579
1951
1952 /* DGID */
1953 cep_p->cep_adds_vect.av_dgid = prec_resp->DGID;
1954
1955 /* CEP Timeout is NOT filled in by PATH routines. */
1956 cep_p->cep_timeout = 0;
1957
1958 IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: Done. Port=%d, PKey=%X\n"
1959 "SGID=%llX:%llX DGID=%llX:%llX", cep_p->cep_adds_vect.av_port_num,
1960 prec_resp->P_Key,
1961 prec_resp->SGID.gid_prefix, prec_resp->SGID.gid_guid,
1962 prec_resp->DGID.gid_prefix, prec_resp->DGID.gid_guid);
1963
1964 return (IBT_SUCCESS);
1965 }
1966
1967
1968 static void
1969 ibcm_fill_svcinfo(sa_service_record_t *sr_resp, ibcm_dest_t *dest)
1970 {
1971 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dest))
1972
1973 dest->d_gid = sr_resp->ServiceGID;
1974 dest->d_sid = sr_resp->ServiceID;
1975 ibcm_swizzle_to_srv(sr_resp->ServiceData, &dest->d_sdata);
1976 dest->d_pkey = sr_resp->ServiceP_Key;
1977
1978 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*dest))
1979
1980 IBTF_DPRINTF_L3(cmlog, "ibcm_fill_svcinfo: SID(%llX), GID(%llX:%llX)"
1981 "\n\tSvcPKey 0x%X", dest->d_sid, dest->d_gid.gid_prefix,
1982 dest->d_gid.gid_guid, dest->d_pkey);
1983 }
1984
1985
1986 static ib_gid_t
1987 ibcm_saa_get_agid(ibtl_cm_port_list_t *sl, ib_gid_t *gidp, uint_t ngid)
1988 {
1989 int k, l;
1990 ib_gid_t a_gid;
1991
1992 a_gid.gid_prefix = a_gid.gid_guid = 0;
1993
1994 for (k = 0; k < sl->p_count; k++) {
1995 for (l = 0; l < ngid; l++) {
1996
1997 if (gidp->gid_prefix == sl->p_sgid.gid_prefix) {
1998 a_gid = *gidp;
1999 break;
2753 }
2754
2755 get_alt_proceed:
2756
2757 if (new_sgid.gid_guid != 0) {
2758 retval = ibtl_cm_get_hca_port(new_sgid, 0, &n_hp);
2759 if (retval != IBT_SUCCESS) {
2760 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: "
2761 "Get HCA Port Failed: %d", retval);
2762 goto get_alt_path_done;
2763 }
2764 }
2765
2766 /* Calculate the size for multi-path records template */
2767 template_len = (2 * sizeof (ib_gid_t)) + sizeof (sa_multipath_record_t);
2768
2769 mpr_req = kmem_zalloc(template_len, KM_SLEEP);
2770
2771 ASSERT(mpr_req != NULL);
2772
2773 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req))
2774
2775 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
2776 sizeof (sa_multipath_record_t));
2777
2778 /* SGID */
2779 if (new_sgid.gid_guid == 0)
2780 *gid_ptr = cur_sgid;
2781 else
2782 *gid_ptr = new_sgid;
2783
2784 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Get Path Between "
2785 " SGID : %llX:%llX", gid_ptr->gid_prefix, gid_ptr->gid_guid);
2786
2787 gid_ptr++;
2788
2789 /* DGID */
2790 if (new_dgid.gid_guid == 0)
2791 *gid_ptr = cur_dgid;
2792 else
2793 *gid_ptr = new_dgid;
2794
2869 }
2870 }
2871
2872 /* Alt PathMTU can be GT or EQU to current channel's Pri PathMTU */
2873
2874 /* P_Key must be same as that of primary path */
2875 retval = ibt_index2pkey_byguid(c_hp.hp_hca_guid, c_hp.hp_port,
2876 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix,
2877 &mpr_req->P_Key);
2878 if (retval != IBT_SUCCESS) {
2879 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: Idx2Pkey Failed: %d",
2880 retval);
2881 goto get_alt_path_done;
2882 }
2883 c_mask |= SA_MPR_COMPMASK_PKEY;
2884
2885 mpr_req->Reversible = 1; /* We always get REVERSIBLE paths. */
2886 mpr_req->IndependenceSelector = 1;
2887 c_mask |= SA_MPR_COMPMASK_REVERSIBLE | SA_MPR_COMPMASK_INDEPSEL;
2888
2889 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req))
2890
2891 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: CMask: 0x%llX", c_mask);
2892
2893 /* NOTE: We will **NOT** specify how many records we want. */
2894
2895 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Primary: MTU %d, PKey[%d]="
2896 "0x%X\n\tSGID = %llX:%llX, DGID = %llX:%llX", prim_mtu,
2897 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, mpr_req->P_Key,
2898 cur_sgid.gid_prefix, cur_sgid.gid_guid, cur_dgid.gid_prefix,
2899 cur_dgid.gid_guid);
2900
2901 /* Get SA Access Handle. */
2902 if (new_sgid.gid_guid != 0)
2903 saa_handle = ibcm_get_saa_handle(hcap, n_hp.hp_port);
2904 else
2905 saa_handle = ibcm_get_saa_handle(hcap, c_hp.hp_port);
2906 if (saa_handle == NULL) {
2907 retval = IBT_HCA_PORT_NOT_ACTIVE;
2908 goto get_alt_path_done;
2909 }
2910
2950 &c_hp)) {
2951 IBTF_DPRINTF_L3(cmlog,
2952 "ibt_get_alt_path: PathRec obtained"
2953 " is similar to Prim Path, ignore "
2954 "this record");
2955 continue;
2956 }
2957 }
2958
2959 if (new_sgid.gid_guid == 0) {
2960 retval = ibcm_update_cep_info(pr_resp, NULL,
2961 &c_hp, &api_p->ap_alt_cep_path);
2962 } else {
2963 retval = ibcm_update_cep_info(pr_resp, NULL,
2964 &n_hp, &api_p->ap_alt_cep_path);
2965 }
2966 if (retval != IBT_SUCCESS)
2967 continue;
2968
2969 /* Update some leftovers */
2970 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*api_p))
2971
2972 api_p->ap_alt_pkt_lt = pr_resp->PacketLifeTime;
2973
2974 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*api_p))
2975
2976 rec_found = 1;
2977 break;
2978 }
2979 kmem_free(results_p, length);
2980 }
2981
2982 if (rec_found == 0) {
2983 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Alternate Path cannot"
2984 " be established");
2985 retval = IBT_PATH_RECORDS_NOT_FOUND;
2986 } else
2987 retval = IBT_SUCCESS;
2988
2989 get_alt_path_done:
2990 if ((snum) && (sgids_p))
2991 kmem_free(sgids_p, snum * sizeof (ib_gid_t));
2992
2993 if ((dnum) && (dgids_p))
2994 kmem_free(dgids_p, dnum * sizeof (ib_gid_t));
2995
3011 ibt_path_info_t *paths;
3012 ibt_path_ip_src_t *src_ip_p;
3013 uint8_t *num_paths_p;
3014 ibt_ip_path_handler_t func;
3015 void *arg;
3016 ibt_path_flags_t flags;
3017 ibt_clnt_hdl_t ibt_hdl;
3018 kmutex_t ip_lock;
3019 kcondvar_t ip_cv;
3020 boolean_t ip_done;
3021 ibt_status_t retval;
3022 uint_t len;
3023 } ibcm_ip_path_tqargs_t;
3024
3025 /* Holds destination information needed to fill in ibt_path_info_t. */
3026 typedef struct ibcm_ip_dinfo_s {
3027 uint8_t num_dest;
3028 ib_gid_t d_gid[1];
3029 } ibcm_ip_dinfo_t;
3030
3031 _NOTE(SCHEME_PROTECTS_DATA("Temporary path storage", ibcm_ip_dinfo_s))
3032
3033 /* Prototype Declarations. */
3034 static void ibcm_process_get_ip_paths(void *tq_arg);
3035 static ibt_status_t ibcm_get_ip_spr(ibcm_ip_path_tqargs_t *,
3036 ibtl_cm_port_list_t *, ibcm_ip_dinfo_t *, uint8_t *, ibt_path_info_t *);
3037 static ibt_status_t ibcm_get_ip_mpr(ibcm_ip_path_tqargs_t *,
3038 ibtl_cm_port_list_t *, ibcm_ip_dinfo_t *dinfo,
3039 uint8_t *, ibt_path_info_t *);
3040
3041 /*
3042 * Perform SA Access to retrieve Path Records.
3043 */
3044 static ibt_status_t
3045 ibcm_saa_ip_pr(ibcm_ip_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl,
3046 ibcm_ip_dinfo_t *dinfo, uint8_t *max_count)
3047 {
3048 uint8_t num_path = *max_count;
3049 uint8_t rec_found = 0;
3050 ibt_status_t retval = IBT_SUCCESS;
3051 uint8_t i, j;
3052
3417 mpr_req = kmem_zalloc(template_len, KM_SLEEP);
3418
3419 ASSERT(mpr_req != NULL);
3420
3421 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
3422 sizeof (sa_multipath_record_t));
3423
3424 /* Get the starting pointer where GIDs are stored. */
3425 gid_s_ptr = gid_ptr;
3426
3427 /* SGID */
3428 for (i = 0; i < sgid_cnt; i++) {
3429 *gid_ptr = sl[i].p_sgid;
3430
3431 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: SGID[%d] = %llX:%llX",
3432 i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
3433
3434 gid_ptr++;
3435 }
3436
3437 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req))
3438
3439 mpr_req->SGIDCount = sgid_cnt;
3440 c_mask = SA_MPR_COMPMASK_SGIDCOUNT;
3441
3442 /* DGIDs */
3443 for (i = 0; i < dgid_cnt; i++) {
3444 *gid_ptr = dinfo->d_gid[i];
3445
3446 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: DGID[%d] = "
3447 "%llX:%llX", i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
3448 gid_ptr++;
3449 }
3450
3451 mpr_req->DGIDCount = dgid_cnt;
3452 c_mask |= SA_MPR_COMPMASK_DGIDCOUNT;
3453
3454 /* Is Flow Label Specified. */
3455 if (attrp->ipa_flow) {
3456 mpr_req->FlowLabel = attrp->ipa_flow;
3457 c_mask |= SA_MPR_COMPMASK_FLOWLABEL;
3458 }
3526 /* Is MTU specified. */
3527 if (attrp->ipa_mtu.r_mtu) {
3528 mpr_req->Mtu = attrp->ipa_mtu.r_mtu;
3529 mpr_req->MtuSelector = attrp->ipa_mtu.r_selector;
3530
3531 c_mask |= SA_MPR_COMPMASK_MTU |
3532 SA_MPR_COMPMASK_MTUSELECTOR;
3533 }
3534
3535 /* We always get REVERSIBLE paths. */
3536 mpr_req->Reversible = 1;
3537 c_mask |= SA_MPR_COMPMASK_REVERSIBLE;
3538
3539 if (p_arg->flags & IBT_PATH_AVAIL) {
3540 mpr_req->IndependenceSelector = 1;
3541 c_mask |= SA_MPR_COMPMASK_INDEPSEL;
3542 }
3543
3544 /* we will not specify how many records we want. */
3545
3546 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req))
3547
3548 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: CMask: %llX Pkey: %X",
3549 c_mask, mpr_req->P_Key);
3550
3551 /* Contact SA Access to retrieve Path Records. */
3552 access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID;
3553 access_args.sq_access_type = IBMF_SAA_RETRIEVE;
3554 access_args.sq_component_mask = c_mask;
3555 access_args.sq_template = mpr_req;
3556 access_args.sq_template_length = sizeof (sa_multipath_record_t);
3557 access_args.sq_callback = NULL;
3558 access_args.sq_callback_arg = NULL;
3559
3560 retval = ibcm_contact_sa_access(sl->p_saa_hdl, &access_args, &length,
3561 &results_p);
3562 if (retval != IBT_SUCCESS) {
3563 *num_path = 0; /* Update the return count. */
3564 kmem_free(mpr_req, template_len);
3565 return (retval);
3566 }
3567
3832 if ((retval != IBT_SUCCESS) &&
3833 (retval != IBT_GIDS_NOT_FOUND)) {
3834 IBTF_DPRINTF_L2(cmlog,
3835 "ibcm_process_get_ip_paths: "
3836 "Invalid DGIDs specified w/ APM Flag");
3837 goto ippath_error2;
3838 }
3839 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths: "
3840 "Found %d Comp DGID", dnum);
3841
3842 if (dnum) {
3843 dinfo->d_gid[i] = d_gids_p[0];
3844 i++;
3845 }
3846 }
3847 }
3848
3849 /* "i" will get us num_dest count. */
3850 dinfo->num_dest = i;
3851
3852 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*p_arg))
3853
3854 /*
3855 * IBTF allocates memory for path_info & src_ip in case of
3856 * Async Get IP Paths
3857 */
3858 if (p_arg->func) { /* Do these only for Async Get Paths */
3859 p_arg->paths = kmem_zalloc(sizeof (ibt_path_info_t) * max_paths,
3860 KM_SLEEP);
3861 if (p_arg->src_ip_p == NULL)
3862 p_arg->src_ip_p = kmem_zalloc(
3863 sizeof (ibt_path_ip_src_t) * max_paths, KM_SLEEP);
3864 }
3865
3866 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*p_arg))
3867
3868 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths: HCA (%llX, %d)",
3869 sl->p_hca_guid, sl->p_port_num);
3870
3871 hcap = ibcm_find_hca_entry(sl->p_hca_guid);
3872 if (hcap == NULL) {
3873 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
3874 "NO HCA found");
3875 retval = IBT_HCA_BUSY_DETACHING;
3876 goto ippath_error2;
3877 }
3878
3879 /* Get SA Access Handle. */
3880 for (i = 0; i < sl->p_count; i++) {
3881 if (i == 0) {
3882 /* Validate whether this HCA supports APM */
3883 if ((p_arg->flags & IBT_PATH_APM) &&
3884 (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG))) {
3885 IBTF_DPRINTF_L2(cmlog,
3886 "ibcm_process_get_ip_paths: HCA (%llX): "
3887 "APM NOT SUPPORTED", sl[i].p_hca_guid);
3888 retval = IBT_APM_NOT_SUPPORTED;
3889 goto ippath_error3;
3890 }
3891 }
3892
3893 saa_handle = ibcm_get_saa_handle(hcap, sl[i].p_port_num);
3894 if (saa_handle == NULL) {
3895 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
3896 "SAA HDL NULL, HCA (%llX:%d) NOT ACTIVE",
3897 sl[i].p_hca_guid, sl[i].p_port_num);
3898 retval = IBT_HCA_PORT_NOT_ACTIVE;
3899 goto ippath_error3;
3900 }
3901 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sl))
3902 sl[i].p_saa_hdl = saa_handle;
3903 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sl))
3904 }
3905
3906 /* Get Path Records. */
3907 retval = ibcm_saa_ip_pr(p_arg, sl, dinfo, &num_path);
3908
3909 ippath_error3:
3910 ibcm_dec_hca_acc_cnt(hcap);
3911
3912 ippath_error2:
3913 if (dinfo && len)
3914 kmem_free(dinfo, len);
3915
3916 ippath_error1:
3917 if (sl)
3918 ibtl_cm_free_active_plist(sl);
3919
3920 ippath_error:
3921 if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA))
3922 num_path = 0;
3923
3924 if (p_arg->num_paths_p != NULL)
3925 *p_arg->num_paths_p = num_path;
3926
3927 if (p_arg->func) { /* Do these only for Async Get Paths */
3928 ibt_path_info_t *tmp_path_p;
3929 ibt_path_ip_src_t *tmp_src_ip_p;
3930
3931 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*p_arg))
3932 p_arg->retval = retval;
3933 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*p_arg))
3934
3935 if (retval == IBT_INSUFF_DATA) {
3936 /*
3937 * We allocated earlier memory based on "max_paths",
3938 * but we got lesser path-records, so re-adjust that
3939 * buffer so that caller can free the correct memory.
3940 */
3941 tmp_path_p = kmem_alloc(
3942 sizeof (ibt_path_info_t) * num_path, KM_SLEEP);
3943
3944 bcopy(p_arg->paths, tmp_path_p,
3945 num_path * sizeof (ibt_path_info_t));
3946
3947 kmem_free(p_arg->paths,
3948 sizeof (ibt_path_info_t) * max_paths);
3949
3950 tmp_src_ip_p = kmem_alloc(
3951 sizeof (ibt_path_ip_src_t) * num_path, KM_SLEEP);
3952
3953 bcopy(p_arg->src_ip_p, tmp_src_ip_p,
4117 ibt_path_ip_src_t *src_ip_p, ibt_ip_path_handler_t func, void *arg)
4118 {
4119 ibcm_ip_path_tqargs_t *path_tq;
4120 int sleep_flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
4121 uint_t len, ret;
4122 ibt_status_t retval;
4123
4124 retval = ibcm_val_ipattr(attrp, flags);
4125 if (retval != IBT_SUCCESS)
4126 return (retval);
4127
4128 len = (attrp->ipa_ndst * sizeof (ibt_ip_addr_t)) +
4129 sizeof (ibcm_ip_path_tqargs_t);
4130 path_tq = kmem_zalloc(len, sleep_flag);
4131 if (path_tq == NULL) {
4132 IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_path: "
4133 "Unable to allocate memory for local usage.");
4134 return (IBT_INSUFF_KERNEL_RESOURCE);
4135 }
4136
4137 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*path_tq))
4138 bcopy(attrp, &path_tq->attr, sizeof (ibt_ip_path_attr_t));
4139
4140 path_tq->attr.ipa_dst_ip = (ibt_ip_addr_t *)(((uchar_t *)path_tq) +
4141 sizeof (ibcm_ip_path_tqargs_t));
4142 bcopy(attrp->ipa_dst_ip, path_tq->attr.ipa_dst_ip,
4143 sizeof (ibt_ip_addr_t) * attrp->ipa_ndst);
4144
4145 /* Ignore IBT_PATH_AVAIL flag, if only one path is requested. */
4146 if ((flags & IBT_PATH_AVAIL) && (attrp->ipa_max_paths == 1)) {
4147 flags &= ~IBT_PATH_AVAIL;
4148
4149 IBTF_DPRINTF_L4(cmlog, "ibcm_get_ip_path: Ignoring "
4150 "IBT_PATH_AVAIL flag, as only ONE path info is requested.");
4151 }
4152
4153 path_tq->flags = flags;
4154 path_tq->ibt_hdl = ibt_hdl;
4155 path_tq->paths = paths;
4156 path_tq->src_ip_p = src_ip_p;
4157 path_tq->num_paths_p = num_path_p;
4158 path_tq->func = func;
4159 path_tq->arg = arg;
4160 path_tq->len = len;
4161 path_tq->ip_done = B_FALSE;
4162 if (func == NULL) { /* Blocking */
4163 mutex_init(&path_tq->ip_lock, NULL, MUTEX_DEFAULT, NULL);
4164 cv_init(&path_tq->ip_cv, NULL, CV_DRIVER, NULL);
4165 }
4166
4167 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*path_tq))
4168
4169 sleep_flag = ((func == NULL) ? TQ_SLEEP : TQ_NOSLEEP);
4170 ret = taskq_dispatch(ibcm_taskq, ibcm_process_get_ip_paths, path_tq,
4171 sleep_flag);
4172 if (ret == 0) {
4173 IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_path: Failed to dispatch "
4174 "the TaskQ");
4175 if (func == NULL) { /* Blocking */
4176 cv_destroy(&path_tq->ip_cv);
4177 mutex_destroy(&path_tq->ip_lock);
4178 }
4179 kmem_free(path_tq, len);
4180 retval = IBT_INSUFF_KERNEL_RESOURCE;
4181 } else {
4182 if (func != NULL) { /* Non-Blocking */
4183 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_path: NonBlocking");
4184 retval = IBT_SUCCESS;
4185 } else { /* Blocking */
4186 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_path: Blocking");
4187 mutex_enter(&path_tq->ip_lock);
4188 while (path_tq->ip_done != B_TRUE)
4430 */
4431 }
4432
4433 get_ip_alt_proceed:
4434 if (new_sgid.gid_guid != 0) {
4435 retval = ibtl_cm_get_hca_port(new_sgid, 0, &n_hp);
4436 if (retval != IBT_SUCCESS) {
4437 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: "
4438 "Get HCA Port Failed: %d", retval);
4439 goto get_ip_alt_path_done;
4440 }
4441 }
4442
4443 /* Calculate the size for multi-path records template */
4444 template_len = (2 * sizeof (ib_gid_t)) + sizeof (sa_multipath_record_t);
4445
4446 mpr_req = kmem_zalloc(template_len, KM_SLEEP);
4447
4448 ASSERT(mpr_req != NULL);
4449
4450 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req))
4451
4452 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
4453 sizeof (sa_multipath_record_t));
4454
4455 /* SGID */
4456 if (new_sgid.gid_guid == 0)
4457 *gid_ptr = cur_sgid;
4458 else
4459 *gid_ptr = new_sgid;
4460
4461 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Get Path Between "
4462 " SGID : %llX:%llX", gid_ptr->gid_prefix, gid_ptr->gid_guid);
4463
4464 gid_ptr++;
4465
4466 /* DGID */
4467 if (new_dgid.gid_guid == 0)
4468 *gid_ptr = cur_dgid;
4469 else
4470 *gid_ptr = new_dgid;
4471
4546 }
4547 }
4548
4549 /* Alt PathMTU can be GT or EQU to current channel's Pri PathMTU */
4550
4551 /* P_Key must be same as that of primary path */
4552 retval = ibt_index2pkey_byguid(c_hp.hp_hca_guid, c_hp.hp_port,
4553 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix,
4554 &mpr_req->P_Key);
4555 if (retval != IBT_SUCCESS) {
4556 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: PKeyIdx2Pkey "
4557 "Failed: %d", retval);
4558 goto get_ip_alt_path_done;
4559 }
4560 c_mask |= SA_MPR_COMPMASK_PKEY;
4561
4562 mpr_req->Reversible = 1; /* We always get REVERSIBLE paths. */
4563 mpr_req->IndependenceSelector = 1;
4564 c_mask |= SA_MPR_COMPMASK_REVERSIBLE | SA_MPR_COMPMASK_INDEPSEL;
4565
4566 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req))
4567
4568 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: CMask: 0x%llX", c_mask);
4569
4570 /* NOTE: We will **NOT** specify how many records we want. */
4571
4572 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Primary: MTU %d, PKey[%d]="
4573 "0x%X\n\tSGID = %llX:%llX, DGID = %llX:%llX", prim_mtu,
4574 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, mpr_req->P_Key,
4575 cur_sgid.gid_prefix, cur_sgid.gid_guid, cur_dgid.gid_prefix,
4576 cur_dgid.gid_guid);
4577
4578 /* Get SA Access Handle. */
4579 if (new_sgid.gid_guid != 0)
4580 saa_handle = ibcm_get_saa_handle(hcap, n_hp.hp_port);
4581 else
4582 saa_handle = ibcm_get_saa_handle(hcap, c_hp.hp_port);
4583 if (saa_handle == NULL) {
4584 retval = IBT_HCA_PORT_NOT_ACTIVE;
4585 goto get_ip_alt_path_done;
4586 }
4587
4627 &c_hp)) {
4628 IBTF_DPRINTF_L3(cmlog,
4629 "ibt_get_ip_alt_path: PathRec "
4630 "obtained is similar to Prim Path, "
4631 "ignore this record");
4632 continue;
4633 }
4634 }
4635
4636 if (new_sgid.gid_guid == 0) {
4637 retval = ibcm_update_cep_info(pr_resp, NULL,
4638 &c_hp, &api_p->ap_alt_cep_path);
4639 } else {
4640 retval = ibcm_update_cep_info(pr_resp, NULL,
4641 &n_hp, &api_p->ap_alt_cep_path);
4642 }
4643 if (retval != IBT_SUCCESS)
4644 continue;
4645
4646 /* Update some leftovers */
4647 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*api_p))
4648
4649 api_p->ap_alt_pkt_lt = pr_resp->PacketLifeTime;
4650
4651 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*api_p))
4652
4653 rec_found = 1;
4654 break;
4655 }
4656 kmem_free(results_p, length);
4657 }
4658
4659 if (rec_found == 0) {
4660 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: AltPath cannot"
4661 " be established");
4662 retval = IBT_PATH_RECORDS_NOT_FOUND;
4663 } else
4664 retval = IBT_SUCCESS;
4665
4666 get_ip_alt_path_done:
4667 if ((snum) && (sgids_p))
4668 kmem_free(sgids_p, snum * sizeof (ib_gid_t));
4669
4670 if ((dnum) && (dgids_p))
4671 kmem_free(dgids_p, dnum * sizeof (ib_gid_t));
4672
4673 ibcm_dec_hca_acc_cnt(hcap);
4674
4675 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Done (status %d)", retval);
4676
4677 return (retval);
4678 }
4679
4680
4681 /* Routines for warlock */
4682
4683 /* ARGSUSED */
4684 static void
4685 ibcm_dummy_path_handler(void *arg, ibt_status_t retval, ibt_path_info_t *paths,
4686 uint8_t num_path)
4687 {
4688 ibcm_path_tqargs_t dummy_path;
4689
4690 dummy_path.func = ibcm_dummy_path_handler;
4691
4692 IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_path_handler: "
4693 "dummy_path.func %p", dummy_path.func);
4694 }
4695
4696 /* ARGSUSED */
4697 static void
4698 ibcm_dummy_ip_path_handler(void *arg, ibt_status_t retval,
4699 ibt_path_info_t *paths, uint8_t num_path, ibt_path_ip_src_t *src_ip)
4700 {
4701 ibcm_ip_path_tqargs_t dummy_path;
4702
4703 dummy_path.func = ibcm_dummy_ip_path_handler;
4704
4705 IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_ip_path_handler: "
4706 "dummy_path.func %p", dummy_path.func);
4707 }
|
31 *
32 * ibt_get_paths() implement the Path Informations related functionality.
33 */
34
35 /* ibcm_saa_service_rec() fills in ServiceID and DGID. */
36 typedef struct ibcm_dest_s {
37 ib_gid_t d_gid;
38 ib_svc_id_t d_sid;
39 ibt_srv_data_t d_sdata;
40 ib_pkey_t d_pkey;
41 uint_t d_tag; /* 0 = Unicast, 1 = Multicast */
42 } ibcm_dest_t;
43
44 /* Holds Destination information needed to fill in ibt_path_info_t. */
45 typedef struct ibcm_dinfo_s {
46 uint8_t num_dest;
47 ib_pkey_t p_key;
48 ibcm_dest_t dest[1];
49 } ibcm_dinfo_t;
50
51 typedef struct ibcm_path_tqargs_s {
52 ibt_path_attr_t attr;
53 ibt_path_info_t *paths;
54 uint8_t *num_paths_p;
55 ibt_path_handler_t func;
56 void *arg;
57 ibt_path_flags_t flags;
58 uint8_t max_paths;
59 } ibcm_path_tqargs_t;
60
61
62 /* Prototype Declarations. */
63 static ibt_status_t ibcm_saa_path_rec(ibcm_path_tqargs_t *,
64 ibtl_cm_port_list_t *, ibcm_dinfo_t *, uint8_t *);
65
66 static ibt_status_t ibcm_update_cep_info(sa_path_record_t *,
67 ibtl_cm_port_list_t *, ibtl_cm_hca_port_t *, ibt_cep_path_t *);
68
69 static ibt_status_t ibcm_saa_service_rec(ibcm_path_tqargs_t *,
70 ibtl_cm_port_list_t *, ibcm_dinfo_t *);
427 {
428 ibcm_path_tqargs_t *path_tq;
429 int sleep_flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
430 int len;
431 ibt_status_t retval;
432
433 retval = ibcm_validate_path_attributes(attrp, flags, max_paths);
434 if (retval != IBT_SUCCESS)
435 return (retval);
436
437 len = (attrp->pa_num_dgids * sizeof (ib_gid_t)) +
438 sizeof (ibcm_path_tqargs_t);
439
440 path_tq = kmem_alloc(len, sleep_flag);
441 if (path_tq == NULL) {
442 IBTF_DPRINTF_L2(cmlog, "ibcm_handle_get_path: "
443 "Unable to allocate memory for local usage.");
444 return (IBT_INSUFF_KERNEL_RESOURCE);
445 }
446
447 bcopy(attrp, &path_tq->attr, sizeof (ibt_path_attr_t));
448
449 if (attrp->pa_num_dgids) {
450 path_tq->attr.pa_dgids = (ib_gid_t *)(((uchar_t *)path_tq) +
451 sizeof (ibcm_path_tqargs_t));
452
453 bcopy(attrp->pa_dgids, path_tq->attr.pa_dgids,
454 sizeof (ib_gid_t) * attrp->pa_num_dgids);
455 } else {
456 path_tq->attr.pa_dgids = NULL;
457 }
458
459 /* Ignore IBT_PATH_AVAIL flag, if only one path is requested. */
460 if ((flags & IBT_PATH_AVAIL) && (max_paths == 1)) {
461 flags &= ~IBT_PATH_AVAIL;
462
463 IBTF_DPRINTF_L4(cmlog, "ibcm_handle_get_path: "
464 "Ignoring IBT_PATH_AVAIL flag, as only ONE path "
465 "information is requested.");
466 }
467
468 path_tq->flags = flags;
469 path_tq->max_paths = max_paths;
470 path_tq->paths = paths;
471 path_tq->num_paths_p = num_path_p;
472 path_tq->func = func;
473 path_tq->arg = arg;
474
475 if (func != NULL) { /* Non-Blocking */
476 IBTF_DPRINTF_L3(cmlog, "ibcm_handle_get_path: Non Blocking");
477 if (taskq_dispatch(ibcm_taskq, ibcm_process_async_get_paths,
478 path_tq, TQ_NOSLEEP) == 0) {
479 IBTF_DPRINTF_L2(cmlog, "ibcm_handle_get_path: "
480 "Failed to dispatch the TaskQ");
481 kmem_free(path_tq, len);
482 return (IBT_INSUFF_KERNEL_RESOURCE);
483 } else
484 return (IBT_SUCCESS);
485 } else { /* Blocking */
486 IBTF_DPRINTF_L3(cmlog, "ibcm_handle_get_path: Blocking");
487 return (ibcm_process_get_paths(path_tq));
488 }
489 }
490
491
492 static void
493 ibcm_process_async_get_paths(void *tq_arg)
494 {
713 len = 0;
714 }
715 num_dest = 0;
716 }
717
718 /* Allocate memory and accumulate all destination information */
719 len = (len * sizeof (ibcm_dest_t)) + sizeof (ibcm_dinfo_t);
720
721 dinfo = kmem_zalloc(len, KM_SLEEP);
722 dinfo->num_dest = num_dest;
723 if (p_arg->flags & IBT_PATH_PKEY)
724 dinfo->p_key = p_arg->attr.pa_pkey;
725
726 for (i = 0, j = 0; i < num_dest; i++) {
727 if (i < p_arg->attr.pa_num_dgids)
728 dinfo->dest[i].d_gid = p_arg->attr.pa_dgids[i];
729 else
730 dinfo->dest[i].d_gid = d_gids_p[j++];
731 }
732
733 /* IBTF allocates memory for path_info in case of Async Get Paths */
734 if (p_arg->paths == NULL)
735 p_arg->paths = kmem_zalloc(sizeof (ibt_path_info_t) * max_paths,
736 KM_SLEEP);
737
738 /*
739 * Get list of active HCA<->Port list, that matches input specified attr
740 */
741 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: Get Paths from \n HCA "
742 "(%llX:%d), SGID %llX:%llX", p_arg->attr.pa_hca_guid,
743 p_arg->attr.pa_hca_port_num, p_arg->attr.pa_sgid.gid_prefix,
744 p_arg->attr.pa_sgid.gid_guid);
745
746 retval = ibtl_cm_get_active_plist(&p_arg->attr, p_arg->flags, &slistp);
747 if (retval != IBT_SUCCESS) {
748 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: HCA capable of "
749 "requested source attributes NOT available.");
750 goto path_error;
751 }
752
753 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: HCA (%llX, %d)",
754 slistp->p_hca_guid, slistp->p_port_num);
755
756 hcap = ibcm_find_hca_entry(slistp->p_hca_guid);
757 if (hcap == NULL) {
766 if (i == 0) {
767 /* Validate whether this HCA supports APM */
768 if ((p_arg->flags & IBT_PATH_APM) &&
769 (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG))) {
770 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths:"
771 " HCA (%llX): APM NOT SUPPORTED ",
772 slistp[i].p_hca_guid);
773 retval = IBT_APM_NOT_SUPPORTED;
774 goto path_error1;
775 }
776 }
777
778 saa_handle = ibcm_get_saa_handle(hcap, slistp[i].p_port_num);
779 if (saa_handle == NULL) {
780 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: "
781 "SAA HDL NULL, HCA (%llX:%d) NOT ACTIVE",
782 slistp[i].p_hca_guid, slistp[i].p_port_num);
783 retval = IBT_HCA_PORT_NOT_ACTIVE;
784 goto path_error1;
785 }
786 slistp[i].p_saa_hdl = saa_handle;
787 }
788
789 /*
790 * If Service Name or Service ID are specified, first retrieve
791 * Service Records.
792 */
793 if ((p_arg->attr.pa_sid != 0) || ((p_arg->attr.pa_sname != NULL) &&
794 (strlen(p_arg->attr.pa_sname) != 0))) {
795
796 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: Get Service "
797 "Record for \n\t(%llX, \"%s\")", p_arg->attr.pa_sid,
798 ((p_arg->attr.pa_sname != NULL) ?
799 p_arg->attr.pa_sname : ""));
800
801 /* Get Service Records. */
802 retval = ibcm_saa_service_rec(p_arg, slistp, dinfo);
803 if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA)) {
804 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: Status="
805 "%d, Failed to get Service Record for \n\t"
806 "(%llX, \"%s\")", retval, p_arg->attr.pa_sid,
1407 mpr_req = kmem_zalloc(template_len, KM_SLEEP);
1408
1409 ASSERT(mpr_req != NULL);
1410
1411 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
1412 sizeof (sa_multipath_record_t));
1413
1414 /* Get the starting pointer where GIDs are stored. */
1415 gid_s_ptr = gid_ptr;
1416
1417 /* SGID */
1418 for (i = 0; i < sgid_cnt; i++) {
1419 *gid_ptr = sl[i].p_sgid;
1420
1421 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: SGID[%d] = "
1422 "(%llX:%llX)", i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
1423
1424 gid_ptr++;
1425 }
1426
1427 mpr_req->SGIDCount = sgid_cnt;
1428 c_mask = SA_MPR_COMPMASK_SGIDCOUNT;
1429
1430 /* DGIDs */
1431 for (i = 0; i < dinfo->num_dest; i++) {
1432 if (dinfo->dest[i].d_tag == 0) {
1433 *gid_ptr = dinfo->dest[i].d_gid;
1434
1435 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: "
1436 "DGID[%d] = (%llX:%llX)", i, gid_ptr->gid_prefix,
1437 gid_ptr->gid_guid);
1438 gid_ptr++;
1439 }
1440 }
1441
1442 mpr_req->DGIDCount = dgid_cnt;
1443 c_mask |= SA_MPR_COMPMASK_DGIDCOUNT;
1444
1445 /* Is Flow Label Specified. */
1446 if (attrp->pa_flow) {
1522 c_mask |= SA_MPR_COMPMASK_MTU |
1523 SA_MPR_COMPMASK_MTUSELECTOR;
1524 }
1525
1526 /* Is P_Key Specified or obtained during Service Look-up. */
1527 if (dinfo->p_key) {
1528 mpr_req->P_Key = dinfo->p_key;
1529 c_mask |= SA_MPR_COMPMASK_PKEY;
1530 }
1531
1532 /* We always get REVERSIBLE paths. */
1533 mpr_req->Reversible = 1;
1534 c_mask |= SA_MPR_COMPMASK_REVERSIBLE;
1535
1536 if (p_arg->flags & IBT_PATH_AVAIL) {
1537 mpr_req->IndependenceSelector = 1;
1538 c_mask |= SA_MPR_COMPMASK_INDEPSEL;
1539 }
1540
1541 /* we will not specify how many records we want. */
1542 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: CMask: %llX Pkey: %X",
1543 c_mask, mpr_req->P_Key);
1544
1545 /* Contact SA Access to retrieve Path Records. */
1546 access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID;
1547 access_args.sq_access_type = IBMF_SAA_RETRIEVE;
1548 access_args.sq_component_mask = c_mask;
1549 access_args.sq_template = mpr_req;
1550 access_args.sq_template_length = sizeof (sa_multipath_record_t);
1551 access_args.sq_callback = NULL;
1552 access_args.sq_callback_arg = NULL;
1553
1554 retval = ibcm_contact_sa_access(sl->p_saa_hdl, &access_args, &length,
1555 &results_p);
1556 if (retval != IBT_SUCCESS) {
1557 *num_path = 0; /* Update the return count. */
1558 kmem_free(mpr_req, template_len);
1559 return (retval);
1560 }
1561
1933
1934 /* DGID */
1935 cep_p->cep_adds_vect.av_dgid = prec_resp->DGID;
1936
1937 /* CEP Timeout is NOT filled in by PATH routines. */
1938 cep_p->cep_timeout = 0;
1939
1940 IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: Done. Port=%d, PKey=%X\n"
1941 "SGID=%llX:%llX DGID=%llX:%llX", cep_p->cep_adds_vect.av_port_num,
1942 prec_resp->P_Key,
1943 prec_resp->SGID.gid_prefix, prec_resp->SGID.gid_guid,
1944 prec_resp->DGID.gid_prefix, prec_resp->DGID.gid_guid);
1945
1946 return (IBT_SUCCESS);
1947 }
1948
1949
1950 static void
1951 ibcm_fill_svcinfo(sa_service_record_t *sr_resp, ibcm_dest_t *dest)
1952 {
1953 dest->d_gid = sr_resp->ServiceGID;
1954 dest->d_sid = sr_resp->ServiceID;
1955 ibcm_swizzle_to_srv(sr_resp->ServiceData, &dest->d_sdata);
1956 dest->d_pkey = sr_resp->ServiceP_Key;
1957
1958 IBTF_DPRINTF_L3(cmlog, "ibcm_fill_svcinfo: SID(%llX), GID(%llX:%llX)"
1959 "\n\tSvcPKey 0x%X", dest->d_sid, dest->d_gid.gid_prefix,
1960 dest->d_gid.gid_guid, dest->d_pkey);
1961 }
1962
1963
1964 static ib_gid_t
1965 ibcm_saa_get_agid(ibtl_cm_port_list_t *sl, ib_gid_t *gidp, uint_t ngid)
1966 {
1967 int k, l;
1968 ib_gid_t a_gid;
1969
1970 a_gid.gid_prefix = a_gid.gid_guid = 0;
1971
1972 for (k = 0; k < sl->p_count; k++) {
1973 for (l = 0; l < ngid; l++) {
1974
1975 if (gidp->gid_prefix == sl->p_sgid.gid_prefix) {
1976 a_gid = *gidp;
1977 break;
2731 }
2732
2733 get_alt_proceed:
2734
2735 if (new_sgid.gid_guid != 0) {
2736 retval = ibtl_cm_get_hca_port(new_sgid, 0, &n_hp);
2737 if (retval != IBT_SUCCESS) {
2738 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: "
2739 "Get HCA Port Failed: %d", retval);
2740 goto get_alt_path_done;
2741 }
2742 }
2743
2744 /* Calculate the size for multi-path records template */
2745 template_len = (2 * sizeof (ib_gid_t)) + sizeof (sa_multipath_record_t);
2746
2747 mpr_req = kmem_zalloc(template_len, KM_SLEEP);
2748
2749 ASSERT(mpr_req != NULL);
2750
2751 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
2752 sizeof (sa_multipath_record_t));
2753
2754 /* SGID */
2755 if (new_sgid.gid_guid == 0)
2756 *gid_ptr = cur_sgid;
2757 else
2758 *gid_ptr = new_sgid;
2759
2760 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Get Path Between "
2761 " SGID : %llX:%llX", gid_ptr->gid_prefix, gid_ptr->gid_guid);
2762
2763 gid_ptr++;
2764
2765 /* DGID */
2766 if (new_dgid.gid_guid == 0)
2767 *gid_ptr = cur_dgid;
2768 else
2769 *gid_ptr = new_dgid;
2770
2845 }
2846 }
2847
2848 /* Alt PathMTU can be GT or EQU to current channel's Pri PathMTU */
2849
2850 /* P_Key must be same as that of primary path */
2851 retval = ibt_index2pkey_byguid(c_hp.hp_hca_guid, c_hp.hp_port,
2852 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix,
2853 &mpr_req->P_Key);
2854 if (retval != IBT_SUCCESS) {
2855 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: Idx2Pkey Failed: %d",
2856 retval);
2857 goto get_alt_path_done;
2858 }
2859 c_mask |= SA_MPR_COMPMASK_PKEY;
2860
2861 mpr_req->Reversible = 1; /* We always get REVERSIBLE paths. */
2862 mpr_req->IndependenceSelector = 1;
2863 c_mask |= SA_MPR_COMPMASK_REVERSIBLE | SA_MPR_COMPMASK_INDEPSEL;
2864
2865 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: CMask: 0x%llX", c_mask);
2866
2867 /* NOTE: We will **NOT** specify how many records we want. */
2868
2869 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Primary: MTU %d, PKey[%d]="
2870 "0x%X\n\tSGID = %llX:%llX, DGID = %llX:%llX", prim_mtu,
2871 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, mpr_req->P_Key,
2872 cur_sgid.gid_prefix, cur_sgid.gid_guid, cur_dgid.gid_prefix,
2873 cur_dgid.gid_guid);
2874
2875 /* Get SA Access Handle. */
2876 if (new_sgid.gid_guid != 0)
2877 saa_handle = ibcm_get_saa_handle(hcap, n_hp.hp_port);
2878 else
2879 saa_handle = ibcm_get_saa_handle(hcap, c_hp.hp_port);
2880 if (saa_handle == NULL) {
2881 retval = IBT_HCA_PORT_NOT_ACTIVE;
2882 goto get_alt_path_done;
2883 }
2884
2924 &c_hp)) {
2925 IBTF_DPRINTF_L3(cmlog,
2926 "ibt_get_alt_path: PathRec obtained"
2927 " is similar to Prim Path, ignore "
2928 "this record");
2929 continue;
2930 }
2931 }
2932
2933 if (new_sgid.gid_guid == 0) {
2934 retval = ibcm_update_cep_info(pr_resp, NULL,
2935 &c_hp, &api_p->ap_alt_cep_path);
2936 } else {
2937 retval = ibcm_update_cep_info(pr_resp, NULL,
2938 &n_hp, &api_p->ap_alt_cep_path);
2939 }
2940 if (retval != IBT_SUCCESS)
2941 continue;
2942
2943 /* Update some leftovers */
2944 api_p->ap_alt_pkt_lt = pr_resp->PacketLifeTime;
2945
2946 rec_found = 1;
2947 break;
2948 }
2949 kmem_free(results_p, length);
2950 }
2951
2952 if (rec_found == 0) {
2953 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Alternate Path cannot"
2954 " be established");
2955 retval = IBT_PATH_RECORDS_NOT_FOUND;
2956 } else
2957 retval = IBT_SUCCESS;
2958
2959 get_alt_path_done:
2960 if ((snum) && (sgids_p))
2961 kmem_free(sgids_p, snum * sizeof (ib_gid_t));
2962
2963 if ((dnum) && (dgids_p))
2964 kmem_free(dgids_p, dnum * sizeof (ib_gid_t));
2965
2981 ibt_path_info_t *paths;
2982 ibt_path_ip_src_t *src_ip_p;
2983 uint8_t *num_paths_p;
2984 ibt_ip_path_handler_t func;
2985 void *arg;
2986 ibt_path_flags_t flags;
2987 ibt_clnt_hdl_t ibt_hdl;
2988 kmutex_t ip_lock;
2989 kcondvar_t ip_cv;
2990 boolean_t ip_done;
2991 ibt_status_t retval;
2992 uint_t len;
2993 } ibcm_ip_path_tqargs_t;
2994
2995 /* Holds destination information needed to fill in ibt_path_info_t. */
2996 typedef struct ibcm_ip_dinfo_s {
2997 uint8_t num_dest;
2998 ib_gid_t d_gid[1];
2999 } ibcm_ip_dinfo_t;
3000
3001 /* Prototype Declarations. */
3002 static void ibcm_process_get_ip_paths(void *tq_arg);
3003 static ibt_status_t ibcm_get_ip_spr(ibcm_ip_path_tqargs_t *,
3004 ibtl_cm_port_list_t *, ibcm_ip_dinfo_t *, uint8_t *, ibt_path_info_t *);
3005 static ibt_status_t ibcm_get_ip_mpr(ibcm_ip_path_tqargs_t *,
3006 ibtl_cm_port_list_t *, ibcm_ip_dinfo_t *dinfo,
3007 uint8_t *, ibt_path_info_t *);
3008
3009 /*
3010 * Perform SA Access to retrieve Path Records.
3011 */
3012 static ibt_status_t
3013 ibcm_saa_ip_pr(ibcm_ip_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl,
3014 ibcm_ip_dinfo_t *dinfo, uint8_t *max_count)
3015 {
3016 uint8_t num_path = *max_count;
3017 uint8_t rec_found = 0;
3018 ibt_status_t retval = IBT_SUCCESS;
3019 uint8_t i, j;
3020
3385 mpr_req = kmem_zalloc(template_len, KM_SLEEP);
3386
3387 ASSERT(mpr_req != NULL);
3388
3389 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
3390 sizeof (sa_multipath_record_t));
3391
3392 /* Get the starting pointer where GIDs are stored. */
3393 gid_s_ptr = gid_ptr;
3394
3395 /* SGID */
3396 for (i = 0; i < sgid_cnt; i++) {
3397 *gid_ptr = sl[i].p_sgid;
3398
3399 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: SGID[%d] = %llX:%llX",
3400 i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
3401
3402 gid_ptr++;
3403 }
3404
3405 mpr_req->SGIDCount = sgid_cnt;
3406 c_mask = SA_MPR_COMPMASK_SGIDCOUNT;
3407
3408 /* DGIDs */
3409 for (i = 0; i < dgid_cnt; i++) {
3410 *gid_ptr = dinfo->d_gid[i];
3411
3412 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: DGID[%d] = "
3413 "%llX:%llX", i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
3414 gid_ptr++;
3415 }
3416
3417 mpr_req->DGIDCount = dgid_cnt;
3418 c_mask |= SA_MPR_COMPMASK_DGIDCOUNT;
3419
3420 /* Is Flow Label Specified. */
3421 if (attrp->ipa_flow) {
3422 mpr_req->FlowLabel = attrp->ipa_flow;
3423 c_mask |= SA_MPR_COMPMASK_FLOWLABEL;
3424 }
3492 /* Is MTU specified. */
3493 if (attrp->ipa_mtu.r_mtu) {
3494 mpr_req->Mtu = attrp->ipa_mtu.r_mtu;
3495 mpr_req->MtuSelector = attrp->ipa_mtu.r_selector;
3496
3497 c_mask |= SA_MPR_COMPMASK_MTU |
3498 SA_MPR_COMPMASK_MTUSELECTOR;
3499 }
3500
3501 /* We always get REVERSIBLE paths. */
3502 mpr_req->Reversible = 1;
3503 c_mask |= SA_MPR_COMPMASK_REVERSIBLE;
3504
3505 if (p_arg->flags & IBT_PATH_AVAIL) {
3506 mpr_req->IndependenceSelector = 1;
3507 c_mask |= SA_MPR_COMPMASK_INDEPSEL;
3508 }
3509
3510 /* we will not specify how many records we want. */
3511
3512 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: CMask: %llX Pkey: %X",
3513 c_mask, mpr_req->P_Key);
3514
3515 /* Contact SA Access to retrieve Path Records. */
3516 access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID;
3517 access_args.sq_access_type = IBMF_SAA_RETRIEVE;
3518 access_args.sq_component_mask = c_mask;
3519 access_args.sq_template = mpr_req;
3520 access_args.sq_template_length = sizeof (sa_multipath_record_t);
3521 access_args.sq_callback = NULL;
3522 access_args.sq_callback_arg = NULL;
3523
3524 retval = ibcm_contact_sa_access(sl->p_saa_hdl, &access_args, &length,
3525 &results_p);
3526 if (retval != IBT_SUCCESS) {
3527 *num_path = 0; /* Update the return count. */
3528 kmem_free(mpr_req, template_len);
3529 return (retval);
3530 }
3531
3796 if ((retval != IBT_SUCCESS) &&
3797 (retval != IBT_GIDS_NOT_FOUND)) {
3798 IBTF_DPRINTF_L2(cmlog,
3799 "ibcm_process_get_ip_paths: "
3800 "Invalid DGIDs specified w/ APM Flag");
3801 goto ippath_error2;
3802 }
3803 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths: "
3804 "Found %d Comp DGID", dnum);
3805
3806 if (dnum) {
3807 dinfo->d_gid[i] = d_gids_p[0];
3808 i++;
3809 }
3810 }
3811 }
3812
3813 /* "i" will get us num_dest count. */
3814 dinfo->num_dest = i;
3815
3816 /*
3817 * IBTF allocates memory for path_info & src_ip in case of
3818 * Async Get IP Paths
3819 */
3820 if (p_arg->func) { /* Do these only for Async Get Paths */
3821 p_arg->paths = kmem_zalloc(sizeof (ibt_path_info_t) * max_paths,
3822 KM_SLEEP);
3823 if (p_arg->src_ip_p == NULL)
3824 p_arg->src_ip_p = kmem_zalloc(
3825 sizeof (ibt_path_ip_src_t) * max_paths, KM_SLEEP);
3826 }
3827
3828 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths: HCA (%llX, %d)",
3829 sl->p_hca_guid, sl->p_port_num);
3830
3831 hcap = ibcm_find_hca_entry(sl->p_hca_guid);
3832 if (hcap == NULL) {
3833 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
3834 "NO HCA found");
3835 retval = IBT_HCA_BUSY_DETACHING;
3836 goto ippath_error2;
3837 }
3838
3839 /* Get SA Access Handle. */
3840 for (i = 0; i < sl->p_count; i++) {
3841 if (i == 0) {
3842 /* Validate whether this HCA supports APM */
3843 if ((p_arg->flags & IBT_PATH_APM) &&
3844 (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG))) {
3845 IBTF_DPRINTF_L2(cmlog,
3846 "ibcm_process_get_ip_paths: HCA (%llX): "
3847 "APM NOT SUPPORTED", sl[i].p_hca_guid);
3848 retval = IBT_APM_NOT_SUPPORTED;
3849 goto ippath_error3;
3850 }
3851 }
3852
3853 saa_handle = ibcm_get_saa_handle(hcap, sl[i].p_port_num);
3854 if (saa_handle == NULL) {
3855 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
3856 "SAA HDL NULL, HCA (%llX:%d) NOT ACTIVE",
3857 sl[i].p_hca_guid, sl[i].p_port_num);
3858 retval = IBT_HCA_PORT_NOT_ACTIVE;
3859 goto ippath_error3;
3860 }
3861 sl[i].p_saa_hdl = saa_handle;
3862 }
3863
3864 /* Get Path Records. */
3865 retval = ibcm_saa_ip_pr(p_arg, sl, dinfo, &num_path);
3866
3867 ippath_error3:
3868 ibcm_dec_hca_acc_cnt(hcap);
3869
3870 ippath_error2:
3871 if (dinfo && len)
3872 kmem_free(dinfo, len);
3873
3874 ippath_error1:
3875 if (sl)
3876 ibtl_cm_free_active_plist(sl);
3877
3878 ippath_error:
3879 if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA))
3880 num_path = 0;
3881
3882 if (p_arg->num_paths_p != NULL)
3883 *p_arg->num_paths_p = num_path;
3884
3885 if (p_arg->func) { /* Do these only for Async Get Paths */
3886 ibt_path_info_t *tmp_path_p;
3887 ibt_path_ip_src_t *tmp_src_ip_p;
3888
3889 p_arg->retval = retval;
3890
3891 if (retval == IBT_INSUFF_DATA) {
3892 /*
3893 * We allocated earlier memory based on "max_paths",
3894 * but we got lesser path-records, so re-adjust that
3895 * buffer so that caller can free the correct memory.
3896 */
3897 tmp_path_p = kmem_alloc(
3898 sizeof (ibt_path_info_t) * num_path, KM_SLEEP);
3899
3900 bcopy(p_arg->paths, tmp_path_p,
3901 num_path * sizeof (ibt_path_info_t));
3902
3903 kmem_free(p_arg->paths,
3904 sizeof (ibt_path_info_t) * max_paths);
3905
3906 tmp_src_ip_p = kmem_alloc(
3907 sizeof (ibt_path_ip_src_t) * num_path, KM_SLEEP);
3908
3909 bcopy(p_arg->src_ip_p, tmp_src_ip_p,
4073 ibt_path_ip_src_t *src_ip_p, ibt_ip_path_handler_t func, void *arg)
4074 {
4075 ibcm_ip_path_tqargs_t *path_tq;
4076 int sleep_flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
4077 uint_t len, ret;
4078 ibt_status_t retval;
4079
4080 retval = ibcm_val_ipattr(attrp, flags);
4081 if (retval != IBT_SUCCESS)
4082 return (retval);
4083
4084 len = (attrp->ipa_ndst * sizeof (ibt_ip_addr_t)) +
4085 sizeof (ibcm_ip_path_tqargs_t);
4086 path_tq = kmem_zalloc(len, sleep_flag);
4087 if (path_tq == NULL) {
4088 IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_path: "
4089 "Unable to allocate memory for local usage.");
4090 return (IBT_INSUFF_KERNEL_RESOURCE);
4091 }
4092
4093 bcopy(attrp, &path_tq->attr, sizeof (ibt_ip_path_attr_t));
4094
4095 path_tq->attr.ipa_dst_ip = (ibt_ip_addr_t *)(((uchar_t *)path_tq) +
4096 sizeof (ibcm_ip_path_tqargs_t));
4097 bcopy(attrp->ipa_dst_ip, path_tq->attr.ipa_dst_ip,
4098 sizeof (ibt_ip_addr_t) * attrp->ipa_ndst);
4099
4100 /* Ignore IBT_PATH_AVAIL flag, if only one path is requested. */
4101 if ((flags & IBT_PATH_AVAIL) && (attrp->ipa_max_paths == 1)) {
4102 flags &= ~IBT_PATH_AVAIL;
4103
4104 IBTF_DPRINTF_L4(cmlog, "ibcm_get_ip_path: Ignoring "
4105 "IBT_PATH_AVAIL flag, as only ONE path info is requested.");
4106 }
4107
4108 path_tq->flags = flags;
4109 path_tq->ibt_hdl = ibt_hdl;
4110 path_tq->paths = paths;
4111 path_tq->src_ip_p = src_ip_p;
4112 path_tq->num_paths_p = num_path_p;
4113 path_tq->func = func;
4114 path_tq->arg = arg;
4115 path_tq->len = len;
4116 path_tq->ip_done = B_FALSE;
4117 if (func == NULL) { /* Blocking */
4118 mutex_init(&path_tq->ip_lock, NULL, MUTEX_DEFAULT, NULL);
4119 cv_init(&path_tq->ip_cv, NULL, CV_DRIVER, NULL);
4120 }
4121
4122 sleep_flag = ((func == NULL) ? TQ_SLEEP : TQ_NOSLEEP);
4123 ret = taskq_dispatch(ibcm_taskq, ibcm_process_get_ip_paths, path_tq,
4124 sleep_flag);
4125 if (ret == 0) {
4126 IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_path: Failed to dispatch "
4127 "the TaskQ");
4128 if (func == NULL) { /* Blocking */
4129 cv_destroy(&path_tq->ip_cv);
4130 mutex_destroy(&path_tq->ip_lock);
4131 }
4132 kmem_free(path_tq, len);
4133 retval = IBT_INSUFF_KERNEL_RESOURCE;
4134 } else {
4135 if (func != NULL) { /* Non-Blocking */
4136 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_path: NonBlocking");
4137 retval = IBT_SUCCESS;
4138 } else { /* Blocking */
4139 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_path: Blocking");
4140 mutex_enter(&path_tq->ip_lock);
4141 while (path_tq->ip_done != B_TRUE)
4383 */
4384 }
4385
4386 get_ip_alt_proceed:
4387 if (new_sgid.gid_guid != 0) {
4388 retval = ibtl_cm_get_hca_port(new_sgid, 0, &n_hp);
4389 if (retval != IBT_SUCCESS) {
4390 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: "
4391 "Get HCA Port Failed: %d", retval);
4392 goto get_ip_alt_path_done;
4393 }
4394 }
4395
4396 /* Calculate the size for multi-path records template */
4397 template_len = (2 * sizeof (ib_gid_t)) + sizeof (sa_multipath_record_t);
4398
4399 mpr_req = kmem_zalloc(template_len, KM_SLEEP);
4400
4401 ASSERT(mpr_req != NULL);
4402
4403 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
4404 sizeof (sa_multipath_record_t));
4405
4406 /* SGID */
4407 if (new_sgid.gid_guid == 0)
4408 *gid_ptr = cur_sgid;
4409 else
4410 *gid_ptr = new_sgid;
4411
4412 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Get Path Between "
4413 " SGID : %llX:%llX", gid_ptr->gid_prefix, gid_ptr->gid_guid);
4414
4415 gid_ptr++;
4416
4417 /* DGID */
4418 if (new_dgid.gid_guid == 0)
4419 *gid_ptr = cur_dgid;
4420 else
4421 *gid_ptr = new_dgid;
4422
4497 }
4498 }
4499
4500 /* Alt PathMTU can be GT or EQU to current channel's Pri PathMTU */
4501
4502 /* P_Key must be same as that of primary path */
4503 retval = ibt_index2pkey_byguid(c_hp.hp_hca_guid, c_hp.hp_port,
4504 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix,
4505 &mpr_req->P_Key);
4506 if (retval != IBT_SUCCESS) {
4507 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: PKeyIdx2Pkey "
4508 "Failed: %d", retval);
4509 goto get_ip_alt_path_done;
4510 }
4511 c_mask |= SA_MPR_COMPMASK_PKEY;
4512
4513 mpr_req->Reversible = 1; /* We always get REVERSIBLE paths. */
4514 mpr_req->IndependenceSelector = 1;
4515 c_mask |= SA_MPR_COMPMASK_REVERSIBLE | SA_MPR_COMPMASK_INDEPSEL;
4516
4517 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: CMask: 0x%llX", c_mask);
4518
4519 /* NOTE: We will **NOT** specify how many records we want. */
4520
4521 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Primary: MTU %d, PKey[%d]="
4522 "0x%X\n\tSGID = %llX:%llX, DGID = %llX:%llX", prim_mtu,
4523 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, mpr_req->P_Key,
4524 cur_sgid.gid_prefix, cur_sgid.gid_guid, cur_dgid.gid_prefix,
4525 cur_dgid.gid_guid);
4526
4527 /* Get SA Access Handle. */
4528 if (new_sgid.gid_guid != 0)
4529 saa_handle = ibcm_get_saa_handle(hcap, n_hp.hp_port);
4530 else
4531 saa_handle = ibcm_get_saa_handle(hcap, c_hp.hp_port);
4532 if (saa_handle == NULL) {
4533 retval = IBT_HCA_PORT_NOT_ACTIVE;
4534 goto get_ip_alt_path_done;
4535 }
4536
4576 &c_hp)) {
4577 IBTF_DPRINTF_L3(cmlog,
4578 "ibt_get_ip_alt_path: PathRec "
4579 "obtained is similar to Prim Path, "
4580 "ignore this record");
4581 continue;
4582 }
4583 }
4584
4585 if (new_sgid.gid_guid == 0) {
4586 retval = ibcm_update_cep_info(pr_resp, NULL,
4587 &c_hp, &api_p->ap_alt_cep_path);
4588 } else {
4589 retval = ibcm_update_cep_info(pr_resp, NULL,
4590 &n_hp, &api_p->ap_alt_cep_path);
4591 }
4592 if (retval != IBT_SUCCESS)
4593 continue;
4594
4595 /* Update some leftovers */
4596 api_p->ap_alt_pkt_lt = pr_resp->PacketLifeTime;
4597
4598 rec_found = 1;
4599 break;
4600 }
4601 kmem_free(results_p, length);
4602 }
4603
4604 if (rec_found == 0) {
4605 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: AltPath cannot"
4606 " be established");
4607 retval = IBT_PATH_RECORDS_NOT_FOUND;
4608 } else
4609 retval = IBT_SUCCESS;
4610
4611 get_ip_alt_path_done:
4612 if ((snum) && (sgids_p))
4613 kmem_free(sgids_p, snum * sizeof (ib_gid_t));
4614
4615 if ((dnum) && (dgids_p))
4616 kmem_free(dgids_p, dnum * sizeof (ib_gid_t));
4617
4618 ibcm_dec_hca_acc_cnt(hcap);
4619
4620 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Done (status %d)", retval);
4621
4622 return (retval);
4623 }
|