Print this page
    
8368 remove warlock leftovers from usr/src/uts
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_path.c
          +++ new/usr/src/uts/common/io/ib/mgt/ibcm/ibcm_path.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright (c) 2016 by Delphix. All rights reserved.
  24   24   */
  25   25  
  26   26  #include <sys/ib/mgt/ibcm/ibcm_impl.h>
  27   27  #include <sys/ib/mgt/ibcm/ibcm_arp.h>
  28   28  
  29   29  /*
  30   30   * ibcm_path.c
  31   31   *
  32   32   * ibt_get_paths() implement the Path Informations related functionality.
  33   33   */
  34   34  
  35   35  /* ibcm_saa_service_rec() fills in ServiceID and DGID. */
  36   36  typedef struct ibcm_dest_s {
  37   37          ib_gid_t        d_gid;
  38   38          ib_svc_id_t     d_sid;
  39   39          ibt_srv_data_t  d_sdata;
  40   40          ib_pkey_t       d_pkey;
  
    | 
      ↓ open down ↓ | 
    40 lines elided | 
    
      ↑ open up ↑ | 
  
  41   41          uint_t          d_tag;  /* 0 = Unicast, 1 = Multicast */
  42   42  } ibcm_dest_t;
  43   43  
  44   44  /* Holds Destination information needed to fill in ibt_path_info_t. */
  45   45  typedef struct ibcm_dinfo_s {
  46   46          uint8_t         num_dest;
  47   47          ib_pkey_t       p_key;
  48   48          ibcm_dest_t     dest[1];
  49   49  } ibcm_dinfo_t;
  50   50  
  51      -_NOTE(SCHEME_PROTECTS_DATA("Temporary path storage", ibcm_dinfo_s))
  52      -_NOTE(READ_ONLY_DATA(ibt_path_attr_s))
  53      -
  54   51  typedef struct ibcm_path_tqargs_s {
  55   52          ibt_path_attr_t         attr;
  56   53          ibt_path_info_t         *paths;
  57   54          uint8_t                 *num_paths_p;
  58   55          ibt_path_handler_t      func;
  59   56          void                    *arg;
  60   57          ibt_path_flags_t        flags;
  61   58          uint8_t                 max_paths;
  62   59  } ibcm_path_tqargs_t;
  63   60  
  64   61  
  65   62  /* Prototype Declarations. */
  66   63  static ibt_status_t ibcm_saa_path_rec(ibcm_path_tqargs_t *,
  67   64      ibtl_cm_port_list_t *, ibcm_dinfo_t *, uint8_t *);
  68   65  
  69   66  static ibt_status_t ibcm_update_cep_info(sa_path_record_t *,
  70   67      ibtl_cm_port_list_t *, ibtl_cm_hca_port_t *, ibt_cep_path_t *);
  71   68  
  72   69  static ibt_status_t ibcm_saa_service_rec(ibcm_path_tqargs_t *,
  73   70      ibtl_cm_port_list_t *, ibcm_dinfo_t *);
  74   71  
  75   72  static ibt_status_t ibcm_get_single_pathrec(ibcm_path_tqargs_t *,
  76   73      ibtl_cm_port_list_t *, ibcm_dinfo_t *, uint8_t,
  77   74      uint8_t *, ibt_path_info_t *);
  78   75  
  79   76  static ibt_status_t ibcm_get_multi_pathrec(ibcm_path_tqargs_t *,
  80   77      ibtl_cm_port_list_t *, ibcm_dinfo_t *dinfo,
  81   78      uint8_t *, ibt_path_info_t *);
  82   79  
  83   80  static ibt_status_t ibcm_validate_path_attributes(ibt_path_attr_t *attrp,
  84   81      ibt_path_flags_t flags, uint8_t max_paths);
  85   82  
  86   83  static ibt_status_t ibcm_handle_get_path(ibt_path_attr_t *attrp,
  87   84      ibt_path_flags_t flags, uint8_t max_paths, ibt_path_info_t *paths,
  88   85      uint8_t *num_path_p, ibt_path_handler_t func, void  *arg);
  89   86  
  90   87  static void ibcm_process_async_get_paths(void *tq_arg);
  91   88  
  92   89  static ibt_status_t ibcm_process_get_paths(void *tq_arg);
  93   90  
  94   91  static ibt_status_t ibcm_get_comp_pgids(ib_gid_t, ib_gid_t, ib_guid_t,
  95   92      ib_gid_t **, uint_t *);
  96   93  
  97   94  /*
  98   95   * Function:
  99   96   *      ibt_aget_paths
 100   97   * Input:
 101   98   *      ibt_hdl         The handle returned to the client by the IBTF from an
 102   99   *                      ibt_attach() call. Can be used by the IBTF Policy module
 103  100   *                      and CM in the determination of the "best" path to the
 104  101   *                      specified destination for this class of driver.
 105  102   *      flags           Path flags.
 106  103   *      attrp           Points to an ibt_path_attr_t struct that contains
 107  104   *                      required and optional attributes.
 108  105   *      func            A pointer to an ibt_path_handler_t function to call
 109  106   *                      when ibt_aget_paths() completes.
 110  107   *      arg             The argument to 'func'.
 111  108   * Returns:
 112  109   *      IBT_SUCCESS on early validation of attributes else appropriate error.
 113  110   * Description:
 114  111   *      Finds the best path to a specified destination or service
 115  112   *      asynchronously (as determined by the IBTL) that satisfies the
 116  113   *      requirements specified in an ibt_path_attr_t struct.
 117  114   *      ibt_aget_paths() is a Non-Blocking version of ibt_get_paths().
 118  115   */
 119  116  ibt_status_t
 120  117  ibt_aget_paths(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags,
 121  118      ibt_path_attr_t *attrp, uint8_t max_paths, ibt_path_handler_t func,
 122  119      void  *arg)
 123  120  {
 124  121          IBTF_DPRINTF_L3(cmlog, "ibt_aget_paths(%p(%s), 0x%X, %p, %d, %p)",
 125  122              ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), flags, attrp, max_paths,
 126  123              func);
 127  124  
 128  125          if (func == NULL) {
 129  126                  IBTF_DPRINTF_L2(cmlog, "ibt_aget_paths: Function Pointer is "
 130  127                      "NULL - ERROR ");
 131  128                  return (IBT_INVALID_PARAM);
 132  129          }
 133  130  
 134  131          /* Memory for path info will be allocated in ibcm_process_get_paths() */
 135  132          return (ibcm_handle_get_path(attrp, flags, max_paths, NULL, NULL,
 136  133              func, arg));
 137  134  }
 138  135  
 139  136  
 140  137  /*
 141  138   * ibt_get_paths() cache consists of one or more of:
 142  139   *
 143  140   *      ib_gid_t dgid (attrp->pa_dgids[0])
 144  141   *      ibt_path_attr_t attr
 145  142   *      ibt_path_flags_t flags
 146  143   *      ibt_path_info_t path
 147  144   *
 148  145   * If the first 3 match, max_paths is 1, sname is NULL, and sid is 0,
 149  146   * then the path is returned immediately.
 150  147   *
 151  148   * Note that a compare of "attr" is non-trivial.  Only accept ones
 152  149   * that memcmp() succeeds, i.e., basically assume a bzero was done.
 153  150   *
 154  151   * Cache must be invalidated if PORT_DOWN event or GID_UNAVAIL occurs.
 155  152   * Cache must be freed as part of _fini.
 156  153   */
 157  154  
 158  155  #define IBCM_PATH_CACHE_SIZE    16      /* keep small for linear search */
 159  156  #define IBCM_PATH_CACHE_TIMEOUT 60      /* purge cache after 60 seconds */
 160  157  
 161  158  typedef struct ibcm_path_cache_s {
 162  159          ib_gid_t                dgid;
 163  160          ibt_path_attr_t         attr;
 164  161          ibt_path_flags_t        flags;
 165  162          ibt_path_info_t         path;
 166  163  } ibcm_path_cache_t;
 167  164  
 168  165  kmutex_t ibcm_path_cache_mutex;
 169  166  int ibcm_path_cache_invalidate; /* invalidate cache on next ibt_get_paths */
 170  167  clock_t ibcm_path_cache_timeout = IBCM_PATH_CACHE_TIMEOUT; /* tunable */
 171  168  timeout_id_t ibcm_path_cache_timeout_id;
 172  169  int ibcm_path_cache_size_init = IBCM_PATH_CACHE_SIZE;   /* tunable */
 173  170  int ibcm_path_cache_size;
 174  171  ibcm_path_cache_t *ibcm_path_cachep;
 175  172  
 176  173  /* tunable, set to 1 to not allow link-local address */
 177  174  int     ibcm_ip6_linklocal_addr_ok = 0;
 178  175  
 179  176  struct ibcm_path_cache_stat_s {
 180  177          int hits;
 181  178          int misses;
 182  179          int adds;
 183  180          int already_in_cache;
 184  181          int bad_path_for_cache;
 185  182          int purges;
 186  183          int timeouts;
 187  184  } ibcm_path_cache_stats;
 188  185  
 189  186  /*ARGSUSED*/
 190  187  static void
 191  188  ibcm_path_cache_timeout_cb(void *arg)
 192  189  {
 193  190          clock_t timeout_in_hz;
 194  191  
 195  192          timeout_in_hz = drv_usectohz(ibcm_path_cache_timeout * 1000000);
 196  193          mutex_enter(&ibcm_path_cache_mutex);
 197  194          ibcm_path_cache_invalidate = 1; /* invalidate cache on next check */
 198  195          if (ibcm_path_cache_timeout_id)
 199  196                  ibcm_path_cache_timeout_id = timeout(ibcm_path_cache_timeout_cb,
 200  197                      NULL, timeout_in_hz);
 201  198          /* else we're in _fini */
 202  199          mutex_exit(&ibcm_path_cache_mutex);
 203  200  }
 204  201  
 205  202  void
 206  203  ibcm_path_cache_init(void)
 207  204  {
 208  205          clock_t timeout_in_hz;
 209  206          int cache_size = ibcm_path_cache_size_init;
 210  207          ibcm_path_cache_t *path_cachep;
 211  208  
 212  209          timeout_in_hz = drv_usectohz(ibcm_path_cache_timeout * 1000000);
 213  210          path_cachep = kmem_zalloc(cache_size * sizeof (*path_cachep), KM_SLEEP);
 214  211          mutex_init(&ibcm_path_cache_mutex, NULL, MUTEX_DEFAULT, NULL);
 215  212          mutex_enter(&ibcm_path_cache_mutex);
 216  213          ibcm_path_cache_size = cache_size;
 217  214          ibcm_path_cachep = path_cachep;
 218  215          ibcm_path_cache_timeout_id = timeout(ibcm_path_cache_timeout_cb,
 219  216              NULL, timeout_in_hz);
 220  217          mutex_exit(&ibcm_path_cache_mutex);
 221  218  }
 222  219  
 223  220  void
 224  221  ibcm_path_cache_fini(void)
 225  222  {
 226  223          timeout_id_t tmp_timeout_id;
 227  224          int cache_size;
 228  225          ibcm_path_cache_t *path_cachep;
 229  226  
 230  227          mutex_enter(&ibcm_path_cache_mutex);
 231  228          if (ibcm_path_cache_timeout_id) {
 232  229                  tmp_timeout_id = ibcm_path_cache_timeout_id;
 233  230                  ibcm_path_cache_timeout_id = 0; /* no more timeouts */
 234  231          }
 235  232          cache_size = ibcm_path_cache_size;
 236  233          path_cachep = ibcm_path_cachep;
 237  234          mutex_exit(&ibcm_path_cache_mutex);
 238  235          if (tmp_timeout_id)
 239  236                  (void) untimeout(tmp_timeout_id);
 240  237          mutex_destroy(&ibcm_path_cache_mutex);
 241  238          kmem_free(path_cachep, cache_size * sizeof (*path_cachep));
 242  239  }
 243  240  
 244  241  static ibcm_status_t
 245  242  ibcm_path_cache_check(ibt_path_flags_t flags, ibt_path_attr_t *attrp,
 246  243      uint8_t max_paths, ibt_path_info_t *path, uint8_t *num_paths_p)
 247  244  {
 248  245          int i;
 249  246          ib_gid_t dgid;
 250  247          ibcm_path_cache_t *path_cachep;
 251  248  
 252  249          if (max_paths != 1 || attrp->pa_num_dgids != 1 ||
 253  250              attrp->pa_sname != NULL || attrp->pa_sid != 0) {
 254  251                  mutex_enter(&ibcm_path_cache_mutex);
 255  252                  ibcm_path_cache_stats.bad_path_for_cache++;
 256  253                  mutex_exit(&ibcm_path_cache_mutex);
 257  254                  return (IBCM_FAILURE);
 258  255          }
 259  256  
 260  257          dgid = attrp->pa_dgids[0];
 261  258          if ((dgid.gid_guid | dgid.gid_prefix) == 0ULL)
 262  259                  return (IBCM_FAILURE);
 263  260  
 264  261          mutex_enter(&ibcm_path_cache_mutex);
 265  262          if (ibcm_path_cache_invalidate) {       /* invalidate all entries */
 266  263                  ibcm_path_cache_stats.timeouts++;
 267  264                  ibcm_path_cache_invalidate = 0;
 268  265                  path_cachep = ibcm_path_cachep;
 269  266                  for (i = 0; i < ibcm_path_cache_size; i++, path_cachep++) {
 270  267                          path_cachep->dgid.gid_guid = 0ULL;
 271  268                          path_cachep->dgid.gid_prefix = 0ULL;
 272  269                  }
 273  270                  mutex_exit(&ibcm_path_cache_mutex);
 274  271                  return (IBCM_FAILURE);
 275  272          }
 276  273  
 277  274          path_cachep = ibcm_path_cachep;
 278  275          for (i = 0; i < ibcm_path_cache_size; i++, path_cachep++) {
 279  276                  if (path_cachep->dgid.gid_guid == 0ULL)
 280  277                          break;  /* end of search, no more valid cache entries */
 281  278  
 282  279                  /* make pa_dgids pointers match, so we can use memcmp */
 283  280                  path_cachep->attr.pa_dgids = attrp->pa_dgids;
 284  281                  if (path_cachep->flags != flags ||
 285  282                      path_cachep->dgid.gid_guid != dgid.gid_guid ||
 286  283                      path_cachep->dgid.gid_prefix != dgid.gid_prefix ||
 287  284                      memcmp(&(path_cachep->attr), attrp, sizeof (*attrp)) != 0) {
 288  285                          /* make pa_dgids NULL again */
 289  286                          path_cachep->attr.pa_dgids = NULL;
 290  287                          continue;
 291  288                  }
 292  289                  /* else we have a match */
 293  290                  /* make pa_dgids NULL again */
 294  291                  path_cachep->attr.pa_dgids = NULL;
 295  292                  *path = path_cachep->path;      /* retval */
 296  293                  if (num_paths_p)
 297  294                          *num_paths_p = 1;       /* retval */
 298  295                  ibcm_path_cache_stats.hits++;
 299  296                  mutex_exit(&ibcm_path_cache_mutex);
 300  297                  return (IBCM_SUCCESS);
 301  298          }
 302  299          ibcm_path_cache_stats.misses++;
 303  300          mutex_exit(&ibcm_path_cache_mutex);
 304  301          return (IBCM_FAILURE);
 305  302  }
 306  303  
 307  304  static void
 308  305  ibcm_path_cache_add(ibt_path_flags_t flags,
 309  306      ibt_path_attr_t *attrp, uint8_t max_paths, ibt_path_info_t *path)
 310  307  {
 311  308          int i;
 312  309          ib_gid_t dgid;
 313  310          ibcm_path_cache_t *path_cachep;
 314  311  
 315  312          if (max_paths != 1 || attrp->pa_num_dgids != 1 ||
 316  313              attrp->pa_sname != NULL || attrp->pa_sid != 0)
 317  314                  return;
 318  315  
 319  316          dgid = attrp->pa_dgids[0];
 320  317          if ((dgid.gid_guid | dgid.gid_prefix) == 0ULL)
 321  318                  return;
 322  319  
 323  320          mutex_enter(&ibcm_path_cache_mutex);
 324  321          path_cachep = ibcm_path_cachep;
 325  322          for (i = 0; i < ibcm_path_cache_size; i++, path_cachep++) {
 326  323                  path_cachep->attr.pa_dgids = attrp->pa_dgids;
 327  324                  if (path_cachep->flags == flags &&
 328  325                      path_cachep->dgid.gid_guid == dgid.gid_guid &&
 329  326                      path_cachep->dgid.gid_prefix == dgid.gid_prefix &&
 330  327                      memcmp(&(path_cachep->attr), attrp, sizeof (*attrp)) == 0) {
 331  328                          /* already in cache */
 332  329                          ibcm_path_cache_stats.already_in_cache++;
 333  330                          path_cachep->attr.pa_dgids = NULL;
 334  331                          mutex_exit(&ibcm_path_cache_mutex);
 335  332                          return;
 336  333                  }
 337  334                  if (path_cachep->dgid.gid_guid != 0ULL) {
 338  335                          path_cachep->attr.pa_dgids = NULL;
 339  336                          continue;
 340  337                  }
 341  338                  /* else the rest of the entries are free, so use this one */
 342  339                  ibcm_path_cache_stats.adds++;
 343  340                  path_cachep->flags = flags;
 344  341                  path_cachep->attr = *attrp;
 345  342                  path_cachep->attr.pa_dgids = NULL;
 346  343                  path_cachep->dgid = attrp->pa_dgids[0];
 347  344                  path_cachep->path = *path;
 348  345                  mutex_exit(&ibcm_path_cache_mutex);
 349  346                  return;
 350  347          }
 351  348          mutex_exit(&ibcm_path_cache_mutex);
 352  349  }
 353  350  
 354  351  void
 355  352  ibcm_path_cache_purge(void)
 356  353  {
 357  354          mutex_enter(&ibcm_path_cache_mutex);
 358  355          ibcm_path_cache_invalidate = 1; /* invalidate cache on next check */
 359  356          ibcm_path_cache_stats.purges++;
 360  357          mutex_exit(&ibcm_path_cache_mutex);
 361  358  }
 362  359  
 363  360  /*
 364  361   * Function:
 365  362   *      ibt_get_paths
 366  363   * Input:
 367  364   *      ibt_hdl         The handle returned to the client by the IBTF from an
 368  365   *                      ibt_attach() call. Can be used by the IBTF Policy module
 369  366   *                      and CM in the determination of the "best" path to the
 370  367   *                      specified destination for this class of driver.
 371  368   *      flags           Path flags.
 372  369   *      attrp           Points to an ibt_path_attr_t struct that contains
 373  370   *                      required and optional attributes.
 374  371   *      max_paths       The size of the "paths" array argument. Also, this
 375  372   *                      is the limit on the number of paths returned.
 376  373   *                      max_paths indicates the number of requested paths to
 377  374   *                      the specified destination(s).
 378  375   * Output:
 379  376   *      paths           An array of ibt_path_info_t structs filled in by
 380  377   *                      ibt_get_paths() as output parameters. Upon return,
 381  378   *                      array elements with non-NULL HCA GUIDs are valid.
 382  379   *      num_paths_p     If non-NULL, return the actual number of paths found.
 383  380   * Returns:
 384  381   *      IBT_SUCCESS on Success else appropriate error.
 385  382   * Description:
 386  383   *      Finds the best path to a specified destination (as determined by the
 387  384   *      IBTL) that satisfies the requirements specified in an ibt_path_attr_t
 388  385   *      struct.
 389  386   *
 390  387   *      This routine can not be called from interrupt context.
 391  388   */
 392  389  ibt_status_t
 393  390  ibt_get_paths(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags,
 394  391      ibt_path_attr_t *attrp, uint8_t max_paths, ibt_path_info_t *paths,
 395  392      uint8_t *num_paths_p)
 396  393  {
 397  394          ibt_status_t    retval;
 398  395  
 399  396          ASSERT(paths != NULL);
 400  397  
 401  398          IBTF_DPRINTF_L3(cmlog, "ibt_get_paths(%p(%s), 0x%X, %p, %d)",
 402  399              ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), flags, attrp, max_paths);
 403  400  
 404  401          if (paths == NULL) {
 405  402                  IBTF_DPRINTF_L2(cmlog, "ibt_get_paths: Path Info Pointer is "
 406  403                      "NULL - ERROR ");
 407  404                  return (IBT_INVALID_PARAM);
 408  405          }
 409  406  
 410  407          if (num_paths_p != NULL)
 411  408                  *num_paths_p = 0;
 412  409  
 413  410          if (ibcm_path_cache_check(flags, attrp, max_paths, paths,
 414  411              num_paths_p) == IBCM_SUCCESS)
 415  412                  return (IBT_SUCCESS);
 416  413  
 417  414          retval = ibcm_handle_get_path(attrp, flags, max_paths, paths,
 418  415              num_paths_p, NULL, NULL);
 419  416  
 420  417          if (retval == IBT_SUCCESS)
 421  418                  ibcm_path_cache_add(flags, attrp, max_paths, paths);
 422  419          return (retval);
 423  420  }
 424  421  
 425  422  
 426  423  static ibt_status_t
 427  424  ibcm_handle_get_path(ibt_path_attr_t *attrp, ibt_path_flags_t flags,
 428  425      uint8_t max_paths, ibt_path_info_t *paths, uint8_t *num_path_p,
 429  426      ibt_path_handler_t func, void  *arg)
 430  427  {
 431  428          ibcm_path_tqargs_t      *path_tq;
 432  429          int             sleep_flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
 433  430          int             len;
 434  431          ibt_status_t    retval;
 435  432  
 436  433          retval = ibcm_validate_path_attributes(attrp, flags, max_paths);
 437  434          if (retval != IBT_SUCCESS)
 438  435                  return (retval);
 439  436  
  
    | 
      ↓ open down ↓ | 
    376 lines elided | 
    
      ↑ open up ↑ | 
  
 440  437          len = (attrp->pa_num_dgids * sizeof (ib_gid_t)) +
 441  438              sizeof (ibcm_path_tqargs_t);
 442  439  
 443  440          path_tq = kmem_alloc(len, sleep_flag);
 444  441          if (path_tq == NULL) {
 445  442                  IBTF_DPRINTF_L2(cmlog, "ibcm_handle_get_path: "
 446  443                      "Unable to allocate memory for local usage.");
 447  444                  return (IBT_INSUFF_KERNEL_RESOURCE);
 448  445          }
 449  446  
 450      -        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*path_tq))
 451      -
 452  447          bcopy(attrp, &path_tq->attr, sizeof (ibt_path_attr_t));
 453  448  
 454  449          if (attrp->pa_num_dgids) {
 455  450                  path_tq->attr.pa_dgids = (ib_gid_t *)(((uchar_t *)path_tq) +
 456  451                      sizeof (ibcm_path_tqargs_t));
 457  452  
 458  453                  bcopy(attrp->pa_dgids, path_tq->attr.pa_dgids,
 459  454                      sizeof (ib_gid_t) * attrp->pa_num_dgids);
 460  455          } else {
 461  456                  path_tq->attr.pa_dgids = NULL;
 462  457          }
 463  458  
 464  459          /* Ignore IBT_PATH_AVAIL flag, if only one path is requested. */
 465  460          if ((flags & IBT_PATH_AVAIL) && (max_paths == 1)) {
 466  461                  flags &= ~IBT_PATH_AVAIL;
 467  462  
 468  463                  IBTF_DPRINTF_L4(cmlog, "ibcm_handle_get_path: "
 469  464                      "Ignoring IBT_PATH_AVAIL flag, as only ONE path "
  
    | 
      ↓ open down ↓ | 
    8 lines elided | 
    
      ↑ open up ↑ | 
  
 470  465                      "information is requested.");
 471  466          }
 472  467  
 473  468          path_tq->flags = flags;
 474  469          path_tq->max_paths = max_paths;
 475  470          path_tq->paths = paths;
 476  471          path_tq->num_paths_p = num_path_p;
 477  472          path_tq->func = func;
 478  473          path_tq->arg = arg;
 479  474  
 480      -        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*path_tq))
 481      -
 482  475          if (func != NULL) {             /* Non-Blocking */
 483  476                  IBTF_DPRINTF_L3(cmlog, "ibcm_handle_get_path: Non Blocking");
 484  477                  if (taskq_dispatch(ibcm_taskq, ibcm_process_async_get_paths,
 485  478                      path_tq, TQ_NOSLEEP) == 0) {
 486  479                          IBTF_DPRINTF_L2(cmlog, "ibcm_handle_get_path: "
 487  480                              "Failed to dispatch the TaskQ");
 488  481                          kmem_free(path_tq, len);
 489  482                          return (IBT_INSUFF_KERNEL_RESOURCE);
 490  483                  } else
 491  484                          return (IBT_SUCCESS);
 492  485          } else {                /* Blocking */
 493  486                  IBTF_DPRINTF_L3(cmlog, "ibcm_handle_get_path: Blocking");
 494  487                  return (ibcm_process_get_paths(path_tq));
 495  488          }
 496  489  }
 497  490  
 498  491  
 499  492  static void
 500  493  ibcm_process_async_get_paths(void *tq_arg)
 501  494  {
 502  495          (void) ibcm_process_get_paths(tq_arg);
 503  496  }
 504  497  
 505  498  
 506  499  static ibt_status_t
 507  500  ibcm_validate_path_attributes(ibt_path_attr_t *attrp, ibt_path_flags_t flags,
 508  501      uint8_t max_paths)
 509  502  {
 510  503          uint_t                  i;
 511  504  
 512  505          IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: Inputs are: "
 513  506              "HCA (%llX, %d),\n\tSGID(%llX:%llX), SName=\"%s\",\n\tSID= %llX, "
 514  507              "Maxpath= %d, Flags= 0x%X, #Dgid= %d, SDFlag= 0x%llX",
 515  508              attrp->pa_hca_guid, attrp->pa_hca_port_num,
 516  509              attrp->pa_sgid.gid_prefix, attrp->pa_sgid.gid_guid,
 517  510              ((attrp->pa_sname != NULL) ? attrp->pa_sname : ""), attrp->pa_sid,
 518  511              max_paths, flags, attrp->pa_num_dgids, attrp->pa_sd_flags);
 519  512  
 520  513          /*
 521  514           * Validate Path Flags.
 522  515           * IBT_PATH_AVAIL & IBT_PATH_PERF are mutually exclusive.
 523  516           */
 524  517          if ((flags & IBT_PATH_AVAIL) && (flags & IBT_PATH_PERF)) {
 525  518                  IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: "
 526  519                      "Invalid Flags: 0x%X,\n\t AVAIL and PERF flags cannot "
 527  520                      "specified together.", flags);
 528  521                  return (IBT_INVALID_PARAM);
 529  522          }
 530  523  
 531  524          /* Validate number of records requested. */
 532  525          if ((flags & (IBT_PATH_AVAIL | IBT_PATH_PERF)) &&
 533  526              (max_paths > IBT_MAX_SPECIAL_PATHS)) {
 534  527                  IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: "
 535  528                      "Max records that can be requested is <%d> \n"
 536  529                      "when IBT_PATH_AVAIL or IBT_PATH_PERF flag is specified.",
 537  530                      IBT_MAX_SPECIAL_PATHS);
 538  531                  return (IBT_INVALID_PARAM);
 539  532          }
 540  533  
 541  534          /* Only 2 destinations can be specified w/ APM flag. */
 542  535          if ((flags & IBT_PATH_APM) && (attrp->pa_num_dgids > 2)) {
 543  536                  IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes:\n\t Max "
 544  537                      "number of DGIDs that can be specified w/APM flag is 2");
 545  538                  return (IBT_INVALID_PARAM);
 546  539          }
 547  540  
 548  541          /*
 549  542           * Max_paths of "0" is invalid.
 550  543           * w/ IBT_PATH_MULTI_SVC_DEST flag, max_paths must be greater than "1".
 551  544           */
 552  545          if ((max_paths == 0) ||
 553  546              ((flags & IBT_PATH_MULTI_SVC_DEST) && (max_paths < 2))) {
 554  547                  IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: "
 555  548                      "Invalid number of records requested:\n flags 0x%X, "
 556  549                      "max_paths %d", flags, max_paths);
 557  550                  return (IBT_INVALID_PARAM);
 558  551          }
 559  552  
 560  553          /*
 561  554           * If IBT_PATH_MULTI_SVC_DEST is set, then ServiceName and/or Service ID
 562  555           * must be specified and DGIDs SHOULD NOT be specified.
 563  556           */
 564  557          if ((flags & IBT_PATH_MULTI_SVC_DEST) && ((attrp->pa_num_dgids > 0) ||
 565  558              ((attrp->pa_sid == 0) && ((attrp->pa_sname == NULL) ||
 566  559              ((attrp->pa_sname != NULL) && (strlen(attrp->pa_sname) == 0)))))) {
 567  560                  IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: "
 568  561                      "Invalid Flags: 0x%X, IBT_PATH_MULTI_SVC_DEST flag set "
 569  562                      "but Service Name \n or Service ID NOT specified or DGIDs "
 570  563                      "are specified.", flags);
 571  564                  return (IBT_INVALID_PARAM);
 572  565          }
 573  566  
 574  567          /*
 575  568           * User need to specify the destination information, which can be
 576  569           * provided as one or more of the following.
 577  570           *      o ServiceName
 578  571           *      o ServiceID
 579  572           *      o Array of DGIDs w/Num of DGIDs, (max of 2)
 580  573           */
 581  574          if ((attrp->pa_sid == 0) && (attrp->pa_num_dgids == 0) &&
 582  575              ((attrp->pa_sname == NULL) || ((attrp->pa_sname != NULL) &&
 583  576              (strlen(attrp->pa_sname) == 0)))) {
 584  577                  /* Destination information not provided, bail out. */
 585  578                  IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: "
 586  579                      "Client's MUST supply DestInfo.");
 587  580                  return (IBT_INVALID_PARAM);
 588  581          }
 589  582  
 590  583          /* If DGIDs are provided, validate them. */
 591  584          if (attrp->pa_num_dgids > 0) {
 592  585                  if (attrp->pa_dgids == NULL) {
 593  586                          IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: "
 594  587                              "pa_dgids NULL, but pa_num_dgids : %d",
 595  588                              attrp->pa_num_dgids);
 596  589                          return (IBT_INVALID_PARAM);
 597  590                  }
 598  591  
 599  592                  /* Validate DGIDs */
 600  593                  for (i = 0; i < attrp->pa_num_dgids; i++) {
 601  594                          ib_gid_t        gid = attrp->pa_dgids[i];
 602  595  
 603  596                          IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: "
 604  597                              "DGID[%d] = %llX:%llX", i, gid.gid_prefix,
 605  598                              gid.gid_guid);
 606  599  
 607  600                          /* APM request for MultiCast destination is invalid. */
 608  601                          if ((gid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
 609  602                                  if (flags & IBT_PATH_APM) {
 610  603                                          IBTF_DPRINTF_L2(cmlog,
 611  604                                              "ibcm_validate_path_attributes: "
 612  605                                              "APM for MGIDs not supported.");
 613  606                                          return (IBT_INVALID_PARAM);
 614  607                                  }
 615  608                          } else if ((gid.gid_prefix == 0) ||
 616  609                              (gid.gid_guid == 0)) {
 617  610                                  IBTF_DPRINTF_L2(cmlog,
 618  611                                      "ibcm_validate_path_attributes: ERROR: "
 619  612                                      "Invalid DGIDs specified");
 620  613                                  return (IBT_INVALID_PARAM);
 621  614                          }
 622  615                  }
 623  616          }
 624  617  
 625  618          /* Check for valid Service Name length. */
 626  619          if ((attrp->pa_sname != NULL) &&
 627  620              (strlen(attrp->pa_sname) >= IB_SVC_NAME_LEN)) {
 628  621                  IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: "
 629  622                      "ServiceName too long");
 630  623                  return (IBT_INVALID_PARAM);
 631  624          }
 632  625  
 633  626          /* If P_Key is specified, check for invalid p_key's */
 634  627          if (flags & IBT_PATH_PKEY) {
 635  628                  /* Limited P_Key is NOT supported as of now!. */
 636  629                  if ((attrp->pa_pkey == IB_PKEY_INVALID_FULL) ||
 637  630                      (attrp->pa_pkey & 0x8000) == 0) {
 638  631                          IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: "
 639  632                              "Specified P_Key is invalid: 0x%X", attrp->pa_pkey);
 640  633                          return (IBT_INVALID_PARAM);
 641  634                  }
 642  635                  IBTF_DPRINTF_L3(cmlog, "ibcm_validate_path_attributes: "
 643  636                      "P_Key= 0x%X", attrp->pa_pkey);
 644  637          }
 645  638  
 646  639          return (IBT_SUCCESS);
 647  640  }
 648  641  
 649  642  
 650  643  static ibt_status_t
 651  644  ibcm_process_get_paths(void *tq_arg)
 652  645  {
 653  646          ibcm_path_tqargs_t      *p_arg = (ibcm_path_tqargs_t *)tq_arg;
 654  647          ibcm_dinfo_t            *dinfo;
 655  648          int                     len;
 656  649          uint8_t                 max_paths, num_path;
 657  650          ibt_status_t            retval;
 658  651          ib_gid_t                *d_gids_p = NULL;
 659  652          ibtl_cm_port_list_t     *slistp = NULL;
 660  653          uint_t                  dnum = 0;
 661  654          uint8_t                 num_dest, i, j;
 662  655          ibcm_hca_info_t         *hcap;
 663  656          ibmf_saa_handle_t       saa_handle;
 664  657  
 665  658          IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths(%p, 0x%X, %d) ",
 666  659              p_arg, p_arg->flags, p_arg->max_paths);
 667  660  
 668  661          max_paths = num_path = p_arg->max_paths;
 669  662  
 670  663          /*
 671  664           * Prepare the Destination list based on the input DGIDs and
 672  665           * other attributes.
 673  666           *
 674  667           * APM is requested and pa_dgids are specified.  If multiple DGIDs are
 675  668           * specified, check out whether they are companion to each other or if
 676  669           * only one DGID is specified, then get the companion port GID for that.
 677  670           */
 678  671          if (p_arg->attr.pa_num_dgids) {
 679  672                  if (p_arg->flags & IBT_PATH_APM) {
 680  673                          ib_gid_t        c_gid, n_gid;
 681  674  
 682  675                          IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: "
 683  676                              "DGIDs specified w/ APM Flag");
 684  677  
 685  678                          c_gid = p_arg->attr.pa_dgids[0];
 686  679                          if (p_arg->attr.pa_num_dgids > 1)
 687  680                                  n_gid = p_arg->attr.pa_dgids[1];
 688  681                          else
 689  682                                  n_gid.gid_prefix = n_gid.gid_guid = 0;
 690  683  
 691  684                          retval = ibcm_get_comp_pgids(c_gid, n_gid, 0, &d_gids_p,
 692  685                              &dnum);
 693  686                          if ((retval != IBT_SUCCESS) &&
 694  687                              (retval != IBT_GIDS_NOT_FOUND)) {
 695  688                                  IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths:"
 696  689                                      " Invalid DGIDs specified w/ APM Flag");
 697  690                                  goto path_error2;
 698  691                          }
 699  692                          IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: "
 700  693                              "Found %d Comp DGID", dnum);
 701  694                  }
 702  695  
 703  696                  if (dnum) {
 704  697                          len = 1;
 705  698                  } else {
 706  699                          len = p_arg->attr.pa_num_dgids - 1;
 707  700                  }
 708  701                  num_dest = len + 1;
 709  702  
 710  703                  IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: #dgid %d, dnum "
 711  704                      "%d, #dest %d", p_arg->attr.pa_num_dgids, dnum, num_dest);
 712  705          } else {
 713  706                  if (p_arg->flags & IBT_PATH_MULTI_SVC_DEST) {
 714  707                          IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_paths: "
 715  708                              "IBT_PATH_MULTI_SVC_DEST flags set");
 716  709                          len = max_paths - 1;
 717  710                  } else if (p_arg->flags & IBT_PATH_APM) {
 718  711                          len = 1;
 719  712                  } else {
 720  713                          len = 0;
 721  714                  }
 722  715                  num_dest = 0;
 723  716          }
 724  717  
 725  718          /* Allocate memory and accumulate all destination information */
 726  719          len = (len * sizeof (ibcm_dest_t)) + sizeof (ibcm_dinfo_t);
 727  720  
 728  721          dinfo = kmem_zalloc(len, KM_SLEEP);
 729  722          dinfo->num_dest = num_dest;
  
    | 
      ↓ open down ↓ | 
    238 lines elided | 
    
      ↑ open up ↑ | 
  
 730  723          if (p_arg->flags & IBT_PATH_PKEY)
 731  724                  dinfo->p_key = p_arg->attr.pa_pkey;
 732  725  
 733  726          for (i = 0, j = 0; i < num_dest; i++) {
 734  727                  if (i < p_arg->attr.pa_num_dgids)
 735  728                          dinfo->dest[i].d_gid = p_arg->attr.pa_dgids[i];
 736  729                  else
 737  730                          dinfo->dest[i].d_gid = d_gids_p[j++];
 738  731          }
 739  732  
 740      -        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*p_arg))
 741      -
 742  733          /* IBTF allocates memory for path_info in case of Async Get Paths */
 743  734          if (p_arg->paths == NULL)
 744  735                  p_arg->paths = kmem_zalloc(sizeof (ibt_path_info_t) * max_paths,
 745  736                      KM_SLEEP);
 746  737  
 747      -        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*p_arg))
 748      -
 749  738          /*
 750  739           * Get list of active HCA<->Port list, that matches input specified attr
 751  740           */
 752  741          IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: Get Paths from \n HCA "
 753  742              "(%llX:%d), SGID  %llX:%llX", p_arg->attr.pa_hca_guid,
 754  743              p_arg->attr.pa_hca_port_num, p_arg->attr.pa_sgid.gid_prefix,
 755  744              p_arg->attr.pa_sgid.gid_guid);
 756  745  
 757  746          retval = ibtl_cm_get_active_plist(&p_arg->attr, p_arg->flags, &slistp);
 758  747          if (retval != IBT_SUCCESS) {
 759  748                  IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: HCA capable of "
 760  749                      "requested source attributes NOT available.");
 761  750                  goto path_error;
 762  751          }
 763  752  
 764  753          IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: HCA (%llX, %d)",
 765  754              slistp->p_hca_guid, slistp->p_port_num);
 766  755  
 767  756          hcap = ibcm_find_hca_entry(slistp->p_hca_guid);
 768  757          if (hcap == NULL) {
 769  758                  IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: "
 770  759                      "NO HCA found");
 771  760                  retval = IBT_HCA_BUSY_DETACHING;
 772  761                  goto path_error;
 773  762          }
 774  763  
 775  764          /* Get SA Access Handle. */
 776  765          for (i = 0; i < slistp->p_count; i++) {
 777  766                  if (i == 0) {
 778  767                          /* Validate whether this HCA supports APM */
 779  768                          if ((p_arg->flags & IBT_PATH_APM) &&
 780  769                              (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG))) {
 781  770                                  IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths:"
 782  771                                      " HCA (%llX): APM NOT SUPPORTED ",
 783  772                                      slistp[i].p_hca_guid);
 784  773                                  retval = IBT_APM_NOT_SUPPORTED;
 785  774                                  goto path_error1;
 786  775                          }
  
    | 
      ↓ open down ↓ | 
    28 lines elided | 
    
      ↑ open up ↑ | 
  
 787  776                  }
 788  777  
 789  778                  saa_handle = ibcm_get_saa_handle(hcap, slistp[i].p_port_num);
 790  779                  if (saa_handle == NULL) {
 791  780                          IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: "
 792  781                              "SAA HDL NULL, HCA (%llX:%d) NOT ACTIVE",
 793  782                              slistp[i].p_hca_guid, slistp[i].p_port_num);
 794  783                          retval = IBT_HCA_PORT_NOT_ACTIVE;
 795  784                          goto path_error1;
 796  785                  }
 797      -                _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*slistp))
 798  786                  slistp[i].p_saa_hdl = saa_handle;
 799      -                _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*slistp))
 800  787          }
 801  788  
 802  789          /*
 803  790           * If Service Name or Service ID are specified, first retrieve
 804  791           * Service Records.
 805  792           */
 806  793          if ((p_arg->attr.pa_sid != 0) || ((p_arg->attr.pa_sname != NULL) &&
 807  794              (strlen(p_arg->attr.pa_sname) != 0))) {
 808  795  
 809  796                  IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: Get Service "
 810  797                      "Record for \n\t(%llX, \"%s\")", p_arg->attr.pa_sid,
 811  798                      ((p_arg->attr.pa_sname != NULL) ?
 812  799                      p_arg->attr.pa_sname : ""));
 813  800  
 814  801                  /* Get Service Records. */
 815  802                  retval = ibcm_saa_service_rec(p_arg, slistp, dinfo);
 816  803                  if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA)) {
 817  804                          IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: Status="
 818  805                              "%d, Failed to get Service Record for \n\t"
 819  806                              "(%llX, \"%s\")", retval, p_arg->attr.pa_sid,
 820  807                              ((p_arg->attr.pa_sname != NULL) ?
 821  808                              p_arg->attr.pa_sname : ""));
 822  809                          goto path_error1;
 823  810                  }
 824  811          }
 825  812  
 826  813          /* Get Path Records. */
 827  814          retval = ibcm_saa_path_rec(p_arg, slistp, dinfo, &num_path);
 828  815  
 829  816  path_error1:
 830  817          ibcm_dec_hca_acc_cnt(hcap);
 831  818  
 832  819  path_error:
 833  820          if (slistp)
 834  821                  ibtl_cm_free_active_plist(slistp);
 835  822  
 836  823          if (dinfo)
 837  824                  kmem_free(dinfo, len);
 838  825  
 839  826  path_error2:
 840  827          if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA))
 841  828                  num_path = 0;
 842  829  
 843  830          if (p_arg->num_paths_p != NULL)
 844  831                  *p_arg->num_paths_p = num_path;
 845  832  
 846  833          if ((dnum) && (d_gids_p))
 847  834                  kmem_free(d_gids_p, dnum * sizeof (ib_gid_t));
 848  835  
 849  836          if (p_arg->func) {   /* Do these only for Async Get Paths */
 850  837                  ibt_path_info_t *tmp_path_p;
 851  838  
 852  839                  if (retval == IBT_INSUFF_DATA) {
 853  840                          /*
 854  841                           * We allocated earlier memory based on "max_paths",
 855  842                           * but we got lesser path-records, so re-adjust that
 856  843                           * buffer so that caller can free the correct memory.
 857  844                           */
 858  845                          tmp_path_p = kmem_alloc(
 859  846                              sizeof (ibt_path_info_t) * num_path, KM_SLEEP);
 860  847  
 861  848                          bcopy(p_arg->paths, tmp_path_p,
 862  849                              num_path * sizeof (ibt_path_info_t));
 863  850  
 864  851                          kmem_free(p_arg->paths,
 865  852                              sizeof (ibt_path_info_t) * max_paths);
 866  853                  } else if (retval != IBT_SUCCESS) {
 867  854                          if (p_arg->paths)
 868  855                                  kmem_free(p_arg->paths,
 869  856                                      sizeof (ibt_path_info_t) * max_paths);
 870  857                          tmp_path_p = NULL;
 871  858                  } else {
 872  859                          tmp_path_p = p_arg->paths;
 873  860                  }
 874  861                  (*(p_arg->func))(p_arg->arg, retval, tmp_path_p, num_path);
 875  862          }
 876  863  
 877  864          len = (sizeof (ib_gid_t) * p_arg->attr.pa_num_dgids) +
 878  865              sizeof (ibcm_path_tqargs_t);
 879  866  
 880  867          if (p_arg && len)
 881  868                  kmem_free(p_arg, len);
 882  869  
 883  870          IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: done: status %d, "
 884  871              "Found %d/%d Path Records", retval, num_path, max_paths);
 885  872  
 886  873          return (retval);
 887  874  }
 888  875  
 889  876  
 890  877  /*
 891  878   * Perform SA Access to retrieve Path Records.
 892  879   */
 893  880  static ibt_status_t
 894  881  ibcm_saa_path_rec(ibcm_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl,
 895  882      ibcm_dinfo_t *dinfo, uint8_t *max_count)
 896  883  {
 897  884          uint8_t         num_path = *max_count;
 898  885          uint8_t         num_path_plus;
 899  886          uint8_t         extra, idx, rec_found = 0;
 900  887          ibt_status_t    retval = IBT_SUCCESS;
 901  888          int             unicast_dgid_present = 0;
 902  889          uint8_t         i;
 903  890  
 904  891          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec(%p, %p, %p, 0x%X, %d)",
 905  892              p_arg, sl, dinfo, p_arg->flags, *max_count);
 906  893  
 907  894          if ((dinfo->num_dest == 0) || (num_path == 0) || (sl == NULL)) {
 908  895                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: Invalid Counters");
 909  896                  return (IBT_INVALID_PARAM);
 910  897          }
 911  898  
 912  899          /*
 913  900           * Of the total needed "X" number of paths to "Y" number of destination
 914  901           * we need to get X/Y plus X%Y extra paths to each destination,
 915  902           * We do this so that we can choose the required number of path records
 916  903           * for the specific destination.
 917  904           */
 918  905          num_path /= dinfo->num_dest;
 919  906          extra = (*max_count % dinfo->num_dest);
 920  907  
 921  908          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: numpath %d extra %d dest %d",
 922  909              num_path, extra, dinfo->num_dest);
 923  910  
 924  911          /* Find out whether we need to get PathRecord for a MGID as DGID. */
 925  912          for (idx = 0; idx < dinfo->num_dest; idx++) {
 926  913                  ib_gid_t        dgid = dinfo->dest[idx].d_gid;
 927  914  
 928  915                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: DGID[%d]: %llX:%llX",
 929  916                      idx, dgid.gid_prefix, dgid.gid_guid);
 930  917  
 931  918                  if ((dgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) {
 932  919                          if (extra)
 933  920                                  num_path_plus = num_path + 1;
 934  921                          else
 935  922                                  num_path_plus = num_path;
 936  923  
 937  924                          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: Get %d Paths"
 938  925                              "- MGID(%016llX%016llX)", num_path_plus,
 939  926                              dgid.gid_prefix, dgid.gid_guid);
 940  927  
 941  928                          dinfo->dest[idx].d_tag = 1; /* MultiCast */
 942  929  
 943  930                          /* Yes, it's Single PathRec query for MGID as DGID. */
 944  931                          retval = ibcm_get_single_pathrec(p_arg, sl, dinfo, idx,
 945  932                              &num_path_plus, &p_arg->paths[rec_found]);
 946  933                          if ((retval != IBT_SUCCESS) &&
 947  934                              (retval != IBT_INSUFF_DATA)) {
 948  935                                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: "
 949  936                                      "Failed to get PathRec for MGID %d",
 950  937                                      retval);
 951  938                                  continue;
 952  939                          }
 953  940                          if (extra)
 954  941                                  extra--;
 955  942  
 956  943                          rec_found += num_path_plus;
 957  944                  }
 958  945                  if (rec_found == *max_count)
 959  946                          break;
 960  947          }
 961  948  
 962  949          for (i = 0; i < dinfo->num_dest; i++) {
 963  950                  if (dinfo->dest[i].d_tag == 0) {
 964  951                          unicast_dgid_present++;
 965  952                  }
 966  953          }
 967  954  
 968  955          num_path_plus = *max_count - rec_found;
 969  956  
 970  957          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: Recfound: %d, need to find "
 971  958              "%d, UniCastGID present %d", rec_found, num_path_plus,
 972  959              unicast_dgid_present);
 973  960  
 974  961          if ((unicast_dgid_present != 0) && (num_path_plus > 0)) {
 975  962                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: MultiSM=%X, #SRC=%d,"
 976  963                      "Dest%d", sl->p_multi, sl->p_count, unicast_dgid_present);
 977  964  
 978  965                  if ((sl->p_multi != IBTL_CM_SIMPLE_SETUP) ||
 979  966                      ((unicast_dgid_present == 1) && (sl->p_count == 1))) {
 980  967                          /*
 981  968                           * Use SinglePathRec if we are dealing w/ MultiSM or
 982  969                           * request is for one SGID to one DGID.
 983  970                           */
 984  971                          retval = ibcm_get_single_pathrec(p_arg, sl, dinfo, 0xFF,
 985  972                              &num_path_plus, &p_arg->paths[rec_found]);
 986  973                  } else {
 987  974                          uint8_t old_num_path_plus = num_path_plus;
 988  975  
 989  976                          /* MultiPathRec will be used for other queries. */
 990  977                          retval = ibcm_get_multi_pathrec(p_arg, sl, dinfo,
 991  978                              &num_path_plus, &p_arg->paths[rec_found]);
 992  979                          if ((retval != IBT_SUCCESS) &&
 993  980                              (retval != IBT_INSUFF_DATA) &&
 994  981                              (sl->p_count > 0) &&
 995  982                              (dinfo->num_dest > 0)) {
 996  983                                  ibtl_cm_port_list_t sl_tmp = *sl;
 997  984                                  ibcm_dinfo_t dinfo_tmp = *dinfo;
 998  985  
 999  986                                  sl_tmp.p_count = 1;
1000  987                                  dinfo_tmp.num_dest = 1;
1001  988                                  num_path_plus = old_num_path_plus;
1002  989                                  retval = ibcm_get_single_pathrec(p_arg, &sl_tmp,
1003  990                                      &dinfo_tmp, 0xFF, &num_path_plus,
1004  991                                      &p_arg->paths[rec_found]);
1005  992                          }
1006  993                  }
1007  994                  if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA)) {
1008  995                          IBTF_DPRINTF_L2(cmlog, "ibcm_saa_path_rec: "
1009  996                              "Failed to get PathRec: Status %d", retval);
1010  997                  } else {
1011  998                          rec_found += num_path_plus;
1012  999                  }
1013 1000          }
1014 1001  
1015 1002          if (rec_found == 0)  {
1016 1003                  if (retval == IBT_SUCCESS)
1017 1004                          retval = IBT_PATH_RECORDS_NOT_FOUND;
1018 1005          } else if (rec_found != *max_count)
1019 1006                  retval = IBT_INSUFF_DATA;
1020 1007          else if (rec_found != 0)
1021 1008                  retval = IBT_SUCCESS;
1022 1009  
1023 1010          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: done. Status = %d, "
1024 1011              "Found %d/%d Paths", retval, rec_found, *max_count);
1025 1012  
1026 1013          *max_count = rec_found; /* Update the return count. */
1027 1014  
1028 1015          return (retval);
1029 1016  }
1030 1017  
1031 1018  ibt_status_t
1032 1019  ibcm_contact_sa_access(ibmf_saa_handle_t saa_handle,
1033 1020      ibmf_saa_access_args_t *access_args, size_t *length, void **results_p)
1034 1021  {
1035 1022          int     retry;
1036 1023          int     sa_retval;
1037 1024  
1038 1025          IBTF_DPRINTF_L3(cmlog, "ibcm_contact_sa_access(%p, %p)",
1039 1026              saa_handle, access_args);
1040 1027  
1041 1028          ibcm_sa_access_enter();
1042 1029  
1043 1030          for (retry = 0; retry < ibcm_max_sa_retries; retry++) {
1044 1031                  sa_retval = ibmf_sa_access(saa_handle, access_args, 0,
1045 1032                      length, results_p);
1046 1033                  if (sa_retval != IBMF_TRANS_TIMEOUT)
1047 1034                          break;
1048 1035  
1049 1036                  IBTF_DPRINTF_L2(cmlog, "ibcm_contact_sa_access: "
1050 1037                      "ibmf_sa_access() - Timed Out (%d)", sa_retval);
1051 1038                  delay(ibcm_sa_timeout_delay);
1052 1039          }
1053 1040  
1054 1041          ibcm_sa_access_exit();
1055 1042  
1056 1043          if ((sa_retval == IBMF_SUCCESS) || (sa_retval == IBMF_NO_RECORDS) ||
1057 1044              (sa_retval == IBMF_REQ_INVALID)) {
1058 1045                  IBTF_DPRINTF_L3(cmlog, "ibcm_contact_sa_access: "
1059 1046                      "ibmf_sa_access() returned (%d)", sa_retval);
1060 1047                  return (IBT_SUCCESS);
1061 1048          } else  {
1062 1049                  IBTF_DPRINTF_L2(cmlog, "ibcm_contact_sa_access: "
1063 1050                      "ibmf_sa_access(): Failed (%d)", sa_retval);
1064 1051                  return (ibcm_ibmf_analyze_error(sa_retval));
1065 1052          }
1066 1053  }
1067 1054  
1068 1055  
1069 1056  static ibt_status_t
1070 1057  ibcm_update_pri(sa_path_record_t *pr_resp, ibtl_cm_port_list_t *sl,
1071 1058      ibcm_dinfo_t *dinfo, ibt_path_info_t *paths)
1072 1059  {
1073 1060          ibt_status_t    retval = IBT_SUCCESS;
1074 1061          int             d, s;
1075 1062  
1076 1063          retval = ibcm_update_cep_info(pr_resp, sl, NULL,
1077 1064              &paths->pi_prim_cep_path);
1078 1065          if (retval != IBT_SUCCESS)
1079 1066                  return (retval);
1080 1067  
1081 1068          /* Update some leftovers */
1082 1069          paths->pi_prim_pkt_lt = pr_resp->PacketLifeTime;
1083 1070          paths->pi_path_mtu = pr_resp->Mtu;
1084 1071  
1085 1072          for (d = 0; d < dinfo->num_dest; d++) {
1086 1073                  if (pr_resp->DGID.gid_guid == dinfo->dest[d].d_gid.gid_guid) {
1087 1074                          paths->pi_sid = dinfo->dest[d].d_sid;
1088 1075                          if (paths->pi_sid != 0) {
1089 1076                                  bcopy(&dinfo->dest[d].d_sdata,
1090 1077                                      &paths->pi_sdata, sizeof (ibt_srv_data_t));
1091 1078                          }
1092 1079                          break;
1093 1080                  }
1094 1081          }
1095 1082  
1096 1083          for (s = 0; s < sl->p_count; s++) {
1097 1084                  if (pr_resp->SGID.gid_guid == sl[s].p_sgid.gid_guid) {
1098 1085                          paths->pi_hca_guid = sl[s].p_hca_guid;
1099 1086                  }
1100 1087          }
1101 1088  
1102 1089          /* Set Alternate Path to invalid state. */
1103 1090          paths->pi_alt_cep_path.cep_hca_port_num = 0;
1104 1091          paths->pi_alt_cep_path.cep_adds_vect.av_dlid = 0;
1105 1092  
1106 1093          IBTF_DPRINTF_L5(cmlog, "Path: HCA GUID  = 0x%llX", paths->pi_hca_guid);
1107 1094          IBTF_DPRINTF_L5(cmlog, "Path: ServiceID = 0x%llX", paths->pi_sid);
1108 1095  
1109 1096          return (retval);
1110 1097  }
1111 1098  
1112 1099  
1113 1100  static ibt_status_t
1114 1101  ibcm_get_single_pathrec(ibcm_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl,
1115 1102      ibcm_dinfo_t *dinfo, uint8_t idx, uint8_t *num_path, ibt_path_info_t *paths)
1116 1103  {
1117 1104          sa_path_record_t        pathrec_req;
1118 1105          sa_path_record_t        *pr_resp;
1119 1106          ibmf_saa_access_args_t  access_args;
1120 1107          uint64_t                c_mask = 0;
1121 1108          void                    *results_p;
1122 1109          uint8_t                 num_rec;
1123 1110          size_t                  length;
1124 1111          ibt_status_t            retval;
1125 1112          int                     i, j, k;
1126 1113          uint8_t                 found, p_fnd;
1127 1114          ibt_path_attr_t         *attrp = &p_arg->attr;
1128 1115          ibmf_saa_handle_t       saa_handle;
1129 1116  
1130 1117          IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec(%p, %p, %p, %d)",
1131 1118              p_arg, sl, dinfo, *num_path);
1132 1119  
1133 1120          bzero(&pathrec_req, sizeof (sa_path_record_t));
1134 1121  
1135 1122          /* Is Flow Label Specified. */
1136 1123          if (attrp->pa_flow) {
1137 1124                  pathrec_req.FlowLabel = attrp->pa_flow;
1138 1125                  c_mask |= SA_PR_COMPMASK_FLOWLABEL;
1139 1126          }
1140 1127  
1141 1128          /* Is HopLimit Specified. */
1142 1129          if (p_arg->flags & IBT_PATH_HOP) {
1143 1130                  pathrec_req.HopLimit = attrp->pa_hop;
1144 1131                  c_mask |= SA_PR_COMPMASK_HOPLIMIT;
1145 1132          }
1146 1133  
1147 1134          /* Is P_Key Specified. */
1148 1135          if (dinfo->p_key) {
1149 1136                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: "
1150 1137                      "Specified or Global PKEY 0x%X", dinfo->p_key);
1151 1138                  pathrec_req.P_Key = dinfo->p_key;
1152 1139                  c_mask |= SA_PR_COMPMASK_PKEY;
1153 1140          }
1154 1141  
1155 1142          /* Is TClass Specified. */
1156 1143          if (attrp->pa_tclass) {
1157 1144                  pathrec_req.TClass = attrp->pa_tclass;
1158 1145                  c_mask |= SA_PR_COMPMASK_TCLASS;
1159 1146          }
1160 1147  
1161 1148          /* Is SL specified. */
1162 1149          if (attrp->pa_sl) {
1163 1150                  pathrec_req.SL = attrp->pa_sl;
1164 1151                  c_mask |= SA_PR_COMPMASK_SL;
1165 1152          }
1166 1153  
1167 1154          /* If IBT_PATH_PERF is set, then mark all selectors to BEST. */
1168 1155          if (p_arg->flags & IBT_PATH_PERF) {
1169 1156                  pathrec_req.PacketLifeTimeSelector = IBT_BEST;
1170 1157                  pathrec_req.MtuSelector = IBT_BEST;
1171 1158                  pathrec_req.RateSelector = IBT_BEST;
1172 1159  
1173 1160                  c_mask |= SA_PR_COMPMASK_PKTLTSELECTOR |
1174 1161                      SA_PR_COMPMASK_RATESELECTOR | SA_PR_COMPMASK_MTUSELECTOR;
1175 1162          } else {
1176 1163                  if (attrp->pa_pkt_lt.p_selector == IBT_BEST) {
1177 1164                          pathrec_req.PacketLifeTimeSelector = IBT_BEST;
1178 1165                          c_mask |= SA_PR_COMPMASK_PKTLTSELECTOR;
1179 1166                  }
1180 1167  
1181 1168                  if (attrp->pa_srate.r_selector == IBT_BEST) {
1182 1169                          pathrec_req.RateSelector = IBT_BEST;
1183 1170                          c_mask |= SA_PR_COMPMASK_RATESELECTOR;
1184 1171                  }
1185 1172  
1186 1173                  if (attrp->pa_mtu.r_selector == IBT_BEST) {
1187 1174                          pathrec_req.MtuSelector = IBT_BEST;
1188 1175                          c_mask |= SA_PR_COMPMASK_MTUSELECTOR;
1189 1176                  }
1190 1177          }
1191 1178  
1192 1179          /*
1193 1180           * Honor individual selection of these attributes,
1194 1181           * even if IBT_PATH_PERF is set.
1195 1182           */
1196 1183          /* Check out whether Packet Life Time is specified. */
1197 1184          if (attrp->pa_pkt_lt.p_pkt_lt) {
1198 1185                  pathrec_req.PacketLifeTime =
1199 1186                      ibt_usec2ib(attrp->pa_pkt_lt.p_pkt_lt);
1200 1187                  pathrec_req.PacketLifeTimeSelector =
1201 1188                      attrp->pa_pkt_lt.p_selector;
1202 1189  
1203 1190                  c_mask |= SA_PR_COMPMASK_PKTLT | SA_PR_COMPMASK_PKTLTSELECTOR;
1204 1191          }
1205 1192  
1206 1193          /* Is SRATE specified. */
1207 1194          if (attrp->pa_srate.r_srate) {
1208 1195                  pathrec_req.Rate = attrp->pa_srate.r_srate;
1209 1196                  pathrec_req.RateSelector = attrp->pa_srate.r_selector;
1210 1197  
1211 1198                  c_mask |= SA_PR_COMPMASK_RATE | SA_PR_COMPMASK_RATESELECTOR;
1212 1199          }
1213 1200  
1214 1201          /* Is MTU specified. */
1215 1202          if (attrp->pa_mtu.r_mtu) {
1216 1203                  pathrec_req.Mtu = attrp->pa_mtu.r_mtu;
1217 1204                  pathrec_req.MtuSelector = attrp->pa_mtu.r_selector;
1218 1205  
1219 1206                  c_mask |= SA_PR_COMPMASK_MTU | SA_PR_COMPMASK_MTUSELECTOR;
1220 1207          }
1221 1208  
1222 1209          /* We always get REVERSIBLE paths. */
1223 1210          pathrec_req.Reversible = 1;
1224 1211          c_mask |= SA_PR_COMPMASK_REVERSIBLE;
1225 1212  
1226 1213          pathrec_req.NumbPath = *num_path;
1227 1214          c_mask |= SA_PR_COMPMASK_NUMBPATH;
1228 1215  
1229 1216          if (idx != 0xFF) {
1230 1217                  /* MGID */
1231 1218                  pathrec_req.DGID = dinfo->dest[idx].d_gid;
1232 1219                  c_mask |= SA_PR_COMPMASK_DGID;
1233 1220          }
1234 1221  
1235 1222          p_fnd = found = 0;
1236 1223  
1237 1224          for (i = 0; i < sl->p_count; i++) {
1238 1225                  /* SGID */
1239 1226                  pathrec_req.SGID = sl[i].p_sgid;
1240 1227                  c_mask |= SA_PR_COMPMASK_SGID;
1241 1228                  saa_handle = sl[i].p_saa_hdl;
1242 1229  
1243 1230                  for (k = 0; k < dinfo->num_dest; k++) {
1244 1231                          if (idx == 0xFF) {              /* DGID */
1245 1232                                  if (dinfo->dest[k].d_tag != 0)
1246 1233                                          continue;
1247 1234  
1248 1235                                  if (pathrec_req.SGID.gid_prefix !=
1249 1236                                      dinfo->dest[k].d_gid.gid_prefix) {
1250 1237                                          IBTF_DPRINTF_L3(cmlog,
1251 1238                                              "ibcm_get_single_pathrec: SGID_pfx="
1252 1239                                              "%llX, DGID_pfx=%llX doesn't match",
1253 1240                                              pathrec_req.SGID.gid_prefix,
1254 1241                                              dinfo->dest[k].d_gid.gid_prefix);
1255 1242                                          continue;
1256 1243                                  }
1257 1244  
1258 1245                                  pathrec_req.DGID = dinfo->dest[k].d_gid;
1259 1246                                  c_mask |= SA_PR_COMPMASK_DGID;
1260 1247  
1261 1248                                  /*
1262 1249                                   * If we had performed Service Look-up, then we
1263 1250                                   * got P_Key from ServiceRecord, so get path
1264 1251                                   * records that satisfy this particular P_Key.
1265 1252                                   */
1266 1253                                  if ((dinfo->p_key == 0) &&
1267 1254                                      (dinfo->dest[k].d_pkey != 0)) {
1268 1255                                          pathrec_req.P_Key =
1269 1256                                              dinfo->dest[k].d_pkey;
1270 1257                                          c_mask |= SA_PR_COMPMASK_PKEY;
1271 1258                                  }
1272 1259                          }
1273 1260  
1274 1261                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: "
1275 1262                              "Get %d Path(s) between\nSGID %llX:%llX "
1276 1263                              "DGID %llX:%llX", pathrec_req.NumbPath,
1277 1264                              pathrec_req.SGID.gid_prefix,
1278 1265                              pathrec_req.SGID.gid_guid,
1279 1266                              pathrec_req.DGID.gid_prefix,
1280 1267                              pathrec_req.DGID.gid_guid);
1281 1268  
1282 1269                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: CMask"
1283 1270                              "=0x%llX, PKey=0x%X", c_mask, pathrec_req.P_Key);
1284 1271  
1285 1272                          /* Contact SA Access to retrieve Path Records. */
1286 1273                          access_args.sq_attr_id = SA_PATHRECORD_ATTRID;
1287 1274                          access_args.sq_template = &pathrec_req;
1288 1275                          access_args.sq_access_type = IBMF_SAA_RETRIEVE;
1289 1276                          access_args.sq_template_length =
1290 1277                              sizeof (sa_path_record_t);
1291 1278                          access_args.sq_component_mask = c_mask;
1292 1279                          access_args.sq_callback = NULL;
1293 1280                          access_args.sq_callback_arg = NULL;
1294 1281  
1295 1282                          retval = ibcm_contact_sa_access(saa_handle,
1296 1283                              &access_args, &length, &results_p);
1297 1284                          if (retval != IBT_SUCCESS) {
1298 1285                                  *num_path = 0;
1299 1286                                  return (retval);
1300 1287                          }
1301 1288  
1302 1289                          num_rec = length / sizeof (sa_path_record_t);
1303 1290  
1304 1291                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: "
1305 1292                              "FOUND %d/%d path requested", num_rec, *num_path);
1306 1293  
1307 1294                          if ((results_p == NULL) || (num_rec == 0)) {
1308 1295                                  if (idx != 0xFF)
1309 1296                                          break;
1310 1297                                  else
1311 1298                                          continue;
1312 1299                          }
1313 1300  
1314 1301                          /* Update the PathInfo from the response. */
1315 1302                          pr_resp = (sa_path_record_t *)results_p;
1316 1303                          for (j = 0; j < num_rec; j++, pr_resp++) {
1317 1304                                  if ((p_fnd != 0) &&
1318 1305                                      (p_arg->flags & IBT_PATH_APM)) {
1319 1306                                          IBTF_DPRINTF_L3(cmlog,
1320 1307                                              "ibcm_get_single_pathrec: "
1321 1308                                              "Fill Alternate Path");
1322 1309                                          retval = ibcm_update_cep_info(pr_resp,
1323 1310                                              sl, NULL,
1324 1311                                              &paths[found - 1].pi_alt_cep_path);
1325 1312                                          if (retval != IBT_SUCCESS)
1326 1313                                                  continue;
1327 1314  
1328 1315                                          /* Update some leftovers */
1329 1316                                          paths[found - 1].pi_alt_pkt_lt =
1330 1317                                              pr_resp->PacketLifeTime;
1331 1318                                          p_fnd = 0;
1332 1319                                  } else {
1333 1320                                          IBTF_DPRINTF_L3(cmlog,
1334 1321                                              "ibcm_get_single_pathrec: "
1335 1322                                              "Fill Primary Path");
1336 1323  
1337 1324                                          if (found == *num_path)
1338 1325                                                  break;
1339 1326  
1340 1327                                          retval = ibcm_update_pri(pr_resp, sl,
1341 1328                                              dinfo, &paths[found]);
1342 1329                                          if (retval != IBT_SUCCESS)
1343 1330                                                  continue;
1344 1331                                          p_fnd = 1;
1345 1332                                          found++;
1346 1333                                  }
1347 1334  
1348 1335                          }
1349 1336                          /* Deallocate the memory for results_p. */
1350 1337                          kmem_free(results_p, length);
1351 1338  
1352 1339                          if (idx != 0xFF)
1353 1340                                  break;          /* We r here for MGID */
1354 1341                  }
1355 1342                  if ((idx != 0xFF) && (found == *num_path))
1356 1343                          break;          /* We r here for MGID */
1357 1344          }
1358 1345  
1359 1346          if (found == 0)
1360 1347                  retval = IBT_PATH_RECORDS_NOT_FOUND;
1361 1348          else if (found != *num_path)
1362 1349                  retval = IBT_INSUFF_DATA;
1363 1350          else
1364 1351                  retval = IBT_SUCCESS;
1365 1352  
1366 1353          IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: done. Status %d, "
1367 1354              "Found %d/%d Paths", retval, found, *num_path);
1368 1355  
1369 1356          *num_path = found;
1370 1357  
1371 1358          return (retval);
1372 1359  }
1373 1360  
1374 1361  
1375 1362  static ibt_status_t
1376 1363  ibcm_get_multi_pathrec(ibcm_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl,
1377 1364      ibcm_dinfo_t *dinfo, uint8_t *num_path, ibt_path_info_t *paths)
1378 1365  {
1379 1366          sa_multipath_record_t   *mpr_req;
1380 1367          sa_path_record_t        *pr_resp;
1381 1368          ibmf_saa_access_args_t  access_args;
1382 1369          void                    *results_p;
1383 1370          uint64_t                c_mask = 0;
1384 1371          ib_gid_t                *gid_ptr, *gid_s_ptr;
1385 1372          size_t                  length;
1386 1373          int                     template_len;
1387 1374          uint8_t                 found, num_rec;
1388 1375          int                     i, k;
1389 1376          ibt_status_t            retval;
1390 1377          uint8_t                 sgid_cnt, dgid_cnt;
1391 1378          ibt_path_attr_t         *attrp = &p_arg->attr;
1392 1379  
1393 1380          IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec(%p, %p, %p, %d)",
1394 1381              attrp, sl, dinfo, *num_path);
1395 1382  
1396 1383          for (i = 0, dgid_cnt = 0; i < dinfo->num_dest; i++) {
1397 1384                  if (dinfo->dest[i].d_tag == 0)
1398 1385                          dgid_cnt++;
1399 1386          }
1400 1387  
1401 1388          sgid_cnt = sl->p_count;
1402 1389  
1403 1390          if ((sgid_cnt == 0) || (dgid_cnt == 0)) {
1404 1391                  IBTF_DPRINTF_L2(cmlog, "ibcm_get_multi_pathrec: sgid_cnt(%d) or"
1405 1392                      " dgid_cnt(%d) is zero", sgid_cnt, dgid_cnt);
1406 1393                  return (IBT_INVALID_PARAM);
1407 1394          }
1408 1395  
1409 1396          IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: Get %d records between "
1410 1397              "%d Src(s) <=> %d Dest(s)", *num_path, sgid_cnt, dgid_cnt);
1411 1398  
1412 1399          /*
1413 1400           * Calculate the size for multi-path records template, which includes
1414 1401           * constant portion of the multipath record, plus variable size for
1415 1402           * SGID (sgid_cnt) and DGID (dgid_cnt).
1416 1403           */
1417 1404          template_len = ((dgid_cnt + sgid_cnt) * sizeof (ib_gid_t)) +
1418 1405              sizeof (sa_multipath_record_t);
1419 1406  
1420 1407          mpr_req = kmem_zalloc(template_len, KM_SLEEP);
1421 1408  
1422 1409          ASSERT(mpr_req != NULL);
1423 1410  
1424 1411          gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
1425 1412              sizeof (sa_multipath_record_t));
1426 1413  
1427 1414          /* Get the starting pointer where GIDs are stored. */
1428 1415          gid_s_ptr = gid_ptr;
1429 1416  
  
    | 
      ↓ open down ↓ | 
    620 lines elided | 
    
      ↑ open up ↑ | 
  
1430 1417          /* SGID */
1431 1418          for (i = 0; i < sgid_cnt; i++) {
1432 1419                  *gid_ptr = sl[i].p_sgid;
1433 1420  
1434 1421                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: SGID[%d] = "
1435 1422                      "(%llX:%llX)", i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
1436 1423  
1437 1424                  gid_ptr++;
1438 1425          }
1439 1426  
1440      -        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req))
1441      -
1442 1427          mpr_req->SGIDCount = sgid_cnt;
1443 1428          c_mask = SA_MPR_COMPMASK_SGIDCOUNT;
1444 1429  
1445 1430          /* DGIDs */
1446 1431          for (i = 0; i < dinfo->num_dest; i++) {
1447 1432                  if (dinfo->dest[i].d_tag == 0) {
1448 1433                          *gid_ptr = dinfo->dest[i].d_gid;
1449 1434  
1450 1435                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: "
1451 1436                              "DGID[%d] = (%llX:%llX)", i, gid_ptr->gid_prefix,
1452 1437                              gid_ptr->gid_guid);
1453 1438                          gid_ptr++;
1454 1439                  }
1455 1440          }
1456 1441  
1457 1442          mpr_req->DGIDCount = dgid_cnt;
1458 1443          c_mask |= SA_MPR_COMPMASK_DGIDCOUNT;
1459 1444  
1460 1445          /* Is Flow Label Specified. */
1461 1446          if (attrp->pa_flow) {
1462 1447                  mpr_req->FlowLabel = attrp->pa_flow;
1463 1448                  c_mask |= SA_MPR_COMPMASK_FLOWLABEL;
1464 1449          }
1465 1450  
1466 1451          /* Is HopLimit Specified. */
1467 1452          if (p_arg->flags & IBT_PATH_HOP) {
1468 1453                  mpr_req->HopLimit = attrp->pa_hop;
1469 1454                  c_mask |= SA_MPR_COMPMASK_HOPLIMIT;
1470 1455          }
1471 1456  
1472 1457          /* Is TClass Specified. */
1473 1458          if (attrp->pa_tclass) {
1474 1459                  mpr_req->TClass = attrp->pa_tclass;
1475 1460                  c_mask |= SA_MPR_COMPMASK_TCLASS;
1476 1461          }
1477 1462  
1478 1463          /* Is SL specified. */
1479 1464          if (attrp->pa_sl) {
1480 1465                  mpr_req->SL = attrp->pa_sl;
1481 1466                  c_mask |= SA_MPR_COMPMASK_SL;
1482 1467          }
1483 1468  
1484 1469          if (p_arg->flags & IBT_PATH_PERF) {
1485 1470                  mpr_req->PacketLifeTimeSelector = IBT_BEST;
1486 1471                  mpr_req->RateSelector = IBT_BEST;
1487 1472                  mpr_req->MtuSelector = IBT_BEST;
1488 1473  
1489 1474                  c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR |
1490 1475                      SA_MPR_COMPMASK_RATESELECTOR | SA_MPR_COMPMASK_MTUSELECTOR;
1491 1476          } else {
1492 1477                  if (attrp->pa_pkt_lt.p_selector == IBT_BEST) {
1493 1478                          mpr_req->PacketLifeTimeSelector = IBT_BEST;
1494 1479                          c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR;
1495 1480                  }
1496 1481  
1497 1482                  if (attrp->pa_srate.r_selector == IBT_BEST) {
1498 1483                          mpr_req->RateSelector = IBT_BEST;
1499 1484                          c_mask |= SA_MPR_COMPMASK_RATESELECTOR;
1500 1485                  }
1501 1486  
1502 1487                  if (attrp->pa_mtu.r_selector == IBT_BEST) {
1503 1488                          mpr_req->MtuSelector = IBT_BEST;
1504 1489                          c_mask |= SA_MPR_COMPMASK_MTUSELECTOR;
1505 1490                  }
1506 1491          }
1507 1492  
1508 1493          /*
1509 1494           * Honor individual selection of these attributes,
1510 1495           * even if IBT_PATH_PERF is set.
1511 1496           */
1512 1497          /* Check out whether Packet Life Time is specified. */
1513 1498          if (attrp->pa_pkt_lt.p_pkt_lt) {
1514 1499                  mpr_req->PacketLifeTime =
1515 1500                      ibt_usec2ib(attrp->pa_pkt_lt.p_pkt_lt);
1516 1501                  mpr_req->PacketLifeTimeSelector =
1517 1502                      attrp->pa_pkt_lt.p_selector;
1518 1503  
1519 1504                  c_mask |= SA_MPR_COMPMASK_PKTLT |
1520 1505                      SA_MPR_COMPMASK_PKTLTSELECTOR;
1521 1506          }
1522 1507  
1523 1508          /* Is SRATE specified. */
1524 1509          if (attrp->pa_srate.r_srate) {
1525 1510                  mpr_req->Rate = attrp->pa_srate.r_srate;
1526 1511                  mpr_req->RateSelector = attrp->pa_srate.r_selector;
1527 1512  
1528 1513                  c_mask |= SA_MPR_COMPMASK_RATE |
1529 1514                      SA_MPR_COMPMASK_RATESELECTOR;
1530 1515          }
1531 1516  
1532 1517          /* Is MTU specified. */
1533 1518          if (attrp->pa_mtu.r_mtu) {
1534 1519                  mpr_req->Mtu = attrp->pa_mtu.r_mtu;
1535 1520                  mpr_req->MtuSelector = attrp->pa_mtu.r_selector;
1536 1521  
1537 1522                  c_mask |= SA_MPR_COMPMASK_MTU |
1538 1523                      SA_MPR_COMPMASK_MTUSELECTOR;
1539 1524          }
1540 1525  
1541 1526          /* Is P_Key Specified or obtained during Service Look-up. */
1542 1527          if (dinfo->p_key) {
1543 1528                  mpr_req->P_Key = dinfo->p_key;
1544 1529                  c_mask |= SA_MPR_COMPMASK_PKEY;
1545 1530          }
1546 1531  
  
    | 
      ↓ open down ↓ | 
    95 lines elided | 
    
      ↑ open up ↑ | 
  
1547 1532          /* We always get REVERSIBLE paths. */
1548 1533          mpr_req->Reversible = 1;
1549 1534          c_mask |= SA_MPR_COMPMASK_REVERSIBLE;
1550 1535  
1551 1536          if (p_arg->flags & IBT_PATH_AVAIL) {
1552 1537                  mpr_req->IndependenceSelector = 1;
1553 1538                  c_mask |= SA_MPR_COMPMASK_INDEPSEL;
1554 1539          }
1555 1540  
1556 1541          /* we will not specify how many records we want. */
1557      -
1558      -        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req))
1559      -
1560 1542          IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: CMask: %llX Pkey: %X",
1561 1543              c_mask, mpr_req->P_Key);
1562 1544  
1563 1545          /* Contact SA Access to retrieve Path Records. */
1564 1546          access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID;
1565 1547          access_args.sq_access_type = IBMF_SAA_RETRIEVE;
1566 1548          access_args.sq_component_mask = c_mask;
1567 1549          access_args.sq_template = mpr_req;
1568 1550          access_args.sq_template_length = sizeof (sa_multipath_record_t);
1569 1551          access_args.sq_callback = NULL;
1570 1552          access_args.sq_callback_arg = NULL;
1571 1553  
1572 1554          retval = ibcm_contact_sa_access(sl->p_saa_hdl, &access_args, &length,
1573 1555              &results_p);
1574 1556          if (retval != IBT_SUCCESS) {
1575 1557                  *num_path = 0;  /* Update the return count. */
1576 1558                  kmem_free(mpr_req, template_len);
1577 1559                  return (retval);
1578 1560          }
1579 1561  
1580 1562          num_rec = length / sizeof (sa_path_record_t);
1581 1563  
1582 1564          IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: Found %d Paths",
1583 1565              num_rec);
1584 1566  
1585 1567          found = 0;
1586 1568          if ((results_p != NULL) && (num_rec > 0)) {
1587 1569                  /* Update the PathInfo with the response Path Records */
1588 1570                  pr_resp = (sa_path_record_t *)results_p;
1589 1571  
1590 1572                  for (i = 0; i < num_rec; i++) {
1591 1573                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: "
1592 1574                              "P[%d]: SG %llX, DG %llX", i,
1593 1575                              pr_resp[i].SGID.gid_guid, pr_resp[i].DGID.gid_guid);
1594 1576                  }
1595 1577  
1596 1578                  if (p_arg->flags & (IBT_PATH_APM | IBT_PATH_AVAIL)) {
1597 1579                          sa_path_record_t *p_resp = NULL, *a_resp = NULL;
1598 1580                          sa_path_record_t *p_tmp = NULL, *a_tmp = NULL;
1599 1581                          int             p_found = 0, a_found = 0;
1600 1582                          ib_gid_t        p_sg, a_sg, p_dg, a_dg;
1601 1583                          int             p_tmp_found = 0, a_tmp_found = 0;
1602 1584  
1603 1585                          p_sg = gid_s_ptr[0];
1604 1586                          if (sgid_cnt > 1)
1605 1587                                  a_sg = gid_s_ptr[1];
1606 1588                          else
1607 1589                                  a_sg = p_sg;
1608 1590  
1609 1591                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: "
1610 1592                              "REQ: P_SG: %llX, A_SG: %llX",
1611 1593                              p_sg.gid_guid, a_sg.gid_guid);
1612 1594  
1613 1595                          p_dg = gid_s_ptr[sgid_cnt];
1614 1596                          if (dgid_cnt > 1)
1615 1597                                  a_dg = gid_s_ptr[sgid_cnt + 1];
1616 1598                          else
1617 1599                                  a_dg = p_dg;
1618 1600  
1619 1601                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: "
1620 1602                              "REQ: P_DG: %llX, A_DG: %llX",
1621 1603                              p_dg.gid_guid, a_dg.gid_guid);
1622 1604  
1623 1605                          /*
1624 1606                           * If SGID and/or DGID is specified by user, make sure
1625 1607                           * they get their primary-path on those node points.
1626 1608                           */
1627 1609                          for (i = 0; i < num_rec; i++, pr_resp++) {
1628 1610                                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec:"
1629 1611                                      " PF %d, AF %d,\n\t\t P[%d] = SG: %llX, "
1630 1612                                      "DG: %llX", p_found, a_found, i,
1631 1613                                      pr_resp->SGID.gid_guid,
1632 1614                                      pr_resp->DGID.gid_guid);
1633 1615  
1634 1616                                  if ((!p_found) &&
1635 1617                                      (p_dg.gid_guid == pr_resp->DGID.gid_guid)) {
1636 1618                                          IBTF_DPRINTF_L3(cmlog,
1637 1619                                              "ibcm_get_multi_pathrec: "
1638 1620                                              "Pri DGID Match.. ");
1639 1621                                          if (p_sg.gid_guid ==
1640 1622                                              pr_resp->SGID.gid_guid) {
1641 1623                                                  p_found = 1;
1642 1624                                                  p_resp = pr_resp;
1643 1625                                                  IBTF_DPRINTF_L3(cmlog,
1644 1626                                                      "ibcm_get_multi_pathrec: "
1645 1627                                                      "Primary Path Found");
1646 1628  
1647 1629                                                  if (a_found)
1648 1630                                                          break;
1649 1631                                                  else
1650 1632                                                          continue;
1651 1633                                          } else if ((!p_tmp_found) &&
1652 1634                                              (a_sg.gid_guid ==
1653 1635                                              pr_resp->SGID.gid_guid)) {
1654 1636                                                  p_tmp_found = 1;
1655 1637                                                  p_tmp = pr_resp;
1656 1638                                                  IBTF_DPRINTF_L3(cmlog,
1657 1639                                                      "ibcm_get_multi_pathrec: "
1658 1640                                                      "Tmp Pri Path Found");
1659 1641                                          }
1660 1642                                          IBTF_DPRINTF_L3(cmlog,
1661 1643                                              "ibcm_get_multi_pathrec:"
1662 1644                                              "Pri SGID Don't Match.. ");
1663 1645                                  }
1664 1646  
1665 1647                                  if ((!a_found) &&
1666 1648                                      (a_dg.gid_guid == pr_resp->DGID.gid_guid)) {
1667 1649                                          IBTF_DPRINTF_L3(cmlog,
1668 1650                                              "ibcm_get_multi_pathrec:"
1669 1651                                              "Alt DGID Match.. ");
1670 1652                                          if (a_sg.gid_guid ==
1671 1653                                              pr_resp->SGID.gid_guid) {
1672 1654                                                  a_found = 1;
1673 1655                                                  a_resp = pr_resp;
1674 1656  
1675 1657                                                  IBTF_DPRINTF_L3(cmlog,
1676 1658                                                      "ibcm_get_multi_pathrec:"
1677 1659                                                      "Alternate Path Found ");
1678 1660  
1679 1661                                                  if (p_found)
1680 1662                                                          break;
1681 1663                                                  else
1682 1664                                                          continue;
1683 1665                                          } else if ((!a_tmp_found) &&
1684 1666                                              (p_sg.gid_guid ==
1685 1667                                              pr_resp->SGID.gid_guid)) {
1686 1668                                                  a_tmp_found = 1;
1687 1669                                                  a_tmp = pr_resp;
1688 1670  
1689 1671                                                  IBTF_DPRINTF_L3(cmlog,
1690 1672                                                      "ibcm_get_multi_pathrec:"
1691 1673                                                      "Tmp Alt Path Found ");
1692 1674                                          }
1693 1675                                          IBTF_DPRINTF_L3(cmlog,
1694 1676                                              "ibcm_get_multi_pathrec:"
1695 1677                                              "Alt SGID Don't Match.. ");
1696 1678                                  }
1697 1679                          }
1698 1680  
1699 1681                          if ((p_found == 0) && (a_found == 0) &&
1700 1682                              (p_tmp_found == 0) && (a_tmp_found == 0)) {
1701 1683                                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec:"
1702 1684                                      " Path to desired node points NOT "
1703 1685                                      "Available.");
1704 1686                                  retval = IBT_PATH_RECORDS_NOT_FOUND;
1705 1687                                  goto get_mpr_end;
1706 1688                          }
1707 1689  
1708 1690                          if (p_resp == NULL) {
1709 1691                                  if (a_resp != NULL) {
1710 1692                                          p_resp = a_resp;
1711 1693                                          a_resp = NULL;
1712 1694                                  } else if (p_tmp != NULL) {
1713 1695                                          p_resp = p_tmp;
1714 1696                                          p_tmp = NULL;
1715 1697                                  } else if (a_tmp != NULL) {
1716 1698                                          p_resp = a_tmp;
1717 1699                                          a_tmp = NULL;
1718 1700                                  }
1719 1701                          }
1720 1702                          if (a_resp == NULL) {
1721 1703                                  if (a_tmp != NULL) {
1722 1704                                          a_resp = a_tmp;
1723 1705                                          a_tmp = NULL;
1724 1706                                  } else if (p_tmp != NULL) {
1725 1707                                          a_resp = p_tmp;
1726 1708                                          p_tmp = NULL;
1727 1709                                  }
1728 1710                          }
1729 1711  
1730 1712                          /* Fill in Primary Path */
1731 1713                          retval = ibcm_update_pri(p_resp, sl, dinfo,
1732 1714                              &paths[found]);
1733 1715                          if (retval != IBT_SUCCESS)
1734 1716                                  goto get_mpr_end;
1735 1717  
1736 1718                          if (p_arg->flags & IBT_PATH_APM) {
1737 1719                                  /* Fill in Alternate Path */
1738 1720                                  if (a_resp != NULL) {
1739 1721                                          /*
1740 1722                                           * a_resp will point to AltPathInfo
1741 1723                                           * buffer.
1742 1724                                           */
1743 1725                                          retval = ibcm_update_cep_info(a_resp,
1744 1726                                              sl, NULL,
1745 1727                                              &paths[found].pi_alt_cep_path);
1746 1728                                          if (retval != IBT_SUCCESS)
1747 1729                                                  goto get_mpr_end;
1748 1730  
1749 1731                                          /* Update some leftovers */
1750 1732                                          paths[found].pi_alt_pkt_lt =
1751 1733                                              a_resp->PacketLifeTime;
1752 1734                                  } else {
1753 1735                                          IBTF_DPRINTF_L3(cmlog,
1754 1736                                              "ibcm_get_multi_pathrec:"
1755 1737                                              " Alternate Path NOT Available.");
1756 1738                                          retval = IBT_INSUFF_DATA;
1757 1739                                  }
1758 1740                                  found++;
1759 1741                          } else if (p_arg->flags & IBT_PATH_AVAIL) {
1760 1742                                  found++;
1761 1743  
1762 1744                                  if (found < *num_path) {
1763 1745  
1764 1746                                          /* Fill in second Path */
1765 1747                                          if (a_resp != NULL) {
1766 1748                                                  retval = ibcm_update_pri(a_resp,
1767 1749                                                      sl, dinfo, &paths[found]);
1768 1750                                                  if (retval != IBT_SUCCESS)
1769 1751                                                          goto get_mpr_end;
1770 1752                                                  else
1771 1753                                                          found++;
1772 1754                                          } else {
1773 1755                                                  IBTF_DPRINTF_L3(cmlog,
1774 1756                                                      "ibcm_get_multi_pathrec: "
1775 1757                                                      "SecondPath NOT Available");
1776 1758                                                  retval = IBT_INSUFF_DATA;
1777 1759                                          }
1778 1760                                  }
1779 1761                          }
1780 1762                  } else {        /* If NOT APM */
1781 1763                          boolean_t       check_pkey = B_FALSE;
1782 1764  
1783 1765                          /* mark flag whether to validate PKey or not. */
1784 1766                          if ((dinfo->p_key == 0) && (dinfo->dest[0].d_pkey != 0))
1785 1767                                  check_pkey = B_TRUE;
1786 1768  
1787 1769                          for (i = 0; i < num_rec; i++, pr_resp++) {
1788 1770                                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec:"
1789 1771                                      " PKeyCheck - %s, PKey=0x%X, DGID(%llX)",
1790 1772                                      ((check_pkey == B_TRUE)?"REQD":"NOT_REQD"),
1791 1773                                      pr_resp->P_Key, pr_resp->DGID.gid_guid);
1792 1774  
1793 1775                                  if (check_pkey) {
1794 1776                                          boolean_t       match_found = B_FALSE;
1795 1777  
1796 1778                                          /* For all DGIDs */
1797 1779                                          for (k = 0; k < dinfo->num_dest; k++) {
1798 1780                                                  if (dinfo->dest[k].d_tag != 0)
1799 1781                                                          continue;
1800 1782  
1801 1783                                                  if ((dinfo->dest[k].d_gid.
1802 1784                                                      gid_guid ==
1803 1785                                                      pr_resp->DGID.gid_guid) &&
1804 1786                                                      (dinfo->dest[k].d_pkey ==
1805 1787                                                      pr_resp->P_Key)) {
1806 1788                                                          match_found = B_TRUE;
1807 1789                                                          break;
1808 1790                                                  }
1809 1791                                          }
1810 1792                                          if (!match_found)
1811 1793                                                  continue;
1812 1794                                  }
1813 1795                                  /* Fill in Primary Path */
1814 1796                                  retval = ibcm_update_pri(pr_resp, sl, dinfo,
1815 1797                                      &paths[found]);
1816 1798                                  if (retval != IBT_SUCCESS)
1817 1799                                          continue;
1818 1800  
1819 1801                                  if (++found == *num_path)
1820 1802                                          break;
1821 1803                          }
1822 1804                  }
1823 1805  get_mpr_end:
1824 1806                  kmem_free(results_p, length);
1825 1807          }
1826 1808          kmem_free(mpr_req, template_len);
1827 1809  
1828 1810          if (found == 0)
1829 1811                  retval = IBT_PATH_RECORDS_NOT_FOUND;
1830 1812          else if (found != *num_path)
1831 1813                  retval = IBT_INSUFF_DATA;
1832 1814          else
1833 1815                  retval = IBT_SUCCESS;
1834 1816  
1835 1817          IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: Done (status %d). "
1836 1818              "Found %d/%d Paths", retval, found, *num_path);
1837 1819  
1838 1820          *num_path = found;      /* Update the return count. */
1839 1821  
1840 1822          return (retval);
1841 1823  }
1842 1824  
1843 1825  
1844 1826  /*
1845 1827   * Update the output path records buffer with the values as obtained from
1846 1828   * SA Access retrieve call results for Path Records.
1847 1829   */
1848 1830  static ibt_status_t
1849 1831  ibcm_update_cep_info(sa_path_record_t *prec_resp, ibtl_cm_port_list_t *sl,
1850 1832      ibtl_cm_hca_port_t *hport, ibt_cep_path_t *cep_p)
1851 1833  {
1852 1834          ibt_status_t    retval;
1853 1835          int             i;
1854 1836  
1855 1837          IBCM_DUMP_PATH_REC(prec_resp);
1856 1838  
1857 1839          /*
1858 1840           * If path's packet life time is more than 4 seconds, IBCM cannot
1859 1841           * handle this path connection, so discard this path record.
1860 1842           */
1861 1843          if (prec_resp->PacketLifeTime > ibcm_max_ib_pkt_lt) {
1862 1844                  IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: Path's Packet "
1863 1845                      "LifeTime too high %d, Maximum allowed %d IB Time (4 sec)",
1864 1846                      prec_resp->PacketLifeTime, ibcm_max_ib_pkt_lt);
1865 1847                  return (ibt_get_module_failure(IBT_FAILURE_IBSM, 0));
1866 1848          }
1867 1849  
1868 1850          if ((prec_resp->Mtu > IB_MTU_4K) || (prec_resp->Mtu < IB_MTU_256)) {
1869 1851                  IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: MTU (%d) from "
1870 1852                      "pathrecord is invalid, reject it.", prec_resp->Mtu);
1871 1853                  return (ibt_get_module_failure(IBT_FAILURE_IBSM, 0));
1872 1854          }
1873 1855  
1874 1856          /* Source Node Information. */
1875 1857          cep_p->cep_adds_vect.av_sgid = prec_resp->SGID;
1876 1858          if (hport != NULL) {
1877 1859                  /* Convert P_Key to P_Key_Index */
1878 1860                  retval = ibt_pkey2index_byguid(hport->hp_hca_guid,
1879 1861                      hport->hp_port, prec_resp->P_Key, &cep_p->cep_pkey_ix);
1880 1862                  if (retval != IBT_SUCCESS) {
1881 1863                          /* Failed to get pkey_index from pkey */
1882 1864                          IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: "
1883 1865                              "Pkey2Index (PKey = %X) conversion failed: %d",
1884 1866                              prec_resp->P_Key, retval);
1885 1867                          return (ibt_get_module_failure(IBT_FAILURE_IBSM, 0));
1886 1868                  }
1887 1869                  cep_p->cep_adds_vect.av_sgid_ix = hport->hp_sgid_ix;
1888 1870                  cep_p->cep_adds_vect.av_src_path =
1889 1871                      prec_resp->SLID - hport->hp_base_lid;
1890 1872                  cep_p->cep_adds_vect.av_port_num = cep_p->cep_hca_port_num =
1891 1873                      hport->hp_port;
1892 1874          } else if (sl != NULL) {
1893 1875                  for (i = 0; i < sl->p_count; i++) {
1894 1876                          if (prec_resp->SGID.gid_guid == sl[i].p_sgid.gid_guid) {
1895 1877                                  /* Convert P_Key to P_Key_Index */
1896 1878                                  retval = ibt_pkey2index_byguid(sl[i].p_hca_guid,
1897 1879                                      sl[i].p_port_num, prec_resp->P_Key,
1898 1880                                      &cep_p->cep_pkey_ix);
1899 1881                                  if (retval != IBT_SUCCESS) {
1900 1882                                          /* Failed to get pkey_index from pkey */
1901 1883                                          IBTF_DPRINTF_L2(cmlog,
1902 1884                                              "ibcm_update_cep_info: Pkey2Index "
1903 1885                                              "(PKey = %X) conversion failed: %d",
1904 1886                                              prec_resp->P_Key, retval);
1905 1887                                          return (ibt_get_module_failure(
1906 1888                                              IBT_FAILURE_IBSM, 0));
1907 1889                                  }
1908 1890  
1909 1891                                  cep_p->cep_adds_vect.av_sgid_ix =
1910 1892                                      sl[i].p_sgid_ix;
1911 1893                                  cep_p->cep_adds_vect.av_src_path =
1912 1894                                      prec_resp->SLID - sl[i].p_base_lid;
1913 1895                                  cep_p->cep_adds_vect.av_port_num =
1914 1896                                      sl[i].p_port_num;
1915 1897                                  cep_p->cep_hca_port_num = sl[i].p_port_num;
1916 1898  
1917 1899                                  break;
1918 1900                          }
1919 1901                  }
1920 1902          } else {
1921 1903                  IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: Sl or Hport "
1922 1904                      "must be non-null");
1923 1905                  return (IBT_INVALID_PARAM);
1924 1906          }
1925 1907  
1926 1908          if (prec_resp->Rate) {
1927 1909                  cep_p->cep_adds_vect.av_srate = prec_resp->Rate;
1928 1910          } else {
1929 1911                  IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: SRate (%d) from "
1930 1912                      "pathrecord is invalid, reject it.", prec_resp->Rate);
1931 1913                  return (ibt_get_module_failure(IBT_FAILURE_IBSM, 0));
1932 1914          }
1933 1915          /*
1934 1916           * If both Source and Destination GID prefix are same, then GRH is not
1935 1917           * valid, so make it as false, else set this field as true.
1936 1918           */
1937 1919          if (prec_resp->SGID.gid_prefix == prec_resp->DGID.gid_prefix)
1938 1920                  cep_p->cep_adds_vect.av_send_grh = B_FALSE;
1939 1921          else
1940 1922                  cep_p->cep_adds_vect.av_send_grh = B_TRUE;
1941 1923  
1942 1924          /* SGID and SGID Index. */
1943 1925          cep_p->cep_adds_vect.av_sgid = prec_resp->SGID;
1944 1926          cep_p->cep_adds_vect.av_flow = prec_resp->FlowLabel;
1945 1927          cep_p->cep_adds_vect.av_tclass = prec_resp->TClass;
1946 1928          cep_p->cep_adds_vect.av_hop = prec_resp->HopLimit;
1947 1929  
1948 1930          /* Address Vector Definition. */
1949 1931          cep_p->cep_adds_vect.av_dlid = prec_resp->DLID;
1950 1932          cep_p->cep_adds_vect.av_srvl = prec_resp->SL;
1951 1933  
1952 1934          /* DGID */
1953 1935          cep_p->cep_adds_vect.av_dgid = prec_resp->DGID;
1954 1936  
1955 1937          /* CEP Timeout is NOT filled in by PATH routines. */
1956 1938          cep_p->cep_timeout = 0;
1957 1939  
1958 1940          IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: Done. Port=%d, PKey=%X\n"
1959 1941              "SGID=%llX:%llX DGID=%llX:%llX", cep_p->cep_adds_vect.av_port_num,
1960 1942              prec_resp->P_Key,
  
    | 
      ↓ open down ↓ | 
    391 lines elided | 
    
      ↑ open up ↑ | 
  
1961 1943              prec_resp->SGID.gid_prefix, prec_resp->SGID.gid_guid,
1962 1944              prec_resp->DGID.gid_prefix, prec_resp->DGID.gid_guid);
1963 1945  
1964 1946          return (IBT_SUCCESS);
1965 1947  }
1966 1948  
1967 1949  
1968 1950  static void
1969 1951  ibcm_fill_svcinfo(sa_service_record_t *sr_resp, ibcm_dest_t *dest)
1970 1952  {
1971      -        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dest))
1972      -
1973 1953          dest->d_gid = sr_resp->ServiceGID;
1974 1954          dest->d_sid = sr_resp->ServiceID;
1975 1955          ibcm_swizzle_to_srv(sr_resp->ServiceData, &dest->d_sdata);
1976 1956          dest->d_pkey = sr_resp->ServiceP_Key;
1977 1957  
1978      -        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*dest))
1979      -
1980 1958          IBTF_DPRINTF_L3(cmlog, "ibcm_fill_svcinfo: SID(%llX), GID(%llX:%llX)"
1981 1959              "\n\tSvcPKey 0x%X", dest->d_sid, dest->d_gid.gid_prefix,
1982 1960              dest->d_gid.gid_guid, dest->d_pkey);
1983 1961  }
1984 1962  
1985 1963  
1986 1964  static ib_gid_t
1987 1965  ibcm_saa_get_agid(ibtl_cm_port_list_t *sl, ib_gid_t *gidp, uint_t ngid)
1988 1966  {
1989 1967          int             k, l;
1990 1968          ib_gid_t        a_gid;
1991 1969  
1992 1970          a_gid.gid_prefix = a_gid.gid_guid = 0;
1993 1971  
1994 1972          for (k = 0; k < sl->p_count; k++) {
1995 1973                  for (l = 0; l < ngid; l++) {
1996 1974  
1997 1975                          if (gidp->gid_prefix == sl->p_sgid.gid_prefix) {
1998 1976                                  a_gid = *gidp;
1999 1977                                  break;
2000 1978                          }
2001 1979                          if (a_gid.gid_guid && a_gid.gid_prefix)
2002 1980                                  break;
2003 1981                          gidp++;
2004 1982                  }
2005 1983                  if (a_gid.gid_guid && a_gid.gid_prefix)
2006 1984                          break;
2007 1985                  sl++;
2008 1986          }
2009 1987          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_get_agid: AltGID = %llX:%llX",
2010 1988              a_gid.gid_prefix, a_gid.gid_guid);
2011 1989  
2012 1990          return (a_gid);
2013 1991  }
2014 1992  
2015 1993  /*
2016 1994   * Perform SA Access to retrieve Service Records.
2017 1995   * On Success, returns ServiceID and ServiceGID info in '*dinfo'.
2018 1996   */
2019 1997  static ibt_status_t
2020 1998  ibcm_saa_service_rec(ibcm_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl,
2021 1999      ibcm_dinfo_t *dinfo)
2022 2000  {
2023 2001          sa_service_record_t     svcrec_req;
2024 2002          sa_service_record_t     *svcrec_resp;
2025 2003          void                    *results_p;
2026 2004          uint64_t                component_mask = 0;
2027 2005          size_t                  length;
2028 2006          uint8_t                 i, j, k, rec_found, s;
2029 2007          ibmf_saa_access_args_t  access_args;
2030 2008          ibt_status_t            retval;
2031 2009          ibt_path_attr_t         *attrp = &p_arg->attr;
2032 2010          uint64_t                tmp_sd_flag = attrp->pa_sd_flags;
2033 2011          uint8_t                 num_req;
2034 2012  
2035 2013          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec(%p, %p)", p_arg, sl);
2036 2014  
2037 2015          bzero(&svcrec_req, sizeof (svcrec_req));
2038 2016  
2039 2017          /* Service Name */
2040 2018          if ((attrp->pa_sname != NULL) && (strlen(attrp->pa_sname) != 0)) {
2041 2019                  (void) strncpy((char *)(svcrec_req.ServiceName),
2042 2020                      attrp->pa_sname, IB_SVC_NAME_LEN);
2043 2021  
2044 2022                  component_mask |= SA_SR_COMPMASK_NAME;
2045 2023          }
2046 2024  
2047 2025          /* Service ID */
2048 2026          if (attrp->pa_sid) {
2049 2027                  svcrec_req.ServiceID = attrp->pa_sid;
2050 2028                  component_mask |= SA_SR_COMPMASK_ID;
2051 2029          }
2052 2030  
2053 2031          /* Is P_Key Specified. */
2054 2032          if (p_arg->flags & IBT_PATH_PKEY) {
2055 2033                  svcrec_req.ServiceP_Key = attrp->pa_pkey;
2056 2034                  component_mask |= SA_SR_COMPMASK_PKEY;
2057 2035          }
2058 2036  
2059 2037          /* Is ServiceData Specified. */
2060 2038          if (attrp->pa_sd_flags != IBT_NO_SDATA) {
2061 2039                  /* Handle endianess for service data. */
2062 2040                  ibcm_swizzle_from_srv(&attrp->pa_sdata, svcrec_req.ServiceData);
2063 2041  
2064 2042                  /*
2065 2043                   * Lets not interpret each and every ServiceData flags,
2066 2044                   * just pass it on to SAA. Shift the flag, to suit
2067 2045                   * SA_SR_COMPMASK_ALL_DATA definition.
2068 2046                   */
2069 2047                  component_mask |= (tmp_sd_flag << 7);
2070 2048          }
2071 2049  
2072 2050          if (dinfo->num_dest == 1) {
2073 2051  
2074 2052                  /* If a single DGID is specified, provide it */
2075 2053                  svcrec_req.ServiceGID = dinfo->dest->d_gid;
2076 2054                  component_mask |= SA_SR_COMPMASK_GID;
2077 2055  
2078 2056                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec:%llX:%llX",
2079 2057                      svcrec_req.ServiceGID.gid_prefix,
2080 2058                      svcrec_req.ServiceGID.gid_guid);
2081 2059          }
2082 2060  
2083 2061          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2084 2062              "Perform SA Access: Mask: 0x%X", component_mask);
2085 2063  
2086 2064          /*
2087 2065           * Call in SA Access retrieve routine to get Service Records.
2088 2066           *
2089 2067           * SA Access framework allocated memory for the "results_p".
2090 2068           * Make sure to deallocate once we are done with the results_p.
2091 2069           * The size of the buffer allocated will be as returned in
2092 2070           * "length" field.
2093 2071           */
2094 2072          access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
2095 2073          access_args.sq_access_type = IBMF_SAA_RETRIEVE;
2096 2074          access_args.sq_component_mask = component_mask;
2097 2075          access_args.sq_template = &svcrec_req;
2098 2076          access_args.sq_template_length = sizeof (sa_service_record_t);
2099 2077          access_args.sq_callback = NULL;
2100 2078          access_args.sq_callback_arg = NULL;
2101 2079  
2102 2080          for (s = 0; s < sl->p_count; s++) {
2103 2081                  retval = ibcm_contact_sa_access(sl[s].p_saa_hdl, &access_args,
2104 2082                      &length, &results_p);
2105 2083                  if (retval != IBT_SUCCESS)
2106 2084                          if (sl[s].p_multi & IBTL_CM_MULTI_SM)
2107 2085                                  continue;
2108 2086                          else
2109 2087                                  return (retval);
2110 2088  
2111 2089                  if ((results_p == NULL) || (length == 0)) {
2112 2090                          IBTF_DPRINTF_L2(cmlog, "ibcm_saa_service_rec: SvcRec "
2113 2091                              "Not Found: res_p %p, len %d", results_p, length);
2114 2092                          if (sl[s].p_multi & IBTL_CM_MULTI_SM) {
2115 2093                                  retval = IBT_SERVICE_RECORDS_NOT_FOUND;
2116 2094                                  continue;
2117 2095                          } else
2118 2096                                  return (IBT_SERVICE_RECORDS_NOT_FOUND);
2119 2097                  }
2120 2098  
2121 2099                  /* if we are here, we got some records. so break. */
2122 2100                  break;
2123 2101          }
2124 2102  
2125 2103          if (retval != IBT_SUCCESS)
2126 2104                  return (retval);
2127 2105  
2128 2106          num_req = length / sizeof (sa_service_record_t);
2129 2107  
2130 2108          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: Got %d Service Records.",
2131 2109              num_req);
2132 2110  
2133 2111          svcrec_resp = (sa_service_record_t *)results_p;
2134 2112          rec_found = 0;
2135 2113  
2136 2114          /* Update the return values. */
2137 2115          if (dinfo->num_dest) {
2138 2116                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: Get ServiceRec "
2139 2117                      "for Specified DGID: %d", dinfo->num_dest);
2140 2118  
2141 2119                  for (i = 0; i < num_req; i++, svcrec_resp++) {
2142 2120                          /* Limited P_Key is NOT supported as of now!. */
2143 2121                          if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) {
2144 2122                                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2145 2123                                      "SvcPkey 0x%X limited, reject the record.",
2146 2124                                      svcrec_resp->ServiceP_Key);
2147 2125                                  continue;
2148 2126                          }
2149 2127  
2150 2128                          for (j = 0; j < dinfo->num_dest; j++) {
2151 2129                                  if (dinfo->dest[j].d_gid.gid_guid ==
2152 2130                                      svcrec_resp->ServiceGID.gid_guid) {
2153 2131                                          ibcm_fill_svcinfo(svcrec_resp,
2154 2132                                              &dinfo->dest[j]);
2155 2133                                          rec_found++;
2156 2134                                  }
2157 2135                                  if (rec_found == dinfo->num_dest)
2158 2136                                          break;
2159 2137                          }
2160 2138                          if (rec_found == dinfo->num_dest)
2161 2139                                  break;
2162 2140                  }
2163 2141                  if (rec_found != dinfo->num_dest) {
2164 2142                          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: Did NOT "
2165 2143                              "find ServiceRec for all DGIDs: (%d/%d)", rec_found,
2166 2144                              dinfo->num_dest);
2167 2145                          retval = IBT_INSUFF_DATA;
2168 2146                  }
2169 2147          } else if (p_arg->flags & IBT_PATH_APM) {
2170 2148                  ib_gid_t                p_gid, a_gid, last_p_gid;
2171 2149                  ib_gid_t                *gidp = NULL;
2172 2150                  uint_t                  n_gids;
2173 2151                  sa_service_record_t     *stmp;
2174 2152                  boolean_t               pri_fill_done = B_FALSE;
2175 2153                  boolean_t               alt_fill_done = B_FALSE;
2176 2154                  ib_pkey_t               p_pkey = 0, a_pkey = 0;
2177 2155  
2178 2156                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: Need to "
2179 2157                      "find ServiceRec that can satisfy APM");
2180 2158  
2181 2159                  p_gid.gid_prefix = p_gid.gid_guid = 0;
2182 2160                  a_gid.gid_prefix = a_gid.gid_guid = 0;
2183 2161                  last_p_gid.gid_prefix = last_p_gid.gid_guid = 0;
2184 2162  
2185 2163                  for (i = 0; i < num_req; i++, svcrec_resp++) {
2186 2164                          ibt_status_t    ret;
2187 2165                          boolean_t       is_this_on_local_node = B_FALSE;
2188 2166  
2189 2167                          /* Limited P_Key is NOT supported as of now!. */
2190 2168                          if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) {
2191 2169                                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2192 2170                                      "SvcPkey 0x%X limited, reject the record.",
2193 2171                                      svcrec_resp->ServiceP_Key);
2194 2172                                  continue;
2195 2173                          }
2196 2174  
2197 2175                          p_gid = svcrec_resp->ServiceGID;
2198 2176  
2199 2177                          /* Let's avoid LoopBack Nodes. */
2200 2178                          for (j = 0; j < sl->p_count; j++) {
2201 2179                                  if (p_gid.gid_guid == sl[j].p_sgid.gid_guid) {
2202 2180                                          is_this_on_local_node = B_TRUE;
2203 2181  
2204 2182                                          IBTF_DPRINTF_L3(cmlog,
2205 2183                                              "ibcm_saa_service_rec: ServiceGID "
2206 2184                                              "%llX:%llX is on Local Node, "
2207 2185                                              "search for remote.",
2208 2186                                              p_gid.gid_prefix, p_gid.gid_guid);
2209 2187                                  }
2210 2188                          }
2211 2189  
2212 2190                          if (is_this_on_local_node) {
2213 2191                                  if ((i + 1) < num_req) {
2214 2192                                          p_gid.gid_prefix = 0;
2215 2193                                          p_gid.gid_guid = 0;
2216 2194                                          continue;
2217 2195                                  } else if (last_p_gid.gid_prefix != 0) {
2218 2196                                          p_gid = last_p_gid;
2219 2197                                          break;
2220 2198                                  }
2221 2199                          }
2222 2200  
2223 2201                          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2224 2202                              "Finally let Primary DGID = %llX:%llX",
2225 2203                              p_gid.gid_prefix, p_gid.gid_guid);
2226 2204  
2227 2205                          ret = ibt_get_companion_port_gids(p_gid, 0, 0,
2228 2206                              &gidp, &n_gids);
2229 2207                          if (ret == IBT_SUCCESS) {
2230 2208                                  IBTF_DPRINTF_L3(cmlog,
2231 2209                                      "ibcm_saa_service_rec: Found %d "
2232 2210                                      "CompGID for %llX:%llX", n_gids,
2233 2211                                      p_gid.gid_prefix, p_gid.gid_guid);
2234 2212  
2235 2213                                  stmp = (sa_service_record_t *)results_p;
2236 2214                                  a_gid.gid_prefix = a_gid.gid_guid = 0;
2237 2215  
2238 2216                                  if (sl->p_multi & IBTL_CM_MULTI_SM) {
2239 2217                                          /* validate sn_pfx */
2240 2218                                          a_gid = ibcm_saa_get_agid(sl,
2241 2219                                              gidp, n_gids);
2242 2220                                  } else {
2243 2221                                          for (k = 0; k < num_req; k++) {
2244 2222                                                  ib_gid_t sg = stmp->ServiceGID;
2245 2223  
2246 2224                                                  IBTF_DPRINTF_L3(cmlog,
2247 2225                                                      "ibcm_saa_service_rec: "
2248 2226                                                      "SvcGID[%d] = %llX:%llX", k,
2249 2227                                                      sg.gid_prefix, sg.gid_guid);
2250 2228  
2251 2229                                                  for (j = 0; j < n_gids; j++) {
2252 2230                                                          if (gidp[j].gid_guid ==
2253 2231                                                              sg.gid_guid) {
2254 2232                                                                  a_gid = gidp[j];
2255 2233                                                                  break;
2256 2234                                                          }
2257 2235                                                  }
2258 2236                                                  if (a_gid.gid_guid)
2259 2237                                                          break;
2260 2238                                                  stmp++;
2261 2239                                          }
2262 2240                                          if (a_gid.gid_guid == 0) {
2263 2241                                                  /* Rec not found for Alt. */
2264 2242                                                  for (j = 0; j < n_gids; j++) {
2265 2243                                                          if (gidp[j].gid_prefix
2266 2244                                                              == p_gid.
2267 2245                                                              gid_prefix) {
2268 2246                                                                  a_gid = gidp[j];
2269 2247                                                                  break;
2270 2248                                                          }
2271 2249                                                  }
2272 2250                                          }
2273 2251                                  }
2274 2252                                  kmem_free(gidp,
2275 2253                                      n_gids * sizeof (ib_gid_t));
2276 2254  
2277 2255                                  if (a_gid.gid_guid)
2278 2256                                          break;
2279 2257                          } else if (ret == IBT_GIDS_NOT_FOUND) {
2280 2258                                  last_p_gid = p_gid;
2281 2259                                  IBTF_DPRINTF_L3(cmlog,
2282 2260                                      "ibcm_saa_service_rec: Didn't find "
2283 2261                                      "CompGID for %llX:%llX, ret=%d",
2284 2262                                      p_gid.gid_prefix, p_gid.gid_guid,
2285 2263                                      ret);
2286 2264                          } else {
2287 2265                                  IBTF_DPRINTF_L3(cmlog,
2288 2266                                      "ibcm_saa_service_rec: Call to "
2289 2267                                      "ibt_get_companion_port_gids(%llX:"
2290 2268                                      "%llX) Failed = %d",
2291 2269                                      p_gid.gid_prefix, p_gid.gid_guid,
2292 2270                                      ret);
2293 2271                          }
2294 2272                  }
2295 2273  
2296 2274                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: \n\t"
2297 2275                      "Pri DGID(%llX:%llX), Alt DGID(%llX:%llX)",
2298 2276                      p_gid.gid_prefix, p_gid.gid_guid, a_gid.gid_prefix,
2299 2277                      a_gid.gid_guid);
2300 2278  
2301 2279                  svcrec_resp = (sa_service_record_t *)results_p;
2302 2280  
2303 2281                  for (i = 0, j = 0; i < num_req; i++, svcrec_resp++) {
2304 2282                          /* Limited P_Key is NOT supported as of now!. */
2305 2283                          if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) {
2306 2284                                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2307 2285                                      "SvcPkey 0x%X limited, reject the record.",
2308 2286                                      svcrec_resp->ServiceP_Key);
2309 2287                                  continue;
2310 2288                          }
2311 2289  
2312 2290                          if ((!pri_fill_done) && (p_gid.gid_guid ==
2313 2291                              svcrec_resp->ServiceGID.gid_guid)) {
2314 2292                                  p_pkey = svcrec_resp->ServiceP_Key;
2315 2293                                  if ((a_pkey != 0) &&
2316 2294                                      (a_pkey != p_pkey)) {
2317 2295                                          IBTF_DPRINTF_L3(cmlog,
2318 2296                                              "ibcm_saa_service_rec: "
2319 2297                                              "Pri(0x%X) & Alt (0x%X) "
2320 2298                                              "PKey must match.",
2321 2299                                              p_pkey, a_pkey);
2322 2300                                          p_pkey = 0;
2323 2301                                          continue;
2324 2302                                  }
2325 2303                                  ibcm_fill_svcinfo(svcrec_resp,
2326 2304                                      &dinfo->dest[j++]);
2327 2305                                  rec_found++;
2328 2306                                  pri_fill_done = B_TRUE;
2329 2307                          } else if ((!alt_fill_done) && (a_gid.gid_guid ==
2330 2308                              svcrec_resp->ServiceGID.gid_guid)) {
2331 2309                                  a_pkey = svcrec_resp->ServiceP_Key;
2332 2310                                  if ((p_pkey != 0) &&
2333 2311                                      (a_pkey != p_pkey)) {
2334 2312                                          IBTF_DPRINTF_L3(cmlog,
2335 2313                                              "ibcm_saa_service_rec: "
2336 2314                                              "Pri(0x%X) & Alt (0x%X) "
2337 2315                                              "PKey must match.",
2338 2316                                              p_pkey, a_pkey);
2339 2317                                          a_pkey = 0;
2340 2318                                          continue;
2341 2319                                  }
2342 2320                                  ibcm_fill_svcinfo(svcrec_resp,
2343 2321                                      &dinfo->dest[j++]);
2344 2322                                  rec_found++;
2345 2323                                  alt_fill_done = B_TRUE;
2346 2324                          }
2347 2325  
2348 2326                          if (rec_found == 2)
2349 2327                                  break;
2350 2328                  }
2351 2329                  if ((!alt_fill_done) && (a_gid.gid_guid)) {
2352 2330                          dinfo->dest[j].d_gid = a_gid;
2353 2331                          dinfo->dest[j].d_pkey = p_pkey;
2354 2332                          rec_found++;
2355 2333                          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2356 2334                              "Let Alt Pkey=%X, DGID=%llX:%llX", p_pkey,
2357 2335                              a_gid.gid_prefix, a_gid.gid_guid);
2358 2336                  }
2359 2337  
2360 2338                  if (rec_found == 1)
2361 2339                          retval = IBT_INSUFF_DATA;
2362 2340          } else if (p_arg->flags & IBT_PATH_MULTI_SVC_DEST) {
2363 2341                  for (i = 0; i < num_req; i++, svcrec_resp++) {
2364 2342                          ib_gid_t        p_gid;
2365 2343                          boolean_t       is_this_on_local_node = B_FALSE;
2366 2344  
2367 2345                          /* Limited P_Key is NOT supported as of now!. */
2368 2346                          if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) {
2369 2347                                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2370 2348                                      "SvcPkey 0x%X limited, reject the record.",
2371 2349                                      svcrec_resp->ServiceP_Key);
2372 2350                                  continue;
2373 2351                          }
2374 2352  
2375 2353                          p_gid = svcrec_resp->ServiceGID;
2376 2354  
2377 2355                          /* Let's avoid LoopBack Nodes. */
2378 2356                          for (j = 0; j < sl->p_count; j++) {
2379 2357                                  if (p_gid.gid_guid == sl[j].p_sgid.gid_guid) {
2380 2358                                          is_this_on_local_node = B_TRUE;
2381 2359                                          IBTF_DPRINTF_L3(cmlog,
2382 2360                                              "ibcm_saa_service_rec: ServiceGID "
2383 2361                                              "%llX:%llX is on Local Node, "
2384 2362                                              "search for remote.",
2385 2363                                              p_gid.gid_prefix, p_gid.gid_guid);
2386 2364                                  }
2387 2365                          }
2388 2366  
2389 2367                          if (is_this_on_local_node)
2390 2368                                  if ((i + 1) < num_req)
2391 2369                                          continue;
2392 2370  
2393 2371                          IBTF_DPRINTF_L4(cmlog, "ibcm_saa_service_rec: "
2394 2372                              "Found ServiceGID = %llX:%llX",
2395 2373                              p_gid.gid_prefix, p_gid.gid_guid);
2396 2374  
2397 2375                          ibcm_fill_svcinfo(svcrec_resp,
2398 2376                              &dinfo->dest[rec_found]);
2399 2377                          rec_found++;
2400 2378                          if (rec_found == p_arg->max_paths)
2401 2379                                  break;
2402 2380                  }
2403 2381  
2404 2382                  if (rec_found < p_arg->max_paths)
2405 2383                          retval = IBT_INSUFF_DATA;
2406 2384          } else {
2407 2385                  for (i = 0; i < num_req; i++) {
2408 2386                          /* Limited P_Key is NOT supported as of now!. */
2409 2387                          if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) {
2410 2388                                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2411 2389                                      "SvcPkey 0x%X limited, reject the record.",
2412 2390                                      svcrec_resp->ServiceP_Key);
2413 2391                                  svcrec_resp++;
2414 2392                                  continue;
2415 2393                          }
2416 2394  
2417 2395                          ibcm_fill_svcinfo(svcrec_resp, &dinfo->dest[0]);
2418 2396                          rec_found = 1;
2419 2397  
2420 2398                          /* Avoid having loopback node */
2421 2399                          if (svcrec_resp->ServiceGID.gid_guid !=
2422 2400                              sl->p_sgid.gid_guid) {
2423 2401                                  break;
2424 2402                          } else {
2425 2403                                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2426 2404                                      "avoid LoopBack node.");
2427 2405                                  svcrec_resp++;
2428 2406                          }
2429 2407                  }
2430 2408          }
2431 2409  
2432 2410          /* Deallocate the memory for results_p. */
2433 2411          kmem_free(results_p, length);
2434 2412          if (dinfo->num_dest == 0)
2435 2413                  dinfo->num_dest = rec_found;
2436 2414  
2437 2415          /*
2438 2416           * Check out whether all Service Path we looking for are on the same
2439 2417           * P_key. If yes, then set the global p_key field with that value,
2440 2418           * to make it easy during SA Path Query.
2441 2419           */
2442 2420          if ((dinfo->num_dest) && (dinfo->p_key == 0)) {
2443 2421                  ib_pkey_t       pk = dinfo->dest[0].d_pkey;
2444 2422  
2445 2423                  if (dinfo->num_dest == 1) {
2446 2424                          dinfo->p_key = pk;
2447 2425                  } else {
2448 2426                          for (i = 1; i < (dinfo->num_dest - 1); i++) {
2449 2427                                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: "
2450 2428                                      "pk= 0x%X, pk[%d]= 0x%X", pk, i,
2451 2429                                      dinfo->dest[i].d_pkey);
2452 2430                                  if (pk != dinfo->dest[i].d_pkey) {
2453 2431                                          dinfo->p_key = 0;
2454 2432                                          break;
2455 2433                                  } else {
2456 2434                                          dinfo->p_key = pk;
2457 2435                                  }
2458 2436                          }
2459 2437                  }
2460 2438          }
2461 2439  
2462 2440          if (rec_found == 0) {
2463 2441                  IBTF_DPRINTF_L2(cmlog, "ibcm_saa_service_rec: "
2464 2442                      "ServiceRec NOT Found");
2465 2443                  retval = IBT_SERVICE_RECORDS_NOT_FOUND;
2466 2444          }
2467 2445  
2468 2446          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: done. Status %d, "
2469 2447              "PKey 0x%X, Found %d SvcRec", retval, dinfo->p_key, rec_found);
2470 2448  
2471 2449          return (retval);
2472 2450  }
2473 2451  
2474 2452  
2475 2453  static boolean_t
2476 2454  ibcm_compare_paths(sa_path_record_t *pr_resp, ibt_cep_path_t *rc_path,
2477 2455      ibtl_cm_hca_port_t *c_hp)
2478 2456  {
2479 2457          if ((rc_path->cep_hca_port_num == c_hp->hp_port) &&
2480 2458              (rc_path->cep_adds_vect.av_src_path ==
2481 2459              (pr_resp->SLID - c_hp->hp_base_lid)) &&
2482 2460              (rc_path->cep_adds_vect.av_dlid == pr_resp->DLID) &&
2483 2461              (rc_path->cep_adds_vect.av_srate == pr_resp->Rate)) {
2484 2462                  return (B_TRUE);
2485 2463          } else {
2486 2464                  return (B_FALSE);
2487 2465          }
2488 2466  }
2489 2467  
2490 2468  /*
2491 2469   * ibcm_get_comp_pgids() routine gets the companion port for 'gid'.
2492 2470   *
2493 2471   * On success:
2494 2472   *      If 'n_gid' is specified, then verify whether 'n_gid' is indeed a
2495 2473   *      companion portgid of 'gid'.  If matches return success or else error.
2496 2474   *
2497 2475   *      If 'n_gid' is NOT specified, then return back SUCCESS along with
2498 2476   *      obtained Companion PortGids 'gid_p', where 'num' indicated number
2499 2477   *      of companion portgids returned in 'gid_p'.
2500 2478   */
2501 2479  
2502 2480  static ibt_status_t
2503 2481  ibcm_get_comp_pgids(ib_gid_t gid, ib_gid_t n_gid, ib_guid_t hca_guid,
2504 2482      ib_gid_t **gid_p, uint_t *num)
2505 2483  {
2506 2484          ibt_status_t    ret;
2507 2485          int             i;
2508 2486  
2509 2487          ret = ibt_get_companion_port_gids(gid, hca_guid, 0, gid_p, num);
2510 2488          if ((ret != IBT_SUCCESS) && (ret != IBT_GIDS_NOT_FOUND)) {
2511 2489                  IBTF_DPRINTF_L2(cmlog, "ibcm_get_comp_pgids: "
2512 2490                      "ibt_get_companion_port_gids(%llX:%llX) Failed: %d",
2513 2491                      gid.gid_prefix, gid.gid_guid, ret);
2514 2492          } else if ((ret == IBT_GIDS_NOT_FOUND) && (n_gid.gid_guid != 0)) {
2515 2493                  IBTF_DPRINTF_L2(cmlog, "ibcm_get_comp_pgids: Specified GID "
2516 2494                      "(%llX:%llX) is NOT a Companion \n\t to current channel's "
2517 2495                      "GID(%llX:%llX)", n_gid.gid_prefix, n_gid.gid_guid,
2518 2496                      gid.gid_prefix, gid.gid_guid);
2519 2497                  ret = IBT_INVALID_PARAM;
2520 2498          } else if (n_gid.gid_guid != 0) {
2521 2499                  /*
2522 2500                   * We found some Comp GIDs and n_gid is specified. Validate
2523 2501                   * whether the 'n_gid' specified is indeed the companion port
2524 2502                   * GID of 'gid'.
2525 2503                   */
2526 2504                  for (i = 0; i < *num; i++) {
2527 2505                          if ((n_gid.gid_prefix == gid_p[i]->gid_prefix) &&
2528 2506                              (n_gid.gid_guid == gid_p[i]->gid_guid)) {
2529 2507                                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_comp_pgids: "
2530 2508                                      "Matching Found!. Done.");
2531 2509                                  return (IBT_SUCCESS);
2532 2510                          }
2533 2511                  }
2534 2512                  IBTF_DPRINTF_L2(cmlog, "ibcm_get_comp_pgids: GID (%llX:%llX)\n"
2535 2513                      "\t and (%llX:%llX) are NOT Companion Port GIDS",
2536 2514                      n_gid.gid_prefix, n_gid.gid_guid, gid.gid_prefix,
2537 2515                      gid.gid_guid);
2538 2516                  ret = IBT_INVALID_PARAM;
2539 2517          } else {
2540 2518                  ret = IBT_SUCCESS;
2541 2519          }
2542 2520  
2543 2521          IBTF_DPRINTF_L3(cmlog, "ibcm_get_comp_pgids: done. Status = %d", ret);
2544 2522          return (ret);
2545 2523  }
2546 2524  
2547 2525  /*
2548 2526   * Function:
2549 2527   *      ibt_get_alt_path
2550 2528   * Input:
2551 2529   *      rc_chan         An RC channel handle returned in a previous call
2552 2530   *                      ibt_alloc_rc_channel(9F), specifies the channel to open.
2553 2531   *      flags           Path flags.
2554 2532   *      attrp           A pointer to an ibt_alt_path_attr_t(9S) structure that
2555 2533   *                      specifies required attributes of the selected path(s).
2556 2534   * Output:
2557 2535   *      api_p           An ibt_alt_path_info_t(9S) struct filled in as output
2558 2536   *                      parameters.
2559 2537   * Returns:
2560 2538   *      IBT_SUCCESS on Success else appropriate error.
2561 2539   * Description:
2562 2540   *      Finds the best alternate path to a specified channel (as determined by
2563 2541   *      the IBTL) that satisfies the requirements specified in an
2564 2542   *      ibt_alt_path_attr_t struct.  The specified channel must have been
2565 2543   *      previously opened successfully using ibt_open_rc_channel.
2566 2544   *      This function also ensures that the service being accessed by the
2567 2545   *      channel is available at the selected alternate port.
2568 2546   *
2569 2547   *      Note: The apa_dgid must be on the same destination channel adapter,
2570 2548   *      if specified.
2571 2549   *      This routine can not be called from interrupt context.
2572 2550   */
2573 2551  ibt_status_t
2574 2552  ibt_get_alt_path(ibt_channel_hdl_t rc_chan, ibt_path_flags_t flags,
2575 2553      ibt_alt_path_attr_t *attrp, ibt_alt_path_info_t *api_p)
2576 2554  {
2577 2555          sa_multipath_record_t   *mpr_req;
2578 2556          sa_path_record_t        *pr_resp;
2579 2557          ibmf_saa_access_args_t  access_args;
2580 2558          ibt_qp_query_attr_t     qp_attr;
2581 2559          ibtl_cm_hca_port_t      c_hp, n_hp;
2582 2560          ibcm_hca_info_t         *hcap;
2583 2561          void                    *results_p;
2584 2562          uint64_t                c_mask = 0;
2585 2563          ib_gid_t                *gid_ptr = NULL;
2586 2564          ib_gid_t                *sgids_p = NULL,  *dgids_p = NULL;
2587 2565          ib_gid_t                cur_dgid, cur_sgid;
2588 2566          ib_gid_t                new_dgid, new_sgid;
2589 2567          ibmf_saa_handle_t       saa_handle;
2590 2568          size_t                  length;
2591 2569          int                     i, j, template_len, rec_found;
2592 2570          uint_t                  snum = 0, dnum = 0, num_rec;
2593 2571          ibt_status_t            retval;
2594 2572          ib_mtu_t                prim_mtu;
2595 2573  
2596 2574          IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path(%p, %x, %p, %p)",
2597 2575              rc_chan, flags, attrp, api_p);
2598 2576  
2599 2577          /* validate channel */
2600 2578          if (IBCM_INVALID_CHANNEL(rc_chan)) {
2601 2579                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: invalid channel");
2602 2580                  return (IBT_CHAN_HDL_INVALID);
2603 2581          }
2604 2582  
2605 2583          if (api_p == NULL) {
2606 2584                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: invalid attribute: "
2607 2585                      " AltPathInfo can't be NULL");
2608 2586                  return (IBT_INVALID_PARAM);
2609 2587          }
2610 2588  
2611 2589          retval = ibt_query_qp(rc_chan, &qp_attr);
2612 2590          if (retval != IBT_SUCCESS) {
2613 2591                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: ibt_query_qp(%p) "
2614 2592                      "failed %d", rc_chan, retval);
2615 2593                  return (retval);
2616 2594          }
2617 2595  
2618 2596          if (qp_attr.qp_info.qp_trans != IBT_RC_SRV) {
2619 2597                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: "
2620 2598                      "Invalid Channel type: Applicable only to RC Channel");
2621 2599                  return (IBT_CHAN_SRV_TYPE_INVALID);
2622 2600          }
2623 2601  
2624 2602          cur_dgid =
2625 2603              qp_attr.qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dgid;
2626 2604          cur_sgid =
2627 2605              qp_attr.qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_sgid;
2628 2606          prim_mtu = qp_attr.qp_info.qp_transport.rc.rc_path_mtu;
2629 2607  
2630 2608          /* If optional attributes are specified, validate them. */
2631 2609          if (attrp) {
2632 2610                  new_dgid = attrp->apa_dgid;
2633 2611                  new_sgid = attrp->apa_sgid;
2634 2612          } else {
2635 2613                  new_dgid.gid_prefix = 0;
2636 2614                  new_dgid.gid_guid = 0;
2637 2615                  new_sgid.gid_prefix = 0;
2638 2616                  new_sgid.gid_guid = 0;
2639 2617          }
2640 2618  
2641 2619          if ((new_dgid.gid_prefix != 0) && (new_sgid.gid_prefix != 0) &&
2642 2620              (new_dgid.gid_prefix != new_sgid.gid_prefix)) {
2643 2621                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: Specified SGID's "
2644 2622                      "SNprefix (%llX) doesn't match with \n specified DGID's "
2645 2623                      "SNprefix: %llX", new_sgid.gid_prefix, new_dgid.gid_prefix);
2646 2624                  return (IBT_INVALID_PARAM);
2647 2625          }
2648 2626  
2649 2627          /* For the specified SGID, get HCA information. */
2650 2628          retval = ibtl_cm_get_hca_port(cur_sgid, 0, &c_hp);
2651 2629          if (retval != IBT_SUCCESS) {
2652 2630                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: "
2653 2631                      "Get HCA Port Failed: %d", retval);
2654 2632                  return (retval);
2655 2633          }
2656 2634  
2657 2635          hcap = ibcm_find_hca_entry(c_hp.hp_hca_guid);
2658 2636          if (hcap == NULL) {
2659 2637                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: NO HCA found");
2660 2638                  return (IBT_HCA_BUSY_DETACHING);
2661 2639          }
2662 2640  
2663 2641          /* Validate whether this HCA support APM */
2664 2642          if (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) {
2665 2643                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: "
2666 2644                      "HCA (%llX) - APM NOT SUPPORTED ", c_hp.hp_hca_guid);
2667 2645                  retval = IBT_APM_NOT_SUPPORTED;
2668 2646                  goto get_alt_path_done;
2669 2647          }
2670 2648  
2671 2649          /* Get Companion Port GID of the current Channel's SGID */
2672 2650          if ((new_sgid.gid_guid == 0) || ((new_sgid.gid_guid != 0) &&
2673 2651              (new_sgid.gid_guid != cur_sgid.gid_guid))) {
2674 2652                  IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: SRC: "
2675 2653                      "Get Companion PortGids for - %llX:%llX",
2676 2654                      cur_sgid.gid_prefix, cur_sgid.gid_guid);
2677 2655  
2678 2656                  retval = ibcm_get_comp_pgids(cur_sgid, new_sgid,
2679 2657                      c_hp.hp_hca_guid, &sgids_p, &snum);
2680 2658                  if (retval != IBT_SUCCESS)
2681 2659                          goto get_alt_path_done;
2682 2660          }
2683 2661  
2684 2662          /* Get Companion Port GID of the current Channel's DGID */
2685 2663          if ((new_dgid.gid_guid == 0) || ((new_dgid.gid_guid != 0) &&
2686 2664              (new_dgid.gid_guid != cur_dgid.gid_guid))) {
2687 2665  
2688 2666                  IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: DEST: "
2689 2667                      "Get Companion PortGids for - %llX:%llX",
2690 2668                      cur_dgid.gid_prefix, cur_dgid.gid_guid);
2691 2669  
2692 2670                  retval = ibcm_get_comp_pgids(cur_dgid, new_dgid, 0, &dgids_p,
2693 2671                      &dnum);
2694 2672                  if (retval != IBT_SUCCESS)
2695 2673                          goto get_alt_path_done;
2696 2674          }
2697 2675  
2698 2676          if ((new_dgid.gid_guid == 0) || (new_sgid.gid_guid == 0)) {
2699 2677                  if (new_sgid.gid_guid == 0) {
2700 2678                          for (i = 0; i < snum; i++) {
2701 2679                                  if (new_dgid.gid_guid == 0) {
2702 2680                                          for (j = 0; j < dnum; j++) {
2703 2681                                                  if (sgids_p[i].gid_prefix ==
2704 2682                                                      dgids_p[j].gid_prefix) {
2705 2683                                                          new_dgid = dgids_p[j];
2706 2684                                                          new_sgid = sgids_p[i];
2707 2685  
2708 2686                                                          goto get_alt_proceed;
2709 2687                                                  }
2710 2688                                          }
2711 2689                                          /*  Current DGID */
2712 2690                                          if (sgids_p[i].gid_prefix ==
2713 2691                                              cur_dgid.gid_prefix) {
2714 2692                                                  new_sgid = sgids_p[i];
2715 2693                                                  goto get_alt_proceed;
2716 2694                                          }
2717 2695                                  } else {
2718 2696                                          if (sgids_p[i].gid_prefix ==
2719 2697                                              new_dgid.gid_prefix) {
2720 2698                                                  new_sgid = sgids_p[i];
2721 2699                                                  goto get_alt_proceed;
2722 2700                                          }
2723 2701                                  }
2724 2702                          }
2725 2703                          /* Current SGID */
2726 2704                          if (new_dgid.gid_guid == 0) {
2727 2705                                  for (j = 0; j < dnum; j++) {
2728 2706                                          if (cur_sgid.gid_prefix ==
2729 2707                                              dgids_p[j].gid_prefix) {
2730 2708                                                  new_dgid = dgids_p[j];
2731 2709  
2732 2710                                                  goto get_alt_proceed;
2733 2711                                          }
2734 2712                                  }
2735 2713                          }
2736 2714                  } else if (new_dgid.gid_guid == 0) {
2737 2715                          for (i = 0; i < dnum; i++) {
2738 2716                                  if (dgids_p[i].gid_prefix ==
2739 2717                                      new_sgid.gid_prefix) {
2740 2718                                          new_dgid = dgids_p[i];
2741 2719                                          goto get_alt_proceed;
2742 2720                                  }
2743 2721                          }
2744 2722                          /* Current DGID */
2745 2723                          if (cur_dgid.gid_prefix == new_sgid.gid_prefix) {
2746 2724                                  goto get_alt_proceed;
2747 2725                          }
2748 2726                  }
2749 2727                  /*
2750 2728                   * hmm... No Companion Ports available.
2751 2729                   * so we will be using current or specified attributes only.
2752 2730                   */
2753 2731          }
2754 2732  
2755 2733  get_alt_proceed:
2756 2734  
2757 2735          if (new_sgid.gid_guid != 0) {
2758 2736                  retval = ibtl_cm_get_hca_port(new_sgid, 0, &n_hp);
2759 2737                  if (retval != IBT_SUCCESS) {
2760 2738                          IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: "
2761 2739                              "Get HCA Port Failed: %d", retval);
2762 2740                          goto get_alt_path_done;
  
    | 
      ↓ open down ↓ | 
    773 lines elided | 
    
      ↑ open up ↑ | 
  
2763 2741                  }
2764 2742          }
2765 2743  
2766 2744          /* Calculate the size for multi-path records template */
2767 2745          template_len = (2 * sizeof (ib_gid_t)) + sizeof (sa_multipath_record_t);
2768 2746  
2769 2747          mpr_req = kmem_zalloc(template_len, KM_SLEEP);
2770 2748  
2771 2749          ASSERT(mpr_req != NULL);
2772 2750  
2773      -        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req))
2774      -
2775 2751          gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
2776 2752              sizeof (sa_multipath_record_t));
2777 2753  
2778 2754          /* SGID */
2779 2755          if (new_sgid.gid_guid == 0)
2780 2756                  *gid_ptr = cur_sgid;
2781 2757          else
2782 2758                  *gid_ptr = new_sgid;
2783 2759  
2784 2760          IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Get Path Between "
2785 2761              " SGID : %llX:%llX", gid_ptr->gid_prefix, gid_ptr->gid_guid);
2786 2762  
2787 2763          gid_ptr++;
2788 2764  
2789 2765          /* DGID */
2790 2766          if (new_dgid.gid_guid == 0)
2791 2767                  *gid_ptr = cur_dgid;
2792 2768          else
2793 2769                  *gid_ptr = new_dgid;
2794 2770  
2795 2771          IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path:\t\t    DGID : %llX:%llX",
2796 2772              gid_ptr->gid_prefix, gid_ptr->gid_guid);
2797 2773  
2798 2774          mpr_req->SGIDCount = 1;
2799 2775          c_mask = SA_MPR_COMPMASK_SGIDCOUNT;
2800 2776  
2801 2777          mpr_req->DGIDCount = 1;
2802 2778          c_mask |= SA_MPR_COMPMASK_DGIDCOUNT;
2803 2779  
2804 2780          /* Is Flow Label Specified. */
2805 2781          if (attrp) {
2806 2782                  if (attrp->apa_flow) {
2807 2783                          mpr_req->FlowLabel = attrp->apa_flow;
2808 2784                          c_mask |= SA_MPR_COMPMASK_FLOWLABEL;
2809 2785                  }
2810 2786  
2811 2787                  /* Is HopLimit Specified. */
2812 2788                  if (flags & IBT_PATH_HOP) {
2813 2789                          mpr_req->HopLimit = attrp->apa_hop;
2814 2790                          c_mask |= SA_MPR_COMPMASK_HOPLIMIT;
2815 2791                  }
2816 2792  
2817 2793                  /* Is TClass Specified. */
2818 2794                  if (attrp->apa_tclass) {
2819 2795                          mpr_req->TClass = attrp->apa_tclass;
2820 2796                          c_mask |= SA_MPR_COMPMASK_TCLASS;
2821 2797                  }
2822 2798  
2823 2799                  /* Is SL specified. */
2824 2800                  if (attrp->apa_sl) {
2825 2801                          mpr_req->SL = attrp->apa_sl;
2826 2802                          c_mask |= SA_MPR_COMPMASK_SL;
2827 2803                  }
2828 2804  
2829 2805                  if (flags & IBT_PATH_PERF) {
2830 2806                          mpr_req->PacketLifeTimeSelector = IBT_BEST;
2831 2807                          mpr_req->RateSelector = IBT_BEST;
2832 2808  
2833 2809                          c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR |
2834 2810                              SA_MPR_COMPMASK_RATESELECTOR;
2835 2811                  } else {
2836 2812                          if (attrp->apa_pkt_lt.p_selector == IBT_BEST) {
2837 2813                                  mpr_req->PacketLifeTimeSelector = IBT_BEST;
2838 2814                                  c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR;
2839 2815                          }
2840 2816  
2841 2817                          if (attrp->apa_srate.r_selector == IBT_BEST) {
2842 2818                                  mpr_req->RateSelector = IBT_BEST;
2843 2819                                  c_mask |= SA_MPR_COMPMASK_RATESELECTOR;
2844 2820                          }
2845 2821                  }
2846 2822  
2847 2823                  /*
2848 2824                   * Honor individual selection of these attributes,
2849 2825                   * even if IBT_PATH_PERF is set.
2850 2826                   */
2851 2827                  /* Check out whether Packet Life Time is specified. */
2852 2828                  if (attrp->apa_pkt_lt.p_pkt_lt) {
2853 2829                          mpr_req->PacketLifeTime =
2854 2830                              ibt_usec2ib(attrp->apa_pkt_lt.p_pkt_lt);
2855 2831                          mpr_req->PacketLifeTimeSelector =
2856 2832                              attrp->apa_pkt_lt.p_selector;
2857 2833  
2858 2834                          c_mask |= SA_MPR_COMPMASK_PKTLT |
2859 2835                              SA_MPR_COMPMASK_PKTLTSELECTOR;
2860 2836                  }
2861 2837  
2862 2838                  /* Is SRATE specified. */
2863 2839                  if (attrp->apa_srate.r_srate) {
2864 2840                          mpr_req->Rate = attrp->apa_srate.r_srate;
2865 2841                          mpr_req->RateSelector = attrp->apa_srate.r_selector;
2866 2842  
2867 2843                          c_mask |= SA_MPR_COMPMASK_RATE |
2868 2844                              SA_MPR_COMPMASK_RATESELECTOR;
2869 2845                  }
2870 2846          }
2871 2847  
2872 2848          /* Alt PathMTU can be GT or EQU to current channel's Pri PathMTU */
2873 2849  
2874 2850          /* P_Key must be same as that of primary path */
2875 2851          retval = ibt_index2pkey_byguid(c_hp.hp_hca_guid, c_hp.hp_port,
2876 2852              qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix,
2877 2853              &mpr_req->P_Key);
2878 2854          if (retval != IBT_SUCCESS) {
  
    | 
      ↓ open down ↓ | 
    94 lines elided | 
    
      ↑ open up ↑ | 
  
2879 2855                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: Idx2Pkey Failed: %d",
2880 2856                      retval);
2881 2857                  goto get_alt_path_done;
2882 2858          }
2883 2859          c_mask |= SA_MPR_COMPMASK_PKEY;
2884 2860  
2885 2861          mpr_req->Reversible = 1;        /* We always get REVERSIBLE paths. */
2886 2862          mpr_req->IndependenceSelector = 1;
2887 2863          c_mask |= SA_MPR_COMPMASK_REVERSIBLE | SA_MPR_COMPMASK_INDEPSEL;
2888 2864  
2889      -        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req))
2890      -
2891 2865          IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: CMask: 0x%llX", c_mask);
2892 2866  
2893 2867          /* NOTE: We will **NOT** specify how many records we want. */
2894 2868  
2895 2869          IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Primary: MTU %d, PKey[%d]="
2896 2870              "0x%X\n\tSGID = %llX:%llX, DGID = %llX:%llX", prim_mtu,
2897 2871              qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, mpr_req->P_Key,
2898 2872              cur_sgid.gid_prefix, cur_sgid.gid_guid, cur_dgid.gid_prefix,
2899 2873              cur_dgid.gid_guid);
2900 2874  
2901 2875          /* Get SA Access Handle. */
2902 2876          if (new_sgid.gid_guid != 0)
2903 2877                  saa_handle = ibcm_get_saa_handle(hcap, n_hp.hp_port);
2904 2878          else
2905 2879                  saa_handle = ibcm_get_saa_handle(hcap, c_hp.hp_port);
2906 2880          if (saa_handle == NULL) {
2907 2881                  retval = IBT_HCA_PORT_NOT_ACTIVE;
2908 2882                  goto get_alt_path_done;
2909 2883          }
2910 2884  
2911 2885          /* Contact SA Access to retrieve Path Records. */
2912 2886          access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID;
2913 2887          access_args.sq_access_type = IBMF_SAA_RETRIEVE;
2914 2888          access_args.sq_component_mask = c_mask;
2915 2889          access_args.sq_template = mpr_req;
2916 2890          access_args.sq_template_length = sizeof (sa_multipath_record_t);
2917 2891          access_args.sq_callback = NULL;
2918 2892          access_args.sq_callback_arg = NULL;
2919 2893  
2920 2894          retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
2921 2895              &results_p);
2922 2896          if (retval != IBT_SUCCESS) {
2923 2897                  goto get_alt_path_done;
2924 2898          }
2925 2899  
2926 2900          num_rec = length / sizeof (sa_path_record_t);
2927 2901  
2928 2902          kmem_free(mpr_req, template_len);
2929 2903  
2930 2904          IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Found %d Paths", num_rec);
2931 2905  
2932 2906          rec_found = 0;
2933 2907          if ((results_p != NULL) && (num_rec > 0)) {
2934 2908                  /* Update the PathInfo with the response Path Records */
2935 2909                  pr_resp = (sa_path_record_t *)results_p;
2936 2910                  for (i = 0; i < num_rec; i++, pr_resp++) {
2937 2911                          if (prim_mtu > pr_resp->Mtu) {
2938 2912                                  IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: "
2939 2913                                      "Alt PathMTU(%d) must be GT or EQU to Pri "
2940 2914                                      "PathMTU(%d). Ignore this rec",
2941 2915                                      pr_resp->Mtu, prim_mtu);
2942 2916                                  continue;
2943 2917                          }
2944 2918  
2945 2919                          if ((new_sgid.gid_guid == 0) &&
2946 2920                              (new_dgid.gid_guid == 0)) {
2947 2921                                  /* Reject PathRec if it same as Primary Path. */
2948 2922                                  if (ibcm_compare_paths(pr_resp,
2949 2923                                      &qp_attr.qp_info.qp_transport.rc.rc_path,
2950 2924                                      &c_hp)) {
2951 2925                                          IBTF_DPRINTF_L3(cmlog,
2952 2926                                              "ibt_get_alt_path: PathRec obtained"
2953 2927                                              " is similar to Prim Path, ignore "
2954 2928                                              "this record");
2955 2929                                          continue;
2956 2930                                  }
2957 2931                          }
2958 2932  
2959 2933                          if (new_sgid.gid_guid == 0) {
  
    | 
      ↓ open down ↓ | 
    59 lines elided | 
    
      ↑ open up ↑ | 
  
2960 2934                                  retval = ibcm_update_cep_info(pr_resp, NULL,
2961 2935                                      &c_hp, &api_p->ap_alt_cep_path);
2962 2936                          } else {
2963 2937                                  retval = ibcm_update_cep_info(pr_resp, NULL,
2964 2938                                      &n_hp, &api_p->ap_alt_cep_path);
2965 2939                          }
2966 2940                          if (retval != IBT_SUCCESS)
2967 2941                                  continue;
2968 2942  
2969 2943                          /* Update some leftovers */
2970      -                        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*api_p))
2971      -
2972 2944                          api_p->ap_alt_pkt_lt = pr_resp->PacketLifeTime;
2973 2945  
2974      -                        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*api_p))
2975      -
2976 2946                          rec_found = 1;
2977 2947                          break;
2978 2948                  }
2979 2949                  kmem_free(results_p, length);
2980 2950          }
2981 2951  
2982 2952          if (rec_found == 0) {
2983 2953                  IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Alternate Path cannot"
2984 2954                      " be established");
2985 2955                  retval = IBT_PATH_RECORDS_NOT_FOUND;
2986 2956          } else
2987 2957                  retval = IBT_SUCCESS;
2988 2958  
2989 2959  get_alt_path_done:
2990 2960          if ((snum) && (sgids_p))
2991 2961                  kmem_free(sgids_p, snum * sizeof (ib_gid_t));
2992 2962  
2993 2963          if ((dnum) && (dgids_p))
2994 2964                  kmem_free(dgids_p, dnum * sizeof (ib_gid_t));
2995 2965  
2996 2966          ibcm_dec_hca_acc_cnt(hcap);
2997 2967  
2998 2968          IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Done (status %d).", retval);
2999 2969  
3000 2970          return (retval);
3001 2971  }
3002 2972  
3003 2973  
3004 2974  
3005 2975  /*
3006 2976   * IP Path API
3007 2977   */
3008 2978  
3009 2979  typedef struct ibcm_ip_path_tqargs_s {
3010 2980          ibt_ip_path_attr_t      attr;
3011 2981          ibt_path_info_t         *paths;
3012 2982          ibt_path_ip_src_t       *src_ip_p;
3013 2983          uint8_t                 *num_paths_p;
3014 2984          ibt_ip_path_handler_t   func;
3015 2985          void                    *arg;
3016 2986          ibt_path_flags_t        flags;
3017 2987          ibt_clnt_hdl_t          ibt_hdl;
3018 2988          kmutex_t                ip_lock;
3019 2989          kcondvar_t              ip_cv;
3020 2990          boolean_t               ip_done;
  
    | 
      ↓ open down ↓ | 
    35 lines elided | 
    
      ↑ open up ↑ | 
  
3021 2991          ibt_status_t            retval;
3022 2992          uint_t                  len;
3023 2993  } ibcm_ip_path_tqargs_t;
3024 2994  
3025 2995  /* Holds destination information needed to fill in ibt_path_info_t. */
3026 2996  typedef struct ibcm_ip_dinfo_s {
3027 2997          uint8_t         num_dest;
3028 2998          ib_gid_t        d_gid[1];
3029 2999  } ibcm_ip_dinfo_t;
3030 3000  
3031      -_NOTE(SCHEME_PROTECTS_DATA("Temporary path storage", ibcm_ip_dinfo_s))
3032      -
3033 3001  /* Prototype Declarations. */
3034 3002  static void ibcm_process_get_ip_paths(void *tq_arg);
3035 3003  static ibt_status_t ibcm_get_ip_spr(ibcm_ip_path_tqargs_t *,
3036 3004      ibtl_cm_port_list_t *, ibcm_ip_dinfo_t *, uint8_t *, ibt_path_info_t *);
3037 3005  static ibt_status_t ibcm_get_ip_mpr(ibcm_ip_path_tqargs_t *,
3038 3006      ibtl_cm_port_list_t *, ibcm_ip_dinfo_t *dinfo,
3039 3007      uint8_t *, ibt_path_info_t *);
3040 3008  
3041 3009  /*
3042 3010   * Perform SA Access to retrieve Path Records.
3043 3011   */
3044 3012  static ibt_status_t
3045 3013  ibcm_saa_ip_pr(ibcm_ip_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl,
3046 3014      ibcm_ip_dinfo_t *dinfo, uint8_t *max_count)
3047 3015  {
3048 3016          uint8_t         num_path = *max_count;
3049 3017          uint8_t         rec_found = 0;
3050 3018          ibt_status_t    retval = IBT_SUCCESS;
3051 3019          uint8_t         i, j;
3052 3020  
3053 3021          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr(%p, %p, %p, 0x%X, %d)",
3054 3022              p_arg, sl, dinfo, p_arg->flags, *max_count);
3055 3023  
3056 3024          if ((dinfo->num_dest == 0) || (num_path == 0) || (sl == NULL)) {
3057 3025                  IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr: Invalid Counters");
3058 3026                  return (IBT_INVALID_PARAM);
3059 3027          }
3060 3028  
3061 3029          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr: MultiSM=%X, #SRC=%d, "
3062 3030              "#Dest=%d, #Path %d", sl->p_multi, sl->p_count, dinfo->num_dest,
3063 3031              num_path);
3064 3032  
3065 3033          if ((sl->p_multi != IBTL_CM_SIMPLE_SETUP) ||
3066 3034              ((dinfo->num_dest == 1) && (sl->p_count == 1))) {
3067 3035                  /*
3068 3036                   * Use SinglePathRec if we are dealing w/ MultiSM or
3069 3037                   * request is for one SGID to one DGID.
3070 3038                   */
3071 3039                  retval = ibcm_get_ip_spr(p_arg, sl, dinfo,
3072 3040                      &num_path, &p_arg->paths[rec_found]);
3073 3041          } else {
3074 3042                  /* MultiPathRec will be used for other queries. */
3075 3043                  retval = ibcm_get_ip_mpr(p_arg, sl, dinfo,
3076 3044                      &num_path, &p_arg->paths[rec_found]);
3077 3045          }
3078 3046          if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA))
3079 3047                  IBTF_DPRINTF_L2(cmlog, "ibcm_saa_ip_pr: "
3080 3048                      "Failed to get PathRec: Status %d", retval);
3081 3049          else
3082 3050                  rec_found += num_path;
3083 3051  
3084 3052          if (rec_found == 0)  {
3085 3053                  if (retval == IBT_SUCCESS)
3086 3054                          retval = IBT_PATH_RECORDS_NOT_FOUND;
3087 3055          } else if (rec_found != *max_count)
3088 3056                  retval = IBT_INSUFF_DATA;
3089 3057          else if (rec_found != 0)
3090 3058                  retval = IBT_SUCCESS;
3091 3059  
3092 3060          if ((p_arg->src_ip_p != NULL) && (rec_found != 0)) {
3093 3061                  for (i = 0; i < rec_found; i++) {
3094 3062                          for (j = 0; j < sl->p_count; j++) {
3095 3063                                  if (sl[j].p_sgid.gid_guid == p_arg->paths[i].
3096 3064                                      pi_prim_cep_path.cep_adds_vect.
3097 3065                                      av_sgid.gid_guid) {
3098 3066                                          bcopy(&sl[j].p_src_ip,
3099 3067                                              &p_arg->src_ip_p[i].ip_primary,
3100 3068                                              sizeof (ibt_ip_addr_t));
3101 3069                                  }
3102 3070                                  /* Is Alt Path present */
3103 3071                                  if (p_arg->paths[i].pi_alt_cep_path.
3104 3072                                      cep_hca_port_num) {
3105 3073                                          if (sl[j].p_sgid.gid_guid ==
3106 3074                                              p_arg->paths[i].pi_alt_cep_path.
3107 3075                                              cep_adds_vect.av_sgid.gid_guid) {
3108 3076                                                  bcopy(&sl[j].p_src_ip,
3109 3077                                                      &p_arg->src_ip_p[i].
3110 3078                                                      ip_alternate,
3111 3079                                                      sizeof (ibt_ip_addr_t));
3112 3080                                          }
3113 3081                                  }
3114 3082                          }
3115 3083                  }
3116 3084          }
3117 3085          IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr: done. Status = %d, "
3118 3086              "Found %d/%d Paths", retval, rec_found, *max_count);
3119 3087  
3120 3088          *max_count = rec_found; /* Update the return count. */
3121 3089  
3122 3090          return (retval);
3123 3091  }
3124 3092  
3125 3093  static ibt_status_t
3126 3094  ibcm_ip_update_pri(sa_path_record_t *pr_resp, ibtl_cm_port_list_t *sl,
3127 3095      ibt_path_info_t *paths)
3128 3096  {
3129 3097          ibt_status_t    retval = IBT_SUCCESS;
3130 3098          int             s;
3131 3099  
3132 3100          retval = ibcm_update_cep_info(pr_resp, sl, NULL,
3133 3101              &paths->pi_prim_cep_path);
3134 3102          if (retval != IBT_SUCCESS)
3135 3103                  return (retval);
3136 3104  
3137 3105          /* Update some leftovers */
3138 3106          paths->pi_prim_pkt_lt = pr_resp->PacketLifeTime;
3139 3107          paths->pi_path_mtu = pr_resp->Mtu;
3140 3108  
3141 3109          for (s = 0; s < sl->p_count; s++) {
3142 3110                  if (pr_resp->SGID.gid_guid == sl[s].p_sgid.gid_guid)
3143 3111                          paths->pi_hca_guid = sl[s].p_hca_guid;
3144 3112          }
3145 3113  
3146 3114          /* Set Alternate Path to invalid state. */
3147 3115          paths->pi_alt_cep_path.cep_hca_port_num = 0;
3148 3116          paths->pi_alt_cep_path.cep_adds_vect.av_dlid = 0;
3149 3117  
3150 3118          IBTF_DPRINTF_L5(cmlog, "ibcm_ip_update_pri: Path HCA GUID 0x%llX",
3151 3119              paths->pi_hca_guid);
3152 3120  
3153 3121          return (retval);
3154 3122  }
3155 3123  
3156 3124  
3157 3125  static ibt_status_t
3158 3126  ibcm_get_ip_spr(ibcm_ip_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl,
3159 3127      ibcm_ip_dinfo_t *dinfo, uint8_t *num_path, ibt_path_info_t *paths)
3160 3128  {
3161 3129          sa_path_record_t        pathrec_req;
3162 3130          sa_path_record_t        *pr_resp;
3163 3131          ibmf_saa_access_args_t  access_args;
3164 3132          uint64_t                c_mask = 0;
3165 3133          void                    *results_p;
3166 3134          uint8_t                 num_rec;
3167 3135          size_t                  length;
3168 3136          ibt_status_t            retval;
3169 3137          int                     i, j, k;
3170 3138          uint8_t                 found, p_fnd;
3171 3139          ibt_ip_path_attr_t      *attrp = &p_arg->attr;
3172 3140          ibmf_saa_handle_t       saa_handle;
3173 3141  
3174 3142          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr(%p, %p, %p, %d)",
3175 3143              p_arg, sl, dinfo, *num_path);
3176 3144  
3177 3145          bzero(&pathrec_req, sizeof (sa_path_record_t));
3178 3146  
3179 3147          /* Is Flow Label Specified. */
3180 3148          if (attrp->ipa_flow) {
3181 3149                  pathrec_req.FlowLabel = attrp->ipa_flow;
3182 3150                  c_mask |= SA_PR_COMPMASK_FLOWLABEL;
3183 3151          }
3184 3152  
3185 3153          /* Is HopLimit Specified. */
3186 3154          if (p_arg->flags & IBT_PATH_HOP) {
3187 3155                  pathrec_req.HopLimit = attrp->ipa_hop;
3188 3156                  c_mask |= SA_PR_COMPMASK_HOPLIMIT;
3189 3157          }
3190 3158  
3191 3159          /* Is TClass Specified. */
3192 3160          if (attrp->ipa_tclass) {
3193 3161                  pathrec_req.TClass = attrp->ipa_tclass;
3194 3162                  c_mask |= SA_PR_COMPMASK_TCLASS;
3195 3163          }
3196 3164  
3197 3165          /* Is SL specified. */
3198 3166          if (attrp->ipa_sl) {
3199 3167                  pathrec_req.SL = attrp->ipa_sl;
3200 3168                  c_mask |= SA_PR_COMPMASK_SL;
3201 3169          }
3202 3170  
3203 3171          /* If IBT_PATH_PERF is set, then mark all selectors to BEST. */
3204 3172          if (p_arg->flags & IBT_PATH_PERF) {
3205 3173                  pathrec_req.PacketLifeTimeSelector = IBT_BEST;
3206 3174                  pathrec_req.MtuSelector = IBT_BEST;
3207 3175                  pathrec_req.RateSelector = IBT_BEST;
3208 3176  
3209 3177                  c_mask |= SA_PR_COMPMASK_PKTLTSELECTOR |
3210 3178                      SA_PR_COMPMASK_RATESELECTOR | SA_PR_COMPMASK_MTUSELECTOR;
3211 3179          } else {
3212 3180                  if (attrp->ipa_pkt_lt.p_selector == IBT_BEST) {
3213 3181                          pathrec_req.PacketLifeTimeSelector = IBT_BEST;
3214 3182                          c_mask |= SA_PR_COMPMASK_PKTLTSELECTOR;
3215 3183                  }
3216 3184  
3217 3185                  if (attrp->ipa_srate.r_selector == IBT_BEST) {
3218 3186                          pathrec_req.RateSelector = IBT_BEST;
3219 3187                          c_mask |= SA_PR_COMPMASK_RATESELECTOR;
3220 3188                  }
3221 3189  
3222 3190                  if (attrp->ipa_mtu.r_selector == IBT_BEST) {
3223 3191                          pathrec_req.MtuSelector = IBT_BEST;
3224 3192                          c_mask |= SA_PR_COMPMASK_MTUSELECTOR;
3225 3193                  }
3226 3194          }
3227 3195  
3228 3196          /*
3229 3197           * Honor individual selection of these attributes,
3230 3198           * even if IBT_PATH_PERF is set.
3231 3199           */
3232 3200          /* Check out whether Packet Life Time is specified. */
3233 3201          if (attrp->ipa_pkt_lt.p_pkt_lt) {
3234 3202                  pathrec_req.PacketLifeTime =
3235 3203                      ibt_usec2ib(attrp->ipa_pkt_lt.p_pkt_lt);
3236 3204                  pathrec_req.PacketLifeTimeSelector =
3237 3205                      attrp->ipa_pkt_lt.p_selector;
3238 3206  
3239 3207                  c_mask |= SA_PR_COMPMASK_PKTLT | SA_PR_COMPMASK_PKTLTSELECTOR;
3240 3208          }
3241 3209  
3242 3210          /* Is SRATE specified. */
3243 3211          if (attrp->ipa_srate.r_srate) {
3244 3212                  pathrec_req.Rate = attrp->ipa_srate.r_srate;
3245 3213                  pathrec_req.RateSelector = attrp->ipa_srate.r_selector;
3246 3214  
3247 3215                  c_mask |= SA_PR_COMPMASK_RATE | SA_PR_COMPMASK_RATESELECTOR;
3248 3216          }
3249 3217  
3250 3218          /* Is MTU specified. */
3251 3219          if (attrp->ipa_mtu.r_mtu) {
3252 3220                  pathrec_req.Mtu = attrp->ipa_mtu.r_mtu;
3253 3221                  pathrec_req.MtuSelector = attrp->ipa_mtu.r_selector;
3254 3222  
3255 3223                  c_mask |= SA_PR_COMPMASK_MTU | SA_PR_COMPMASK_MTUSELECTOR;
3256 3224          }
3257 3225  
3258 3226          /* We always get REVERSIBLE paths. */
3259 3227          pathrec_req.Reversible = 1;
3260 3228          c_mask |= SA_PR_COMPMASK_REVERSIBLE;
3261 3229  
3262 3230          pathrec_req.NumbPath = *num_path;
3263 3231          c_mask |= SA_PR_COMPMASK_NUMBPATH;
3264 3232  
3265 3233          p_fnd = found = 0;
3266 3234  
3267 3235          for (i = 0; i < sl->p_count; i++) {
3268 3236                  /* SGID */
3269 3237                  pathrec_req.SGID = sl[i].p_sgid;
3270 3238                  c_mask |= SA_PR_COMPMASK_SGID;
3271 3239                  saa_handle = sl[i].p_saa_hdl;
3272 3240  
3273 3241                  for (k = 0; k < dinfo->num_dest; k++) {
3274 3242                          if (pathrec_req.SGID.gid_prefix !=
3275 3243                              dinfo->d_gid[k].gid_prefix) {
3276 3244                                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: "
3277 3245                                      "SGID_pfx=%llX DGID_pfx=%llX doesn't match",
3278 3246                                      pathrec_req.SGID.gid_prefix,
3279 3247                                      dinfo->d_gid[k].gid_prefix);
3280 3248                                  continue;
3281 3249                          }
3282 3250  
3283 3251                          pathrec_req.DGID = dinfo->d_gid[k];
3284 3252                          c_mask |= SA_PR_COMPMASK_DGID;
3285 3253  
3286 3254                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: "
3287 3255                              "Get %d Path(s) between\n SGID %llX:%llX "
3288 3256                              "DGID %llX:%llX", pathrec_req.NumbPath,
3289 3257                              pathrec_req.SGID.gid_prefix,
3290 3258                              pathrec_req.SGID.gid_guid,
3291 3259                              pathrec_req.DGID.gid_prefix,
3292 3260                              pathrec_req.DGID.gid_guid);
3293 3261  
3294 3262                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: CMask=0x%llX, "
3295 3263                              "PKey=0x%X", c_mask, pathrec_req.P_Key);
3296 3264  
3297 3265                          /* Contact SA Access to retrieve Path Records. */
3298 3266                          access_args.sq_attr_id = SA_PATHRECORD_ATTRID;
3299 3267                          access_args.sq_template = &pathrec_req;
3300 3268                          access_args.sq_access_type = IBMF_SAA_RETRIEVE;
3301 3269                          access_args.sq_template_length =
3302 3270                              sizeof (sa_path_record_t);
3303 3271                          access_args.sq_component_mask = c_mask;
3304 3272                          access_args.sq_callback = NULL;
3305 3273                          access_args.sq_callback_arg = NULL;
3306 3274  
3307 3275                          retval = ibcm_contact_sa_access(saa_handle,
3308 3276                              &access_args, &length, &results_p);
3309 3277                          if (retval != IBT_SUCCESS) {
3310 3278                                  *num_path = 0;
3311 3279                                  return (retval);
3312 3280                          }
3313 3281  
3314 3282                          num_rec = length / sizeof (sa_path_record_t);
3315 3283  
3316 3284                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: "
3317 3285                              "FOUND %d/%d path requested", num_rec, *num_path);
3318 3286  
3319 3287                          if ((results_p == NULL) || (num_rec == 0))
3320 3288                                  continue;
3321 3289  
3322 3290                          /* Update the PathInfo from the response. */
3323 3291                          pr_resp = (sa_path_record_t *)results_p;
3324 3292                          for (j = 0; j < num_rec; j++, pr_resp++) {
3325 3293                                  if ((p_fnd != 0) &&
3326 3294                                      (p_arg->flags & IBT_PATH_APM)) {
3327 3295                                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr"
3328 3296                                              ": Fill Alternate Path");
3329 3297                                          retval = ibcm_update_cep_info(pr_resp,
3330 3298                                              sl, NULL,
3331 3299                                              &paths[found - 1].pi_alt_cep_path);
3332 3300                                          if (retval != IBT_SUCCESS)
3333 3301                                                  continue;
3334 3302  
3335 3303                                          /* Update some leftovers */
3336 3304                                          paths[found - 1].pi_alt_pkt_lt =
3337 3305                                              pr_resp->PacketLifeTime;
3338 3306                                          p_fnd = 0;
3339 3307                                  } else {
3340 3308                                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr"
3341 3309                                              ": Fill Primary Path");
3342 3310  
3343 3311                                          if (found == *num_path)
3344 3312                                                  break;
3345 3313  
3346 3314                                          retval = ibcm_ip_update_pri(pr_resp, sl,
3347 3315                                              &paths[found]);
3348 3316                                          if (retval != IBT_SUCCESS)
3349 3317                                                  continue;
3350 3318                                          p_fnd = 1;
3351 3319                                          found++;
3352 3320                                  }
3353 3321  
3354 3322                          }
3355 3323                          /* Deallocate the memory for results_p. */
3356 3324                          kmem_free(results_p, length);
3357 3325                  }
3358 3326          }
3359 3327  
3360 3328          if (found == 0)
3361 3329                  retval = IBT_PATH_RECORDS_NOT_FOUND;
3362 3330          else if (found != *num_path)
3363 3331                  retval = IBT_INSUFF_DATA;
3364 3332          else
3365 3333                  retval = IBT_SUCCESS;
3366 3334  
3367 3335          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: done. Status %d, "
3368 3336              "Found %d/%d Paths", retval, found, *num_path);
3369 3337  
3370 3338          *num_path = found;
3371 3339  
3372 3340          return (retval);
3373 3341  }
3374 3342  
3375 3343  
3376 3344  static ibt_status_t
3377 3345  ibcm_get_ip_mpr(ibcm_ip_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl,
3378 3346      ibcm_ip_dinfo_t *dinfo, uint8_t *num_path, ibt_path_info_t *paths)
3379 3347  {
3380 3348          sa_multipath_record_t   *mpr_req;
3381 3349          sa_path_record_t        *pr_resp;
3382 3350          ibmf_saa_access_args_t  access_args;
3383 3351          void                    *results_p;
3384 3352          uint64_t                c_mask = 0;
3385 3353          ib_gid_t                *gid_ptr, *gid_s_ptr;
3386 3354          size_t                  length;
3387 3355          int                     template_len;
3388 3356          uint8_t                 found, num_rec;
3389 3357          int                     i;
3390 3358          ibt_status_t            retval;
3391 3359          uint8_t                 sgid_cnt, dgid_cnt;
3392 3360          ibt_ip_path_attr_t      *attrp = &p_arg->attr;
3393 3361  
3394 3362          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr(%p, %p, %p, %d)",
3395 3363              attrp, sl, dinfo, *num_path);
3396 3364  
3397 3365          dgid_cnt = dinfo->num_dest;
3398 3366          sgid_cnt = sl->p_count;
3399 3367  
3400 3368          if ((sgid_cnt == 0) || (dgid_cnt == 0)) {
3401 3369                  IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_mpr: sgid_cnt(%d) or"
3402 3370                      " dgid_cnt(%d) is zero", sgid_cnt, dgid_cnt);
3403 3371                  return (IBT_INVALID_PARAM);
3404 3372          }
3405 3373  
3406 3374          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: Get %d records between "
3407 3375              "%d Src(s) <=> %d Dest(s)", *num_path, sgid_cnt, dgid_cnt);
3408 3376  
3409 3377          /*
3410 3378           * Calculate the size for multi-path records template, which includes
3411 3379           * constant portion of the multipath record, plus variable size for
3412 3380           * SGID (sgid_cnt) and DGID (dgid_cnt).
3413 3381           */
3414 3382          template_len = ((dgid_cnt + sgid_cnt) * sizeof (ib_gid_t)) +
3415 3383              sizeof (sa_multipath_record_t);
3416 3384  
3417 3385          mpr_req = kmem_zalloc(template_len, KM_SLEEP);
3418 3386  
3419 3387          ASSERT(mpr_req != NULL);
3420 3388  
3421 3389          gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
3422 3390              sizeof (sa_multipath_record_t));
3423 3391  
3424 3392          /* Get the starting pointer where GIDs are stored. */
3425 3393          gid_s_ptr = gid_ptr;
3426 3394  
  
    | 
      ↓ open down ↓ | 
    384 lines elided | 
    
      ↑ open up ↑ | 
  
3427 3395          /* SGID */
3428 3396          for (i = 0; i < sgid_cnt; i++) {
3429 3397                  *gid_ptr = sl[i].p_sgid;
3430 3398  
3431 3399                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: SGID[%d] = %llX:%llX",
3432 3400                      i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
3433 3401  
3434 3402                  gid_ptr++;
3435 3403          }
3436 3404  
3437      -        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req))
3438      -
3439 3405          mpr_req->SGIDCount = sgid_cnt;
3440 3406          c_mask = SA_MPR_COMPMASK_SGIDCOUNT;
3441 3407  
3442 3408          /* DGIDs */
3443 3409          for (i = 0; i < dgid_cnt; i++) {
3444 3410                  *gid_ptr = dinfo->d_gid[i];
3445 3411  
3446 3412                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: DGID[%d] = "
3447 3413                      "%llX:%llX", i, gid_ptr->gid_prefix, gid_ptr->gid_guid);
3448 3414                  gid_ptr++;
3449 3415          }
3450 3416  
3451 3417          mpr_req->DGIDCount = dgid_cnt;
3452 3418          c_mask |= SA_MPR_COMPMASK_DGIDCOUNT;
3453 3419  
3454 3420          /* Is Flow Label Specified. */
3455 3421          if (attrp->ipa_flow) {
3456 3422                  mpr_req->FlowLabel = attrp->ipa_flow;
3457 3423                  c_mask |= SA_MPR_COMPMASK_FLOWLABEL;
3458 3424          }
3459 3425  
3460 3426          /* Is HopLimit Specified. */
3461 3427          if (p_arg->flags & IBT_PATH_HOP) {
3462 3428                  mpr_req->HopLimit = attrp->ipa_hop;
3463 3429                  c_mask |= SA_MPR_COMPMASK_HOPLIMIT;
3464 3430          }
3465 3431  
3466 3432          /* Is TClass Specified. */
3467 3433          if (attrp->ipa_tclass) {
3468 3434                  mpr_req->TClass = attrp->ipa_tclass;
3469 3435                  c_mask |= SA_MPR_COMPMASK_TCLASS;
3470 3436          }
3471 3437  
3472 3438          /* Is SL specified. */
3473 3439          if (attrp->ipa_sl) {
3474 3440                  mpr_req->SL = attrp->ipa_sl;
3475 3441                  c_mask |= SA_MPR_COMPMASK_SL;
3476 3442          }
3477 3443  
3478 3444          if (p_arg->flags & IBT_PATH_PERF) {
3479 3445                  mpr_req->PacketLifeTimeSelector = IBT_BEST;
3480 3446                  mpr_req->RateSelector = IBT_BEST;
3481 3447                  mpr_req->MtuSelector = IBT_BEST;
3482 3448  
3483 3449                  c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR |
3484 3450                      SA_MPR_COMPMASK_RATESELECTOR | SA_MPR_COMPMASK_MTUSELECTOR;
3485 3451          } else {
3486 3452                  if (attrp->ipa_pkt_lt.p_selector == IBT_BEST) {
3487 3453                          mpr_req->PacketLifeTimeSelector = IBT_BEST;
3488 3454                          c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR;
3489 3455                  }
3490 3456  
3491 3457                  if (attrp->ipa_srate.r_selector == IBT_BEST) {
3492 3458                          mpr_req->RateSelector = IBT_BEST;
3493 3459                          c_mask |= SA_MPR_COMPMASK_RATESELECTOR;
3494 3460                  }
3495 3461  
3496 3462                  if (attrp->ipa_mtu.r_selector == IBT_BEST) {
3497 3463                          mpr_req->MtuSelector = IBT_BEST;
3498 3464                          c_mask |= SA_MPR_COMPMASK_MTUSELECTOR;
3499 3465                  }
3500 3466          }
3501 3467  
3502 3468          /*
3503 3469           * Honor individual selection of these attributes,
3504 3470           * even if IBT_PATH_PERF is set.
3505 3471           */
3506 3472          /* Check out whether Packet Life Time is specified. */
3507 3473          if (attrp->ipa_pkt_lt.p_pkt_lt) {
3508 3474                  mpr_req->PacketLifeTime =
3509 3475                      ibt_usec2ib(attrp->ipa_pkt_lt.p_pkt_lt);
3510 3476                  mpr_req->PacketLifeTimeSelector =
3511 3477                      attrp->ipa_pkt_lt.p_selector;
3512 3478  
3513 3479                  c_mask |= SA_MPR_COMPMASK_PKTLT |
3514 3480                      SA_MPR_COMPMASK_PKTLTSELECTOR;
3515 3481          }
3516 3482  
3517 3483          /* Is SRATE specified. */
3518 3484          if (attrp->ipa_srate.r_srate) {
3519 3485                  mpr_req->Rate = attrp->ipa_srate.r_srate;
3520 3486                  mpr_req->RateSelector = attrp->ipa_srate.r_selector;
3521 3487  
3522 3488                  c_mask |= SA_MPR_COMPMASK_RATE |
3523 3489                      SA_MPR_COMPMASK_RATESELECTOR;
3524 3490          }
3525 3491  
3526 3492          /* Is MTU specified. */
3527 3493          if (attrp->ipa_mtu.r_mtu) {
3528 3494                  mpr_req->Mtu = attrp->ipa_mtu.r_mtu;
3529 3495                  mpr_req->MtuSelector = attrp->ipa_mtu.r_selector;
3530 3496  
3531 3497                  c_mask |= SA_MPR_COMPMASK_MTU |
3532 3498                      SA_MPR_COMPMASK_MTUSELECTOR;
3533 3499          }
3534 3500  
3535 3501          /* We always get REVERSIBLE paths. */
  
    | 
      ↓ open down ↓ | 
    87 lines elided | 
    
      ↑ open up ↑ | 
  
3536 3502          mpr_req->Reversible = 1;
3537 3503          c_mask |= SA_MPR_COMPMASK_REVERSIBLE;
3538 3504  
3539 3505          if (p_arg->flags & IBT_PATH_AVAIL) {
3540 3506                  mpr_req->IndependenceSelector = 1;
3541 3507                  c_mask |= SA_MPR_COMPMASK_INDEPSEL;
3542 3508          }
3543 3509  
3544 3510          /* we will not specify how many records we want. */
3545 3511  
3546      -        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req))
3547      -
3548 3512          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: CMask: %llX Pkey: %X",
3549 3513              c_mask, mpr_req->P_Key);
3550 3514  
3551 3515          /* Contact SA Access to retrieve Path Records. */
3552 3516          access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID;
3553 3517          access_args.sq_access_type = IBMF_SAA_RETRIEVE;
3554 3518          access_args.sq_component_mask = c_mask;
3555 3519          access_args.sq_template = mpr_req;
3556 3520          access_args.sq_template_length = sizeof (sa_multipath_record_t);
3557 3521          access_args.sq_callback = NULL;
3558 3522          access_args.sq_callback_arg = NULL;
3559 3523  
3560 3524          retval = ibcm_contact_sa_access(sl->p_saa_hdl, &access_args, &length,
3561 3525              &results_p);
3562 3526          if (retval != IBT_SUCCESS) {
3563 3527                  *num_path = 0;  /* Update the return count. */
3564 3528                  kmem_free(mpr_req, template_len);
3565 3529                  return (retval);
3566 3530          }
3567 3531  
3568 3532          num_rec = length / sizeof (sa_path_record_t);
3569 3533  
3570 3534          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: Found %d Paths", num_rec);
3571 3535  
3572 3536          found = 0;
3573 3537          if ((results_p != NULL) && (num_rec > 0)) {
3574 3538                  /* Update the PathInfo with the response Path Records */
3575 3539                  pr_resp = (sa_path_record_t *)results_p;
3576 3540  
3577 3541                  for (i = 0; i < num_rec; i++) {
3578 3542                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: "
3579 3543                              "P[%d]: SG %llX, DG %llX", i,
3580 3544                              pr_resp[i].SGID.gid_guid, pr_resp[i].DGID.gid_guid);
3581 3545                  }
3582 3546  
3583 3547                  if (p_arg->flags & IBT_PATH_APM) {
3584 3548                          sa_path_record_t *p_resp = NULL, *a_resp = NULL;
3585 3549                          int             p_found = 0, a_found = 0;
3586 3550                          ib_gid_t        p_sg, a_sg, p_dg, a_dg;
3587 3551                          int             s_spec;
3588 3552  
3589 3553                          s_spec =
3590 3554                              p_arg->attr.ipa_src_ip.family != AF_UNSPEC ? 1 : 0;
3591 3555  
3592 3556                          p_sg = gid_s_ptr[0];
3593 3557                          if (sgid_cnt > 1)
3594 3558                                  a_sg = gid_s_ptr[1];
3595 3559                          else
3596 3560                                  a_sg = p_sg;
3597 3561  
3598 3562                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: P_SG: %llX, "
3599 3563                              "A_SG: %llX", p_sg.gid_guid, a_sg.gid_guid);
3600 3564  
3601 3565                          p_dg = gid_s_ptr[sgid_cnt];
3602 3566                          if (dgid_cnt > 1)
3603 3567                                  a_dg = gid_s_ptr[sgid_cnt + 1];
3604 3568                          else
3605 3569                                  a_dg = p_dg;
3606 3570  
3607 3571                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: P_DG: %llX, "
3608 3572                              "A_DG: %llX", p_dg.gid_guid, a_dg.gid_guid);
3609 3573  
3610 3574                          /*
3611 3575                           * If SGID and/or DGID is specified by user, make sure
3612 3576                           * he gets his primary-path on those node points.
3613 3577                           */
3614 3578                          for (i = 0; i < num_rec; i++, pr_resp++) {
3615 3579                                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: "
3616 3580                                      "PF %d, AF %d,\n\t\t P[%d] = SG: %llX, "
3617 3581                                      "DG: %llX", p_found, a_found, i,
3618 3582                                      pr_resp->SGID.gid_guid,
3619 3583                                      pr_resp->DGID.gid_guid);
3620 3584  
3621 3585                                  if ((!p_found) &&
3622 3586                                      (p_dg.gid_guid == pr_resp->DGID.gid_guid)) {
3623 3587                                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr"
3624 3588                                              ": Pri DGID Match.. ");
3625 3589                                          if ((s_spec == 0) || (p_sg.gid_guid ==
3626 3590                                              pr_resp->SGID.gid_guid)) {
3627 3591                                                  p_found = 1;
3628 3592                                                  p_resp = pr_resp;
3629 3593                                                  IBTF_DPRINTF_L3(cmlog,
3630 3594                                                      "ibcm_get_ip_mpr: "
3631 3595                                                      "Primary Path Found");
3632 3596  
3633 3597                                                  if (a_found)
3634 3598                                                          break;
3635 3599                                                  else
3636 3600                                                          continue;
3637 3601                                          }
3638 3602                                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr"
3639 3603                                              ": Pri SGID Don't Match.. ");
3640 3604                                  }
3641 3605  
3642 3606                                  if ((!a_found) &&
3643 3607                                      (a_dg.gid_guid == pr_resp->DGID.gid_guid)) {
3644 3608                                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr"
3645 3609                                              ": Alt DGID Match.. ");
3646 3610                                          if ((s_spec == 0) || (a_sg.gid_guid ==
3647 3611                                              pr_resp->SGID.gid_guid)) {
3648 3612                                                  a_found = 1;
3649 3613                                                  a_resp = pr_resp;
3650 3614  
3651 3615                                                  IBTF_DPRINTF_L3(cmlog,
3652 3616                                                      "ibcm_get_ip_mpr:"
3653 3617                                                      "Alternate Path Found ");
3654 3618  
3655 3619                                                  if (p_found)
3656 3620                                                          break;
3657 3621                                                  else
3658 3622                                                          continue;
3659 3623                                          }
3660 3624                                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr"
3661 3625                                              ": Alt SGID Don't Match.. ");
3662 3626                                  }
3663 3627                          }
3664 3628  
3665 3629                          if ((p_found == 0) && (a_found == 0)) {
3666 3630                                  IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_mpr: Path "
3667 3631                                      "to desired node points NOT Available.");
3668 3632                                  retval = IBT_PATH_RECORDS_NOT_FOUND;
3669 3633                                  goto get_ip_mpr_end;
3670 3634                          }
3671 3635  
3672 3636                          if ((p_resp == NULL) && (a_resp != NULL)) {
3673 3637                                  p_resp = a_resp;
3674 3638                                  a_resp = NULL;
3675 3639                          }
3676 3640  
3677 3641                          /* Fill in Primary Path */
3678 3642                          retval = ibcm_ip_update_pri(p_resp, sl, &paths[found]);
3679 3643                          if (retval != IBT_SUCCESS)
3680 3644                                  goto get_ip_mpr_end;
3681 3645  
3682 3646                          /* Fill in Alternate Path */
3683 3647                          if (a_resp != NULL) {
3684 3648                                  /* a_resp will point to AltPathInfo buffer. */
3685 3649                                  retval = ibcm_update_cep_info(a_resp, sl,
3686 3650                                      NULL, &paths[found].pi_alt_cep_path);
3687 3651                                  if (retval != IBT_SUCCESS)
3688 3652                                          goto get_ip_mpr_end;
3689 3653  
3690 3654                                  /* Update some leftovers */
3691 3655                                  paths[found].pi_alt_pkt_lt =
3692 3656                                      a_resp->PacketLifeTime;
3693 3657                          } else {
3694 3658                                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: "
3695 3659                                      "Alternate Path NOT Available.");
3696 3660                                  retval = IBT_INSUFF_DATA;
3697 3661                          }
3698 3662                          found++;
3699 3663                  } else {        /* If NOT APM */
3700 3664                          for (i = 0; i < num_rec; i++, pr_resp++) {
3701 3665                                  IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: "
3702 3666                                      "DGID(%llX)", pr_resp->DGID.gid_guid);
3703 3667  
3704 3668                                  /* Fill in Primary Path */
3705 3669                                  retval = ibcm_ip_update_pri(pr_resp, sl,
3706 3670                                      &paths[found]);
3707 3671                                  if (retval != IBT_SUCCESS)
3708 3672                                          continue;
3709 3673  
3710 3674                                  if (++found == *num_path)
3711 3675                                          break;
3712 3676                          }
3713 3677                  }
3714 3678  get_ip_mpr_end:
3715 3679                  kmem_free(results_p, length);
3716 3680          }
3717 3681          kmem_free(mpr_req, template_len);
3718 3682  
3719 3683          if (found == 0)
3720 3684                  retval = IBT_PATH_RECORDS_NOT_FOUND;
3721 3685          else if (found != *num_path)
3722 3686                  retval = IBT_INSUFF_DATA;
3723 3687          else
3724 3688                  retval = IBT_SUCCESS;
3725 3689  
3726 3690          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: Done (status %d). "
3727 3691              "Found %d/%d Paths", retval, found, *num_path);
3728 3692  
3729 3693          *num_path = found;      /* Update the return count. */
3730 3694  
3731 3695          return (retval);
3732 3696  }
3733 3697  
3734 3698  
3735 3699  static void
3736 3700  ibcm_process_get_ip_paths(void *tq_arg)
3737 3701  {
3738 3702          ibcm_ip_path_tqargs_t   *p_arg = (ibcm_ip_path_tqargs_t *)tq_arg;
3739 3703          ibcm_ip_dinfo_t         *dinfo = NULL;
3740 3704          int                     len = 0;
3741 3705          uint8_t                 max_paths, num_path;
3742 3706          ib_gid_t                *d_gids_p = NULL;
3743 3707          ib_gid_t                sgid, dgid1, dgid2;
3744 3708          ibt_status_t            retval = IBT_SUCCESS;
3745 3709          ibtl_cm_port_list_t     *sl = NULL;
3746 3710          uint_t                  dnum = 0;
3747 3711          uint8_t                 i;
3748 3712          ibcm_hca_info_t         *hcap;
3749 3713          ibmf_saa_handle_t       saa_handle;
3750 3714          ibt_path_attr_t         attr;
3751 3715          ibt_ip_addr_t           src_ip_p;
3752 3716  
3753 3717          IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths(%p, 0x%X) ",
3754 3718              p_arg, p_arg->flags);
3755 3719  
3756 3720          max_paths = num_path = p_arg->attr.ipa_max_paths;
3757 3721  
3758 3722          /*
3759 3723           * Prepare the Source and Destination GID list based on the input
3760 3724           * attributes.  We contact ARP module to perform IP to MAC
3761 3725           * i.e. GID conversion.  We use this GID for path look-up.
3762 3726           *
3763 3727           * If APM is requested and if multiple Dest IPs are specified, check
3764 3728           * out whether they are companion to each other.  But, if only one
3765 3729           * Dest IP is specified, then it is beyond our scope to verify that
3766 3730           * the companion port GID obtained has IP-Service enabled.
3767 3731           */
3768 3732          dgid1.gid_prefix = dgid1.gid_guid = 0;
3769 3733          sgid.gid_prefix = sgid.gid_guid = 0;
3770 3734  
3771 3735          retval = ibcm_arp_get_ibaddr(p_arg->attr.ipa_zoneid,
3772 3736              p_arg->attr.ipa_src_ip, p_arg->attr.ipa_dst_ip[0], &sgid,
3773 3737              &dgid1, &src_ip_p);
3774 3738          if (retval) {
3775 3739                  IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
3776 3740                      "ibcm_arp_get_ibaddr() failed: %d", retval);
3777 3741                  goto ippath_error;
3778 3742          }
3779 3743  
3780 3744          bzero(&attr, sizeof (ibt_path_attr_t));
3781 3745          attr.pa_hca_guid = p_arg->attr.ipa_hca_guid;
3782 3746          attr.pa_hca_port_num = p_arg->attr.ipa_hca_port_num;
3783 3747          attr.pa_sgid = sgid;
3784 3748          bcopy(&p_arg->attr.ipa_mtu, &attr.pa_mtu, sizeof (ibt_mtu_req_t));
3785 3749          bcopy(&p_arg->attr.ipa_srate, &attr.pa_srate, sizeof (ibt_srate_req_t));
3786 3750          bcopy(&p_arg->attr.ipa_pkt_lt, &attr.pa_pkt_lt,
3787 3751              sizeof (ibt_pkt_lt_req_t));
3788 3752          retval = ibtl_cm_get_active_plist(&attr, p_arg->flags, &sl);
3789 3753          if (retval == IBT_SUCCESS) {
3790 3754                  bcopy(&src_ip_p, &sl->p_src_ip, sizeof (ibt_ip_addr_t));
3791 3755          } else {
3792 3756                  IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
3793 3757                      "ibtl_cm_get_active_plist: Failed %d", retval);
3794 3758                  goto ippath_error;
3795 3759          }
3796 3760  
3797 3761          IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_ip_paths: SGID %llX:%llX, "
3798 3762              "DGID0: %llX:%llX", sl->p_sgid.gid_prefix, sl->p_sgid.gid_guid,
3799 3763              dgid1.gid_prefix, dgid1.gid_guid);
3800 3764  
3801 3765          len = p_arg->attr.ipa_ndst - 1;
3802 3766          len = (len * sizeof (ib_gid_t)) + sizeof (ibcm_ip_dinfo_t);
3803 3767          dinfo = kmem_zalloc(len, KM_SLEEP);
3804 3768  
3805 3769          dinfo->d_gid[0] = dgid1;
3806 3770  
3807 3771          i = 1;
3808 3772          if (p_arg->attr.ipa_ndst > 1) {
3809 3773                  /* Get DGID for all specified Dest IP Addr */
3810 3774                  for (; i < p_arg->attr.ipa_ndst; i++) {
3811 3775                          retval = ibcm_arp_get_ibaddr(p_arg->attr.ipa_zoneid,
3812 3776                              p_arg->attr.ipa_src_ip, p_arg->attr.ipa_dst_ip[i],
3813 3777                              NULL, &dgid2, NULL);
3814 3778                          if (retval) {
3815 3779                                  IBTF_DPRINTF_L2(cmlog,
3816 3780                                      "ibcm_process_get_ip_paths: "
3817 3781                                      "ibcm_arp_get_ibaddr failed: %d", retval);
3818 3782                                  goto ippath_error2;
3819 3783                          }
3820 3784                          dinfo->d_gid[i] = dgid2;
3821 3785  
3822 3786                          IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_ip_paths: "
3823 3787                              "DGID%d: %llX:%llX", i, dgid2.gid_prefix,
3824 3788                              dgid2.gid_guid);
3825 3789                  }
3826 3790  
3827 3791                  if (p_arg->flags & IBT_PATH_APM) {
3828 3792                          dgid2 = dinfo->d_gid[1];
3829 3793  
3830 3794                          retval = ibcm_get_comp_pgids(dgid1, dgid2, 0,
3831 3795                              &d_gids_p, &dnum);
3832 3796                          if ((retval != IBT_SUCCESS) &&
3833 3797                              (retval != IBT_GIDS_NOT_FOUND)) {
3834 3798                                  IBTF_DPRINTF_L2(cmlog,
3835 3799                                      "ibcm_process_get_ip_paths: "
3836 3800                                      "Invalid DGIDs specified w/ APM Flag");
3837 3801                                  goto ippath_error2;
3838 3802                          }
3839 3803                          IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths: "
3840 3804                              "Found %d Comp DGID", dnum);
3841 3805  
  
    | 
      ↓ open down ↓ | 
    284 lines elided | 
    
      ↑ open up ↑ | 
  
3842 3806                          if (dnum) {
3843 3807                                  dinfo->d_gid[i] = d_gids_p[0];
3844 3808                                  i++;
3845 3809                          }
3846 3810                  }
3847 3811          }
3848 3812  
3849 3813          /* "i" will get us num_dest count. */
3850 3814          dinfo->num_dest = i;
3851 3815  
3852      -        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*p_arg))
3853      -
3854 3816          /*
3855 3817           * IBTF allocates memory for path_info & src_ip in case of
3856 3818           * Async Get IP Paths
3857 3819           */
3858 3820          if (p_arg->func) {   /* Do these only for Async Get Paths */
3859 3821                  p_arg->paths = kmem_zalloc(sizeof (ibt_path_info_t) * max_paths,
3860 3822                      KM_SLEEP);
3861 3823                  if (p_arg->src_ip_p == NULL)
3862 3824                          p_arg->src_ip_p = kmem_zalloc(
3863 3825                              sizeof (ibt_path_ip_src_t) * max_paths, KM_SLEEP);
3864 3826          }
3865 3827  
3866      -        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*p_arg))
3867      -
3868 3828          IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths: HCA (%llX, %d)",
3869 3829              sl->p_hca_guid, sl->p_port_num);
3870 3830  
3871 3831          hcap = ibcm_find_hca_entry(sl->p_hca_guid);
3872 3832          if (hcap == NULL) {
3873 3833                  IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
3874 3834                      "NO HCA found");
3875 3835                  retval = IBT_HCA_BUSY_DETACHING;
3876 3836                  goto ippath_error2;
3877 3837          }
3878 3838  
3879 3839          /* Get SA Access Handle. */
3880 3840          for (i = 0; i < sl->p_count; i++) {
3881 3841                  if (i == 0) {
3882 3842                          /* Validate whether this HCA supports APM */
3883 3843                          if ((p_arg->flags & IBT_PATH_APM) &&
3884 3844                              (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG))) {
3885 3845                                  IBTF_DPRINTF_L2(cmlog,
3886 3846                                      "ibcm_process_get_ip_paths: HCA (%llX): "
3887 3847                                      "APM NOT SUPPORTED", sl[i].p_hca_guid);
3888 3848                                  retval = IBT_APM_NOT_SUPPORTED;
3889 3849                                  goto ippath_error3;
3890 3850                          }
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
3891 3851                  }
3892 3852  
3893 3853                  saa_handle = ibcm_get_saa_handle(hcap, sl[i].p_port_num);
3894 3854                  if (saa_handle == NULL) {
3895 3855                          IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: "
3896 3856                              "SAA HDL NULL, HCA (%llX:%d) NOT ACTIVE",
3897 3857                              sl[i].p_hca_guid, sl[i].p_port_num);
3898 3858                          retval = IBT_HCA_PORT_NOT_ACTIVE;
3899 3859                          goto ippath_error3;
3900 3860                  }
3901      -                _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sl))
3902 3861                  sl[i].p_saa_hdl = saa_handle;
3903      -                _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sl))
3904 3862          }
3905 3863  
3906 3864          /* Get Path Records. */
3907 3865          retval = ibcm_saa_ip_pr(p_arg, sl, dinfo, &num_path);
3908 3866  
3909 3867  ippath_error3:
3910 3868          ibcm_dec_hca_acc_cnt(hcap);
3911 3869  
3912 3870  ippath_error2:
3913 3871          if (dinfo && len)
3914 3872                  kmem_free(dinfo, len);
3915 3873  
3916 3874  ippath_error1:
3917 3875          if (sl)
3918 3876                  ibtl_cm_free_active_plist(sl);
3919 3877  
3920 3878  ippath_error:
  
    | 
      ↓ open down ↓ | 
    7 lines elided | 
    
      ↑ open up ↑ | 
  
3921 3879          if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA))
3922 3880                  num_path = 0;
3923 3881  
3924 3882          if (p_arg->num_paths_p != NULL)
3925 3883                  *p_arg->num_paths_p = num_path;
3926 3884  
3927 3885          if (p_arg->func) {   /* Do these only for Async Get Paths */
3928 3886                  ibt_path_info_t *tmp_path_p;
3929 3887                  ibt_path_ip_src_t       *tmp_src_ip_p;
3930 3888  
3931      -                _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*p_arg))
3932 3889                  p_arg->retval = retval;
3933      -                _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*p_arg))
3934 3890  
3935 3891                  if (retval == IBT_INSUFF_DATA) {
3936 3892                          /*
3937 3893                           * We allocated earlier memory based on "max_paths",
3938 3894                           * but we got lesser path-records, so re-adjust that
3939 3895                           * buffer so that caller can free the correct memory.
3940 3896                           */
3941 3897                          tmp_path_p = kmem_alloc(
3942 3898                              sizeof (ibt_path_info_t) * num_path, KM_SLEEP);
3943 3899  
3944 3900                          bcopy(p_arg->paths, tmp_path_p,
3945 3901                              num_path * sizeof (ibt_path_info_t));
3946 3902  
3947 3903                          kmem_free(p_arg->paths,
3948 3904                              sizeof (ibt_path_info_t) * max_paths);
3949 3905  
3950 3906                          tmp_src_ip_p = kmem_alloc(
3951 3907                              sizeof (ibt_path_ip_src_t) * num_path, KM_SLEEP);
3952 3908  
3953 3909                          bcopy(p_arg->src_ip_p, tmp_src_ip_p,
3954 3910                              num_path * sizeof (ibt_path_ip_src_t));
3955 3911  
3956 3912                          kmem_free(p_arg->src_ip_p,
3957 3913                              sizeof (ibt_path_ip_src_t) * max_paths);
3958 3914                  } else if (retval != IBT_SUCCESS) {
3959 3915                          if (p_arg->paths)
3960 3916                                  kmem_free(p_arg->paths,
3961 3917                                      sizeof (ibt_path_info_t) * max_paths);
3962 3918                          if (p_arg->src_ip_p)
3963 3919                                  kmem_free(p_arg->src_ip_p,
3964 3920                                      sizeof (ibt_path_ip_src_t) * max_paths);
3965 3921                          tmp_path_p = NULL;
3966 3922                          tmp_src_ip_p = NULL;
3967 3923                  } else {
3968 3924                          tmp_path_p = p_arg->paths;
3969 3925                          tmp_src_ip_p = p_arg->src_ip_p;
3970 3926                  }
3971 3927                  (*(p_arg->func))(p_arg->arg, retval, tmp_path_p, num_path,
3972 3928                      tmp_src_ip_p);
3973 3929  
3974 3930                  len = p_arg->len;
3975 3931                  if (p_arg && len)
3976 3932                          kmem_free(p_arg, len);
3977 3933          } else {
3978 3934                  mutex_enter(&p_arg->ip_lock);
3979 3935                  p_arg->ip_done = B_TRUE;
3980 3936                  p_arg->retval = retval;
3981 3937                  cv_signal(&p_arg->ip_cv);
3982 3938                  mutex_exit(&p_arg->ip_lock);
3983 3939          }
3984 3940  
3985 3941          IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: done: status %d, "
3986 3942              "Found %d/%d Path Records", retval, num_path, max_paths);
3987 3943  }
3988 3944  
3989 3945  
3990 3946  static ibt_status_t
3991 3947  ibcm_val_ipattr(ibt_ip_path_attr_t *attrp, ibt_path_flags_t flags)
3992 3948  {
3993 3949          uint_t                  i;
3994 3950  
3995 3951          if (attrp == NULL) {
3996 3952                  IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: IP Path Attr is NULL");
3997 3953                  return (IBT_INVALID_PARAM);
3998 3954          }
3999 3955  
4000 3956          IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: Inputs are: HCA %llX:%d, "
4001 3957              "Maxpath= %d, \n Flags= 0x%X, #Dest %d", attrp->ipa_hca_guid,
4002 3958              attrp->ipa_hca_port_num, attrp->ipa_max_paths, flags,
4003 3959              attrp->ipa_ndst);
4004 3960  
4005 3961          /*
4006 3962           * Validate Path Flags.
4007 3963           * IBT_PATH_AVAIL & IBT_PATH_PERF are mutually exclusive.
4008 3964           */
4009 3965          if ((flags & IBT_PATH_AVAIL) && (flags & IBT_PATH_PERF)) {
4010 3966                  IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: Invalid Flags: 0x%X,"
4011 3967                      "\n\t AVAIL and PERF flags specified together", flags);
4012 3968                  return (IBT_INVALID_PARAM);
4013 3969          }
4014 3970  
4015 3971          /*
4016 3972           * Validate number of records requested.
4017 3973           *
4018 3974           * Max_paths of "0" is invalid.
4019 3975           * Max_paths <= IBT_MAX_SPECIAL_PATHS, if AVAIL or PERF is set.
4020 3976           */
4021 3977          if (attrp->ipa_max_paths == 0) {
4022 3978                  IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: Invalid max_paths %d",
4023 3979                      attrp->ipa_max_paths);
4024 3980                  return (IBT_INVALID_PARAM);
4025 3981          }
4026 3982  
4027 3983          if ((flags & (IBT_PATH_AVAIL | IBT_PATH_PERF)) &&
4028 3984              (attrp->ipa_max_paths > IBT_MAX_SPECIAL_PATHS)) {
4029 3985                  IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: MaxPaths that can be "
4030 3986                      "requested is <%d> \n when IBT_PATH_AVAIL or IBT_PATH_PERF"
4031 3987                      " flag is specified.", IBT_MAX_SPECIAL_PATHS);
4032 3988                  return (IBT_INVALID_PARAM);
4033 3989          }
4034 3990  
4035 3991          /* Only 2 destinations can be specified w/ APM flag. */
4036 3992          if ((flags & IBT_PATH_APM) && (attrp->ipa_ndst > 2)) {
4037 3993                  IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: Max #Dest is 2, with "
4038 3994                      "APM flag");
4039 3995                  return (IBT_INVALID_PARAM);
4040 3996          }
4041 3997  
4042 3998          /* Validate the destination info */
4043 3999          if ((attrp->ipa_ndst == 0) || (attrp->ipa_ndst == NULL)) {
4044 4000                  IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: DstIP Not provided "
4045 4001                      "dst_ip %p, ndst %d", attrp->ipa_dst_ip, attrp->ipa_ndst);
4046 4002                  return (IBT_INVALID_PARAM);
4047 4003          }
4048 4004  
4049 4005          /* Basic validation of Source IPADDR (if provided). */
4050 4006          IBCM_PRINT_IP("ibcm_val_ipattr SrcIP", &attrp->ipa_src_ip);
4051 4007          if ((attrp->ipa_src_ip.family == AF_INET) &&
4052 4008              (attrp->ipa_src_ip.un.ip4addr == htonl(INADDR_LOOPBACK) ||
4053 4009              attrp->ipa_src_ip.un.ip4addr == INADDR_ANY)) {
4054 4010                  IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: SrcIP specified is "
4055 4011                      "LOOPBACK/ZEROs: NOT SUPPORTED");
4056 4012                  return (IBT_NOT_SUPPORTED);
4057 4013          } else if ((attrp->ipa_src_ip.family == AF_INET6) &&
4058 4014              (IN6_IS_ADDR_UNSPECIFIED(&attrp->ipa_src_ip.un.ip6addr) ||
4059 4015              IN6_IS_ADDR_LOOPBACK(&attrp->ipa_src_ip.un.ip6addr))) {
4060 4016                  IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: SrcIP specified is "
4061 4017                      "LOOPBACK/ZEROs: NOT SUPPORTED");
4062 4018                  return (IBT_NOT_SUPPORTED);
4063 4019          }
4064 4020  
4065 4021          if (ibcm_ip6_linklocal_addr_ok &&
4066 4022              (attrp->ipa_src_ip.family == AF_INET6) &&
4067 4023              (IN6_IS_ADDR_LINKLOCAL(&attrp->ipa_src_ip.un.ip6addr))) {
4068 4024                  IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: SrcIP specified is "
4069 4025                      "Link Local Address: NOT SUPPORTED");
4070 4026                  return (IBT_NOT_SUPPORTED);
4071 4027          }
4072 4028  
4073 4029          /* Basic validation of Dest IPADDR. */
4074 4030          for (i = 0; i < attrp->ipa_ndst; i++) {
4075 4031                  ibt_ip_addr_t   dst_ip = attrp->ipa_dst_ip[i];
4076 4032  
4077 4033                  IBCM_PRINT_IP("ibcm_val_ipattr DstIP", &dst_ip);
4078 4034  
4079 4035                  if (dst_ip.family == AF_UNSPEC) {
4080 4036                          IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: ERROR: "
4081 4037                              "Invalid DstIP specified");
4082 4038                          return (IBT_INVALID_PARAM);
4083 4039                  } else if ((dst_ip.family == AF_INET) &&
4084 4040                      (dst_ip.un.ip4addr == htonl(INADDR_LOOPBACK) ||
4085 4041                      dst_ip.un.ip4addr == INADDR_ANY)) {
4086 4042                          IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: DstIP "
4087 4043                              "specified is LOOPBACK/ZEROs: NOT SUPPORTED");
4088 4044                          return (IBT_NOT_SUPPORTED);
4089 4045                  } else if ((dst_ip.family == AF_INET6) &&
4090 4046                      (IN6_IS_ADDR_UNSPECIFIED(&dst_ip.un.ip6addr) ||
4091 4047                      IN6_IS_ADDR_LOOPBACK(&dst_ip.un.ip6addr))) {
4092 4048                          IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: DstIP "
4093 4049                              "specified is LOOPBACK/ZEROs: NOT SUPPORTED");
4094 4050                          return (IBT_NOT_SUPPORTED);
4095 4051                  }
4096 4052  
4097 4053                  /*
4098 4054                   * If SrcIP is specified, make sure that SrcIP and DstIP
4099 4055                   * belong to same family.
4100 4056                   */
4101 4057                  if ((attrp->ipa_src_ip.family != AF_UNSPEC) &&
4102 4058                      (attrp->ipa_src_ip.family != dst_ip.family)) {
4103 4059                          IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: ERROR: "
4104 4060                              "Specified SrcIP (%d) and DstIP(%d) family diffs.",
4105 4061                              attrp->ipa_src_ip.family, dst_ip.family);
4106 4062                          return (IBT_INVALID_PARAM);
4107 4063                  }
4108 4064          }
4109 4065  
4110 4066          return (IBT_SUCCESS);
4111 4067  }
4112 4068  
4113 4069  
4114 4070  static ibt_status_t
4115 4071  ibcm_get_ip_path(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags,
4116 4072      ibt_ip_path_attr_t *attrp, ibt_path_info_t *paths, uint8_t *num_path_p,
4117 4073      ibt_path_ip_src_t *src_ip_p, ibt_ip_path_handler_t func, void  *arg)
4118 4074  {
4119 4075          ibcm_ip_path_tqargs_t   *path_tq;
4120 4076          int             sleep_flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP);
4121 4077          uint_t          len, ret;
4122 4078          ibt_status_t    retval;
4123 4079  
4124 4080          retval = ibcm_val_ipattr(attrp, flags);
4125 4081          if (retval != IBT_SUCCESS)
4126 4082                  return (retval);
  
    | 
      ↓ open down ↓ | 
    183 lines elided | 
    
      ↑ open up ↑ | 
  
4127 4083  
4128 4084          len = (attrp->ipa_ndst * sizeof (ibt_ip_addr_t)) +
4129 4085              sizeof (ibcm_ip_path_tqargs_t);
4130 4086          path_tq = kmem_zalloc(len, sleep_flag);
4131 4087          if (path_tq == NULL) {
4132 4088                  IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_path: "
4133 4089                      "Unable to allocate memory for local usage.");
4134 4090                  return (IBT_INSUFF_KERNEL_RESOURCE);
4135 4091          }
4136 4092  
4137      -        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*path_tq))
4138 4093          bcopy(attrp, &path_tq->attr, sizeof (ibt_ip_path_attr_t));
4139 4094  
4140 4095          path_tq->attr.ipa_dst_ip = (ibt_ip_addr_t *)(((uchar_t *)path_tq) +
4141 4096              sizeof (ibcm_ip_path_tqargs_t));
4142 4097          bcopy(attrp->ipa_dst_ip, path_tq->attr.ipa_dst_ip,
4143 4098              sizeof (ibt_ip_addr_t) * attrp->ipa_ndst);
4144 4099  
4145 4100          /* Ignore IBT_PATH_AVAIL flag, if only one path is requested. */
4146 4101          if ((flags & IBT_PATH_AVAIL) && (attrp->ipa_max_paths == 1)) {
4147 4102                  flags &= ~IBT_PATH_AVAIL;
4148 4103  
4149 4104                  IBTF_DPRINTF_L4(cmlog, "ibcm_get_ip_path: Ignoring "
4150 4105                      "IBT_PATH_AVAIL flag, as only ONE path info is requested.");
4151 4106          }
4152 4107  
4153 4108          path_tq->flags = flags;
4154 4109          path_tq->ibt_hdl = ibt_hdl;
4155 4110          path_tq->paths = paths;
4156 4111          path_tq->src_ip_p = src_ip_p;
  
    | 
      ↓ open down ↓ | 
    9 lines elided | 
    
      ↑ open up ↑ | 
  
4157 4112          path_tq->num_paths_p = num_path_p;
4158 4113          path_tq->func = func;
4159 4114          path_tq->arg = arg;
4160 4115          path_tq->len = len;
4161 4116          path_tq->ip_done = B_FALSE;
4162 4117          if (func == NULL) {     /* Blocking */
4163 4118                  mutex_init(&path_tq->ip_lock, NULL, MUTEX_DEFAULT, NULL);
4164 4119                  cv_init(&path_tq->ip_cv, NULL, CV_DRIVER, NULL);
4165 4120          }
4166 4121  
4167      -        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*path_tq))
4168      -
4169 4122          sleep_flag = ((func == NULL) ? TQ_SLEEP : TQ_NOSLEEP);
4170 4123          ret = taskq_dispatch(ibcm_taskq, ibcm_process_get_ip_paths, path_tq,
4171 4124              sleep_flag);
4172 4125          if (ret == 0) {
4173 4126                  IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_path: Failed to dispatch "
4174 4127                      "the TaskQ");
4175 4128                  if (func == NULL) {             /* Blocking */
4176 4129                          cv_destroy(&path_tq->ip_cv);
4177 4130                          mutex_destroy(&path_tq->ip_lock);
4178 4131                  }
4179 4132                  kmem_free(path_tq, len);
4180 4133                  retval = IBT_INSUFF_KERNEL_RESOURCE;
4181 4134          } else {
4182 4135                  if (func != NULL) {             /* Non-Blocking */
4183 4136                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_path: NonBlocking");
4184 4137                          retval = IBT_SUCCESS;
4185 4138                  } else {                /* Blocking */
4186 4139                          IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_path: Blocking");
4187 4140                          mutex_enter(&path_tq->ip_lock);
4188 4141                          while (path_tq->ip_done != B_TRUE)
4189 4142                                  cv_wait(&path_tq->ip_cv, &path_tq->ip_lock);
4190 4143                          retval = path_tq->retval;
4191 4144                          mutex_exit(&path_tq->ip_lock);
4192 4145                          cv_destroy(&path_tq->ip_cv);
4193 4146                          mutex_destroy(&path_tq->ip_lock);
4194 4147                          kmem_free(path_tq, len);
4195 4148                  }
4196 4149          }
4197 4150  
4198 4151          return (retval);
4199 4152  }
4200 4153  
4201 4154  
4202 4155  ibt_status_t
4203 4156  ibt_aget_ip_paths(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags,
4204 4157      ibt_ip_path_attr_t *attrp, ibt_ip_path_handler_t func, void  *arg)
4205 4158  {
4206 4159          IBTF_DPRINTF_L3(cmlog, "ibt_aget_ip_paths(%p (%s), 0x%X, %p, %p, %p)",
4207 4160              ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), flags, attrp, func, arg);
4208 4161  
4209 4162          if (func == NULL) {
4210 4163                  IBTF_DPRINTF_L2(cmlog, "ibt_aget_ip_paths: Function Pointer is "
4211 4164                      "NULL - ERROR ");
4212 4165                  return (IBT_INVALID_PARAM);
4213 4166          }
4214 4167  
4215 4168          /* path info will be allocated in ibcm_process_get_ip_paths() */
4216 4169          return (ibcm_get_ip_path(ibt_hdl, flags, attrp, NULL, NULL,
4217 4170              NULL, func, arg));
4218 4171  }
4219 4172  
4220 4173  
4221 4174  ibt_status_t
4222 4175  ibt_get_ip_paths(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags,
4223 4176      ibt_ip_path_attr_t *attrp, ibt_path_info_t *paths, uint8_t *num_paths_p,
4224 4177      ibt_path_ip_src_t *src_ip_p)
4225 4178  {
4226 4179          IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_paths(%p(%s), 0x%X, %p, %p, %p, %p)",
4227 4180              ibt_hdl, ibtl_cm_get_clnt_name(ibt_hdl), flags, attrp, paths,
4228 4181              num_paths_p, src_ip_p);
4229 4182  
4230 4183          if (paths == NULL) {
4231 4184                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_paths: Path Info Pointer is "
4232 4185                      "NULL - ERROR ");
4233 4186                  return (IBT_INVALID_PARAM);
4234 4187          }
4235 4188  
4236 4189          if (num_paths_p != NULL)
4237 4190                  *num_paths_p = 0;
4238 4191  
4239 4192          return (ibcm_get_ip_path(ibt_hdl, flags, attrp, paths, num_paths_p,
4240 4193              src_ip_p, NULL, NULL));
4241 4194  }
4242 4195  
4243 4196  
4244 4197  ibt_status_t
4245 4198  ibt_get_ip_alt_path(ibt_channel_hdl_t rc_chan, ibt_path_flags_t flags,
4246 4199      ibt_alt_ip_path_attr_t *attrp, ibt_alt_path_info_t *api_p)
4247 4200  {
4248 4201          sa_multipath_record_t   *mpr_req;
4249 4202          sa_path_record_t        *pr_resp;
4250 4203          ibmf_saa_access_args_t  access_args;
4251 4204          ibt_qp_query_attr_t     qp_attr;
4252 4205          ibtl_cm_hca_port_t      c_hp, n_hp;
4253 4206          ibcm_hca_info_t         *hcap;
4254 4207          void                    *results_p;
4255 4208          uint64_t                c_mask = 0;
4256 4209          ib_gid_t                *gid_ptr = NULL;
4257 4210          ib_gid_t                *sgids_p = NULL,  *dgids_p = NULL;
4258 4211          ib_gid_t                cur_dgid, cur_sgid;
4259 4212          ib_gid_t                new_dgid, new_sgid;
4260 4213          ibmf_saa_handle_t       saa_handle;
4261 4214          size_t                  length;
4262 4215          int                     i, j, template_len, rec_found;
4263 4216          uint_t                  snum = 0, dnum = 0, num_rec;
4264 4217          ibt_status_t            retval;
4265 4218          ib_mtu_t                prim_mtu;
4266 4219  
4267 4220          IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path(%p, %x, %p, %p)",
4268 4221              rc_chan, flags, attrp, api_p);
4269 4222  
4270 4223          /* validate channel */
4271 4224          if (IBCM_INVALID_CHANNEL(rc_chan)) {
4272 4225                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: invalid channel");
4273 4226                  return (IBT_CHAN_HDL_INVALID);
4274 4227          }
4275 4228  
4276 4229          if (api_p == NULL) {
4277 4230                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: invalid attribute:"
4278 4231                      " AltPathInfo can't be NULL");
4279 4232                  return (IBT_INVALID_PARAM);
4280 4233          }
4281 4234  
4282 4235          retval = ibt_query_qp(rc_chan, &qp_attr);
4283 4236          if (retval != IBT_SUCCESS) {
4284 4237                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: ibt_query_qp(%p) "
4285 4238                      "failed %d", rc_chan, retval);
4286 4239                  return (retval);
4287 4240          }
4288 4241  
4289 4242          if (qp_attr.qp_info.qp_trans != IBT_RC_SRV) {
4290 4243                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: "
4291 4244                      "Invalid Channel type: Applicable only to RC Channel");
4292 4245                  return (IBT_CHAN_SRV_TYPE_INVALID);
4293 4246          }
4294 4247  
4295 4248          cur_dgid =
4296 4249              qp_attr.qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dgid;
4297 4250          cur_sgid =
4298 4251              qp_attr.qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_sgid;
4299 4252          prim_mtu = qp_attr.qp_info.qp_transport.rc.rc_path_mtu;
4300 4253  
4301 4254          /* If optional attributes are specified, validate them. */
4302 4255          if (attrp) {
4303 4256                  /* Get SGID and DGID for the specified input ip-addr */
4304 4257                  retval = ibcm_arp_get_ibaddr(attrp->apa_zoneid,
4305 4258                      attrp->apa_src_ip, attrp->apa_dst_ip, &new_sgid,
4306 4259                      &new_dgid, NULL);
4307 4260                  if (retval) {
4308 4261                          IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: "
4309 4262                              "ibcm_arp_get_ibaddr() failed: %d", retval);
4310 4263                          return (retval);
4311 4264                  }
4312 4265          } else {
4313 4266                  new_dgid.gid_prefix = 0;
4314 4267                  new_dgid.gid_guid = 0;
4315 4268                  new_sgid.gid_prefix = 0;
4316 4269                  new_sgid.gid_guid = 0;
4317 4270          }
4318 4271  
4319 4272          if ((new_dgid.gid_prefix != 0) && (new_sgid.gid_prefix != 0) &&
4320 4273              (new_dgid.gid_prefix != new_sgid.gid_prefix)) {
4321 4274                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: Specified SGID's "
4322 4275                      "SNprefix (%llX) doesn't match with \n specified DGID's "
4323 4276                      "SNprefix: %llX", new_sgid.gid_prefix, new_dgid.gid_prefix);
4324 4277                  return (IBT_INVALID_PARAM);
4325 4278          }
4326 4279  
4327 4280          /* For the specified SGID, get HCA information. */
4328 4281          retval = ibtl_cm_get_hca_port(cur_sgid, 0, &c_hp);
4329 4282          if (retval != IBT_SUCCESS) {
4330 4283                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: "
4331 4284                      "Get HCA Port Failed: %d", retval);
4332 4285                  return (retval);
4333 4286          }
4334 4287  
4335 4288          hcap = ibcm_find_hca_entry(c_hp.hp_hca_guid);
4336 4289          if (hcap == NULL) {
4337 4290                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: NO HCA found");
4338 4291                  return (IBT_HCA_BUSY_DETACHING);
4339 4292          }
4340 4293  
4341 4294          /* Validate whether this HCA support APM */
4342 4295          if (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) {
4343 4296                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: "
4344 4297                      "HCA (%llX) - APM NOT SUPPORTED ", c_hp.hp_hca_guid);
4345 4298                  retval = IBT_APM_NOT_SUPPORTED;
4346 4299                  goto get_ip_alt_path_done;
4347 4300          }
4348 4301  
4349 4302          /* Get Companion Port GID of the current Channel's SGID */
4350 4303          if ((new_sgid.gid_guid == 0) || ((new_sgid.gid_guid != 0) &&
4351 4304              (new_sgid.gid_guid != cur_sgid.gid_guid))) {
4352 4305                  IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: SRC: "
4353 4306                      "Get Companion PortGids for - %llX:%llX",
4354 4307                      cur_sgid.gid_prefix, cur_sgid.gid_guid);
4355 4308  
4356 4309                  retval = ibcm_get_comp_pgids(cur_sgid, new_sgid,
4357 4310                      c_hp.hp_hca_guid, &sgids_p, &snum);
4358 4311                  if (retval != IBT_SUCCESS)
4359 4312                          goto get_ip_alt_path_done;
4360 4313          }
4361 4314  
4362 4315          /* Get Companion Port GID of the current Channel's DGID */
4363 4316          if ((new_dgid.gid_guid == 0) || ((new_dgid.gid_guid != 0) &&
4364 4317              (new_dgid.gid_guid != cur_dgid.gid_guid))) {
4365 4318  
4366 4319                  IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: DEST: "
4367 4320                      "Get Companion PortGids for - %llX:%llX",
4368 4321                      cur_dgid.gid_prefix, cur_dgid.gid_guid);
4369 4322  
4370 4323                  retval = ibcm_get_comp_pgids(cur_dgid, new_dgid, 0, &dgids_p,
4371 4324                      &dnum);
4372 4325                  if (retval != IBT_SUCCESS)
4373 4326                          goto get_ip_alt_path_done;
4374 4327          }
4375 4328  
4376 4329          if ((new_dgid.gid_guid == 0) || (new_sgid.gid_guid == 0)) {
4377 4330                  if (new_sgid.gid_guid == 0) {
4378 4331                          for (i = 0; i < snum; i++) {
4379 4332                                  if (new_dgid.gid_guid == 0) {
4380 4333                                          for (j = 0; j < dnum; j++) {
4381 4334                                                  if (sgids_p[i].gid_prefix ==
4382 4335                                                      dgids_p[j].gid_prefix) {
4383 4336                                                          new_dgid = dgids_p[j];
4384 4337                                                          new_sgid = sgids_p[i];
4385 4338  
4386 4339                                                          goto get_ip_alt_proceed;
4387 4340                                                  }
4388 4341                                          }
4389 4342                                          /*  Current DGID */
4390 4343                                          if (sgids_p[i].gid_prefix ==
4391 4344                                              cur_dgid.gid_prefix) {
4392 4345                                                  new_sgid = sgids_p[i];
4393 4346                                                  goto get_ip_alt_proceed;
4394 4347                                          }
4395 4348                                  } else {
4396 4349                                          if (sgids_p[i].gid_prefix ==
4397 4350                                              new_dgid.gid_prefix) {
4398 4351                                                  new_sgid = sgids_p[i];
4399 4352                                                  goto get_ip_alt_proceed;
4400 4353                                          }
4401 4354                                  }
4402 4355                          }
4403 4356                          /* Current SGID */
4404 4357                          if (new_dgid.gid_guid == 0) {
4405 4358                                  for (j = 0; j < dnum; j++) {
4406 4359                                          if (cur_sgid.gid_prefix ==
4407 4360                                              dgids_p[j].gid_prefix) {
4408 4361                                                  new_dgid = dgids_p[j];
4409 4362  
4410 4363                                                  goto get_ip_alt_proceed;
4411 4364                                          }
4412 4365                                  }
4413 4366                          }
4414 4367                  } else if (new_dgid.gid_guid == 0) {
4415 4368                          for (i = 0; i < dnum; i++) {
4416 4369                                  if (dgids_p[i].gid_prefix ==
4417 4370                                      new_sgid.gid_prefix) {
4418 4371                                          new_dgid = dgids_p[i];
4419 4372                                          goto get_ip_alt_proceed;
4420 4373                                  }
4421 4374                          }
4422 4375                          /* Current DGID */
4423 4376                          if (cur_dgid.gid_prefix == new_sgid.gid_prefix) {
4424 4377                                  goto get_ip_alt_proceed;
4425 4378                          }
4426 4379                  }
4427 4380                  /*
4428 4381                   * hmm... No Companion Ports available.
4429 4382                   * so we will be using current or specified attributes only.
4430 4383                   */
4431 4384          }
4432 4385  
4433 4386  get_ip_alt_proceed:
4434 4387          if (new_sgid.gid_guid != 0) {
4435 4388                  retval = ibtl_cm_get_hca_port(new_sgid, 0, &n_hp);
4436 4389                  if (retval != IBT_SUCCESS) {
4437 4390                          IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: "
4438 4391                              "Get HCA Port Failed: %d", retval);
4439 4392                          goto get_ip_alt_path_done;
  
    | 
      ↓ open down ↓ | 
    261 lines elided | 
    
      ↑ open up ↑ | 
  
4440 4393                  }
4441 4394          }
4442 4395  
4443 4396          /* Calculate the size for multi-path records template */
4444 4397          template_len = (2 * sizeof (ib_gid_t)) + sizeof (sa_multipath_record_t);
4445 4398  
4446 4399          mpr_req = kmem_zalloc(template_len, KM_SLEEP);
4447 4400  
4448 4401          ASSERT(mpr_req != NULL);
4449 4402  
4450      -        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req))
4451      -
4452 4403          gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) +
4453 4404              sizeof (sa_multipath_record_t));
4454 4405  
4455 4406          /* SGID */
4456 4407          if (new_sgid.gid_guid == 0)
4457 4408                  *gid_ptr = cur_sgid;
4458 4409          else
4459 4410                  *gid_ptr = new_sgid;
4460 4411  
4461 4412          IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Get Path Between "
4462 4413              " SGID : %llX:%llX", gid_ptr->gid_prefix, gid_ptr->gid_guid);
4463 4414  
4464 4415          gid_ptr++;
4465 4416  
4466 4417          /* DGID */
4467 4418          if (new_dgid.gid_guid == 0)
4468 4419                  *gid_ptr = cur_dgid;
4469 4420          else
4470 4421                  *gid_ptr = new_dgid;
4471 4422  
4472 4423          IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path:\t\t    DGID : %llX:%llX",
4473 4424              gid_ptr->gid_prefix, gid_ptr->gid_guid);
4474 4425  
4475 4426          mpr_req->SGIDCount = 1;
4476 4427          c_mask = SA_MPR_COMPMASK_SGIDCOUNT;
4477 4428  
4478 4429          mpr_req->DGIDCount = 1;
4479 4430          c_mask |= SA_MPR_COMPMASK_DGIDCOUNT;
4480 4431  
4481 4432          /* Is Flow Label Specified. */
4482 4433          if (attrp) {
4483 4434                  if (attrp->apa_flow) {
4484 4435                          mpr_req->FlowLabel = attrp->apa_flow;
4485 4436                          c_mask |= SA_MPR_COMPMASK_FLOWLABEL;
4486 4437                  }
4487 4438  
4488 4439                  /* Is HopLimit Specified. */
4489 4440                  if (flags & IBT_PATH_HOP) {
4490 4441                          mpr_req->HopLimit = attrp->apa_hop;
4491 4442                          c_mask |= SA_MPR_COMPMASK_HOPLIMIT;
4492 4443                  }
4493 4444  
4494 4445                  /* Is TClass Specified. */
4495 4446                  if (attrp->apa_tclass) {
4496 4447                          mpr_req->TClass = attrp->apa_tclass;
4497 4448                          c_mask |= SA_MPR_COMPMASK_TCLASS;
4498 4449                  }
4499 4450  
4500 4451                  /* Is SL specified. */
4501 4452                  if (attrp->apa_sl) {
4502 4453                          mpr_req->SL = attrp->apa_sl;
4503 4454                          c_mask |= SA_MPR_COMPMASK_SL;
4504 4455                  }
4505 4456  
4506 4457                  if (flags & IBT_PATH_PERF) {
4507 4458                          mpr_req->PacketLifeTimeSelector = IBT_BEST;
4508 4459                          mpr_req->RateSelector = IBT_BEST;
4509 4460  
4510 4461                          c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR |
4511 4462                              SA_MPR_COMPMASK_RATESELECTOR;
4512 4463                  } else {
4513 4464                          if (attrp->apa_pkt_lt.p_selector == IBT_BEST) {
4514 4465                                  mpr_req->PacketLifeTimeSelector = IBT_BEST;
4515 4466                                  c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR;
4516 4467                          }
4517 4468  
4518 4469                          if (attrp->apa_srate.r_selector == IBT_BEST) {
4519 4470                                  mpr_req->RateSelector = IBT_BEST;
4520 4471                                  c_mask |= SA_MPR_COMPMASK_RATESELECTOR;
4521 4472                          }
4522 4473                  }
4523 4474  
4524 4475                  /*
4525 4476                   * Honor individual selection of these attributes,
4526 4477                   * even if IBT_PATH_PERF is set.
4527 4478                   */
4528 4479                  /* Check out whether Packet Life Time is specified. */
4529 4480                  if (attrp->apa_pkt_lt.p_pkt_lt) {
4530 4481                          mpr_req->PacketLifeTime =
4531 4482                              ibt_usec2ib(attrp->apa_pkt_lt.p_pkt_lt);
4532 4483                          mpr_req->PacketLifeTimeSelector =
4533 4484                              attrp->apa_pkt_lt.p_selector;
4534 4485  
4535 4486                          c_mask |= SA_MPR_COMPMASK_PKTLT |
4536 4487                              SA_MPR_COMPMASK_PKTLTSELECTOR;
4537 4488                  }
4538 4489  
4539 4490                  /* Is SRATE specified. */
4540 4491                  if (attrp->apa_srate.r_srate) {
4541 4492                          mpr_req->Rate = attrp->apa_srate.r_srate;
4542 4493                          mpr_req->RateSelector = attrp->apa_srate.r_selector;
4543 4494  
4544 4495                          c_mask |= SA_MPR_COMPMASK_RATE |
4545 4496                              SA_MPR_COMPMASK_RATESELECTOR;
4546 4497                  }
4547 4498          }
4548 4499  
4549 4500          /* Alt PathMTU can be GT or EQU to current channel's Pri PathMTU */
4550 4501  
4551 4502          /* P_Key must be same as that of primary path */
4552 4503          retval = ibt_index2pkey_byguid(c_hp.hp_hca_guid, c_hp.hp_port,
4553 4504              qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix,
4554 4505              &mpr_req->P_Key);
4555 4506          if (retval != IBT_SUCCESS) {
  
    | 
      ↓ open down ↓ | 
    94 lines elided | 
    
      ↑ open up ↑ | 
  
4556 4507                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: PKeyIdx2Pkey "
4557 4508                      "Failed: %d", retval);
4558 4509                  goto get_ip_alt_path_done;
4559 4510          }
4560 4511          c_mask |= SA_MPR_COMPMASK_PKEY;
4561 4512  
4562 4513          mpr_req->Reversible = 1;        /* We always get REVERSIBLE paths. */
4563 4514          mpr_req->IndependenceSelector = 1;
4564 4515          c_mask |= SA_MPR_COMPMASK_REVERSIBLE | SA_MPR_COMPMASK_INDEPSEL;
4565 4516  
4566      -        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req))
4567      -
4568 4517          IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: CMask: 0x%llX", c_mask);
4569 4518  
4570 4519          /* NOTE: We will **NOT** specify how many records we want. */
4571 4520  
4572 4521          IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Primary: MTU %d, PKey[%d]="
4573 4522              "0x%X\n\tSGID = %llX:%llX, DGID = %llX:%llX", prim_mtu,
4574 4523              qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, mpr_req->P_Key,
4575 4524              cur_sgid.gid_prefix, cur_sgid.gid_guid, cur_dgid.gid_prefix,
4576 4525              cur_dgid.gid_guid);
4577 4526  
4578 4527          /* Get SA Access Handle. */
4579 4528          if (new_sgid.gid_guid != 0)
4580 4529                  saa_handle = ibcm_get_saa_handle(hcap, n_hp.hp_port);
4581 4530          else
4582 4531                  saa_handle = ibcm_get_saa_handle(hcap, c_hp.hp_port);
4583 4532          if (saa_handle == NULL) {
4584 4533                  retval = IBT_HCA_PORT_NOT_ACTIVE;
4585 4534                  goto get_ip_alt_path_done;
4586 4535          }
4587 4536  
4588 4537          /* Contact SA Access to retrieve Path Records. */
4589 4538          access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID;
4590 4539          access_args.sq_access_type = IBMF_SAA_RETRIEVE;
4591 4540          access_args.sq_component_mask = c_mask;
4592 4541          access_args.sq_template = mpr_req;
4593 4542          access_args.sq_template_length = sizeof (sa_multipath_record_t);
4594 4543          access_args.sq_callback = NULL;
4595 4544          access_args.sq_callback_arg = NULL;
4596 4545  
4597 4546          retval = ibcm_contact_sa_access(saa_handle, &access_args, &length,
4598 4547              &results_p);
4599 4548          if (retval != IBT_SUCCESS) {
4600 4549                  goto get_ip_alt_path_done;
4601 4550          }
4602 4551  
4603 4552          num_rec = length / sizeof (sa_path_record_t);
4604 4553  
4605 4554          kmem_free(mpr_req, template_len);
4606 4555  
4607 4556          IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Found %d Paths", num_rec);
4608 4557  
4609 4558          rec_found = 0;
4610 4559          if ((results_p != NULL) && (num_rec > 0)) {
4611 4560                  /* Update the PathInfo with the response Path Records */
4612 4561                  pr_resp = (sa_path_record_t *)results_p;
4613 4562                  for (i = 0; i < num_rec; i++, pr_resp++) {
4614 4563                          if (prim_mtu > pr_resp->Mtu) {
4615 4564                                  IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: "
4616 4565                                      "Alt PathMTU(%d) must be GT or EQU to Pri "
4617 4566                                      "PathMTU(%d). Ignore this rec",
4618 4567                                      pr_resp->Mtu, prim_mtu);
4619 4568                                  continue;
4620 4569                          }
4621 4570  
4622 4571                          if ((new_sgid.gid_guid == 0) &&
4623 4572                              (new_dgid.gid_guid == 0)) {
4624 4573                                  /* Reject PathRec if it same as Primary Path. */
4625 4574                                  if (ibcm_compare_paths(pr_resp,
4626 4575                                      &qp_attr.qp_info.qp_transport.rc.rc_path,
4627 4576                                      &c_hp)) {
4628 4577                                          IBTF_DPRINTF_L3(cmlog,
4629 4578                                              "ibt_get_ip_alt_path: PathRec "
4630 4579                                              "obtained is similar to Prim Path, "
4631 4580                                              "ignore this record");
4632 4581                                          continue;
4633 4582                                  }
4634 4583                          }
4635 4584  
4636 4585                          if (new_sgid.gid_guid == 0) {
  
    | 
      ↓ open down ↓ | 
    59 lines elided | 
    
      ↑ open up ↑ | 
  
4637 4586                                  retval = ibcm_update_cep_info(pr_resp, NULL,
4638 4587                                      &c_hp, &api_p->ap_alt_cep_path);
4639 4588                          } else {
4640 4589                                  retval = ibcm_update_cep_info(pr_resp, NULL,
4641 4590                                      &n_hp, &api_p->ap_alt_cep_path);
4642 4591                          }
4643 4592                          if (retval != IBT_SUCCESS)
4644 4593                                  continue;
4645 4594  
4646 4595                          /* Update some leftovers */
4647      -                        _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*api_p))
4648      -
4649 4596                          api_p->ap_alt_pkt_lt = pr_resp->PacketLifeTime;
4650 4597  
4651      -                        _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*api_p))
4652      -
4653 4598                          rec_found = 1;
4654 4599                          break;
4655 4600                  }
4656 4601                  kmem_free(results_p, length);
4657 4602          }
4658 4603  
4659 4604          if (rec_found == 0) {
4660 4605                  IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: AltPath cannot"
4661 4606                      " be established");
4662 4607                  retval = IBT_PATH_RECORDS_NOT_FOUND;
4663 4608          } else
4664 4609                  retval = IBT_SUCCESS;
4665 4610  
4666 4611  get_ip_alt_path_done:
4667 4612          if ((snum) && (sgids_p))
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
4668 4613                  kmem_free(sgids_p, snum * sizeof (ib_gid_t));
4669 4614  
4670 4615          if ((dnum) && (dgids_p))
4671 4616                  kmem_free(dgids_p, dnum * sizeof (ib_gid_t));
4672 4617  
4673 4618          ibcm_dec_hca_acc_cnt(hcap);
4674 4619  
4675 4620          IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Done (status %d)", retval);
4676 4621  
4677 4622          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 4623  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX