Print this page
8368 remove warlock leftovers from usr/src/uts


  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 }