root/drivers/infiniband/core/smi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __smi_handle_dr_smp_send
  2. smi_handle_dr_smp_send
  3. opa_smi_handle_dr_smp_send
  4. __smi_handle_dr_smp_recv
  5. smi_handle_dr_smp_recv
  6. opa_smi_handle_dr_smp_recv
  7. __smi_check_forward_dr_smp
  8. smi_check_forward_dr_smp
  9. opa_smi_check_forward_dr_smp
  10. smi_get_fwd_port
  11. opa_smi_get_fwd_port

   1 /*
   2  * Copyright (c) 2004, 2005 Mellanox Technologies Ltd.  All rights reserved.
   3  * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
   4  * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
   5  * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2007 Voltaire Corporation.  All rights reserved.
   7  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
   8  * Copyright (c) 2014 Intel Corporation.  All rights reserved.
   9  *
  10  * This software is available to you under a choice of one of two
  11  * licenses.  You may choose to be licensed under the terms of the GNU
  12  * General Public License (GPL) Version 2, available from the file
  13  * COPYING in the main directory of this source tree, or the
  14  * OpenIB.org BSD license below:
  15  *
  16  *     Redistribution and use in source and binary forms, with or
  17  *     without modification, are permitted provided that the following
  18  *     conditions are met:
  19  *
  20  *      - Redistributions of source code must retain the above
  21  *        copyright notice, this list of conditions and the following
  22  *        disclaimer.
  23  *
  24  *      - Redistributions in binary form must reproduce the above
  25  *        copyright notice, this list of conditions and the following
  26  *        disclaimer in the documentation and/or other materials
  27  *        provided with the distribution.
  28  *
  29  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  30  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  31  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  32  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  33  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  34  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  35  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  36  * SOFTWARE.
  37  *
  38  */
  39 
  40 #include <rdma/ib_smi.h>
  41 #include "smi.h"
  42 #include "opa_smi.h"
  43 
  44 static enum smi_action __smi_handle_dr_smp_send(bool is_switch, int port_num,
  45                                                 u8 *hop_ptr, u8 hop_cnt,
  46                                                 const u8 *initial_path,
  47                                                 const u8 *return_path,
  48                                                 u8 direction,
  49                                                 bool dr_dlid_is_permissive,
  50                                                 bool dr_slid_is_permissive)
  51 {
  52         /* See section 14.2.2.2, Vol 1 IB spec */
  53         /* C14-6 -- valid hop_cnt values are from 0 to 63 */
  54         if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
  55                 return IB_SMI_DISCARD;
  56 
  57         if (!direction) {
  58                 /* C14-9:1 */
  59                 if (hop_cnt && *hop_ptr == 0) {
  60                         (*hop_ptr)++;
  61                         return (initial_path[*hop_ptr] ==
  62                                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
  63                 }
  64 
  65                 /* C14-9:2 */
  66                 if (*hop_ptr && *hop_ptr < hop_cnt) {
  67                         if (!is_switch)
  68                                 return IB_SMI_DISCARD;
  69 
  70                         /* return_path set when received */
  71                         (*hop_ptr)++;
  72                         return (initial_path[*hop_ptr] ==
  73                                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
  74                 }
  75 
  76                 /* C14-9:3 -- We're at the end of the DR segment of path */
  77                 if (*hop_ptr == hop_cnt) {
  78                         /* return_path set when received */
  79                         (*hop_ptr)++;
  80                         return (is_switch ||
  81                                 dr_dlid_is_permissive ?
  82                                 IB_SMI_HANDLE : IB_SMI_DISCARD);
  83                 }
  84 
  85                 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
  86                 /* C14-9:5 -- Fail unreasonable hop pointer */
  87                 return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
  88 
  89         } else {
  90                 /* C14-13:1 */
  91                 if (hop_cnt && *hop_ptr == hop_cnt + 1) {
  92                         (*hop_ptr)--;
  93                         return (return_path[*hop_ptr] ==
  94                                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
  95                 }
  96 
  97                 /* C14-13:2 */
  98                 if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
  99                         if (!is_switch)
 100                                 return IB_SMI_DISCARD;
 101 
 102                         (*hop_ptr)--;
 103                         return (return_path[*hop_ptr] ==
 104                                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
 105                 }
 106 
 107                 /* C14-13:3 -- at the end of the DR segment of path */
 108                 if (*hop_ptr == 1) {
 109                         (*hop_ptr)--;
 110                         /* C14-13:3 -- SMPs destined for SM shouldn't be here */
 111                         return (is_switch ||
 112                                 dr_slid_is_permissive ?
 113                                 IB_SMI_HANDLE : IB_SMI_DISCARD);
 114                 }
 115 
 116                 /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */
 117                 if (*hop_ptr == 0)
 118                         return IB_SMI_HANDLE;
 119 
 120                 /* C14-13:5 -- Check for unreasonable hop pointer */
 121                 return IB_SMI_DISCARD;
 122         }
 123 }
 124 
 125 /*
 126  * Fixup a directed route SMP for sending
 127  * Return IB_SMI_DISCARD if the SMP should be discarded
 128  */
 129 enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
 130                                        bool is_switch, int port_num)
 131 {
 132         return __smi_handle_dr_smp_send(is_switch, port_num,
 133                                         &smp->hop_ptr, smp->hop_cnt,
 134                                         smp->initial_path,
 135                                         smp->return_path,
 136                                         ib_get_smp_direction(smp),
 137                                         smp->dr_dlid == IB_LID_PERMISSIVE,
 138                                         smp->dr_slid == IB_LID_PERMISSIVE);
 139 }
 140 
 141 enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp,
 142                                        bool is_switch, int port_num)
 143 {
 144         return __smi_handle_dr_smp_send(is_switch, port_num,
 145                                         &smp->hop_ptr, smp->hop_cnt,
 146                                         smp->route.dr.initial_path,
 147                                         smp->route.dr.return_path,
 148                                         opa_get_smp_direction(smp),
 149                                         smp->route.dr.dr_dlid ==
 150                                         OPA_LID_PERMISSIVE,
 151                                         smp->route.dr.dr_slid ==
 152                                         OPA_LID_PERMISSIVE);
 153 }
 154 
 155 static enum smi_action __smi_handle_dr_smp_recv(bool is_switch, int port_num,
 156                                                 int phys_port_cnt,
 157                                                 u8 *hop_ptr, u8 hop_cnt,
 158                                                 const u8 *initial_path,
 159                                                 u8 *return_path,
 160                                                 u8 direction,
 161                                                 bool dr_dlid_is_permissive,
 162                                                 bool dr_slid_is_permissive)
 163 {
 164         /* See section 14.2.2.2, Vol 1 IB spec */
 165         /* C14-6 -- valid hop_cnt values are from 0 to 63 */
 166         if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
 167                 return IB_SMI_DISCARD;
 168 
 169         if (!direction) {
 170                 /* C14-9:1 -- sender should have incremented hop_ptr */
 171                 if (hop_cnt && *hop_ptr == 0)
 172                         return IB_SMI_DISCARD;
 173 
 174                 /* C14-9:2 -- intermediate hop */
 175                 if (*hop_ptr && *hop_ptr < hop_cnt) {
 176                         if (!is_switch)
 177                                 return IB_SMI_DISCARD;
 178 
 179                         return_path[*hop_ptr] = port_num;
 180                         /* hop_ptr updated when sending */
 181                         return (initial_path[*hop_ptr+1] <= phys_port_cnt ?
 182                                 IB_SMI_HANDLE : IB_SMI_DISCARD);
 183                 }
 184 
 185                 /* C14-9:3 -- We're at the end of the DR segment of path */
 186                 if (*hop_ptr == hop_cnt) {
 187                         if (hop_cnt)
 188                                 return_path[*hop_ptr] = port_num;
 189                         /* hop_ptr updated when sending */
 190 
 191                         return (is_switch ||
 192                                 dr_dlid_is_permissive ?
 193                                 IB_SMI_HANDLE : IB_SMI_DISCARD);
 194                 }
 195 
 196                 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
 197                 /* C14-9:5 -- fail unreasonable hop pointer */
 198                 return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
 199 
 200         } else {
 201 
 202                 /* C14-13:1 */
 203                 if (hop_cnt && *hop_ptr == hop_cnt + 1) {
 204                         (*hop_ptr)--;
 205                         return (return_path[*hop_ptr] ==
 206                                 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
 207                 }
 208 
 209                 /* C14-13:2 */
 210                 if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
 211                         if (!is_switch)
 212                                 return IB_SMI_DISCARD;
 213 
 214                         /* hop_ptr updated when sending */
 215                         return (return_path[*hop_ptr-1] <= phys_port_cnt ?
 216                                 IB_SMI_HANDLE : IB_SMI_DISCARD);
 217                 }
 218 
 219                 /* C14-13:3 -- We're at the end of the DR segment of path */
 220                 if (*hop_ptr == 1) {
 221                         if (dr_slid_is_permissive) {
 222                                 /* giving SMP to SM - update hop_ptr */
 223                                 (*hop_ptr)--;
 224                                 return IB_SMI_HANDLE;
 225                         }
 226                         /* hop_ptr updated when sending */
 227                         return (is_switch ? IB_SMI_HANDLE : IB_SMI_DISCARD);
 228                 }
 229 
 230                 /* C14-13:4 -- hop_ptr = 0 -> give to SM */
 231                 /* C14-13:5 -- Check for unreasonable hop pointer */
 232                 return (*hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
 233         }
 234 }
 235 
 236 /*
 237  * Adjust information for a received SMP
 238  * Return IB_SMI_DISCARD if the SMP should be dropped
 239  */
 240 enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch,
 241                                        int port_num, int phys_port_cnt)
 242 {
 243         return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
 244                                         &smp->hop_ptr, smp->hop_cnt,
 245                                         smp->initial_path,
 246                                         smp->return_path,
 247                                         ib_get_smp_direction(smp),
 248                                         smp->dr_dlid == IB_LID_PERMISSIVE,
 249                                         smp->dr_slid == IB_LID_PERMISSIVE);
 250 }
 251 
 252 /*
 253  * Adjust information for a received SMP
 254  * Return IB_SMI_DISCARD if the SMP should be dropped
 255  */
 256 enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch,
 257                                            int port_num, int phys_port_cnt)
 258 {
 259         return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
 260                                         &smp->hop_ptr, smp->hop_cnt,
 261                                         smp->route.dr.initial_path,
 262                                         smp->route.dr.return_path,
 263                                         opa_get_smp_direction(smp),
 264                                         smp->route.dr.dr_dlid ==
 265                                         OPA_LID_PERMISSIVE,
 266                                         smp->route.dr.dr_slid ==
 267                                         OPA_LID_PERMISSIVE);
 268 }
 269 
 270 static enum smi_forward_action __smi_check_forward_dr_smp(u8 hop_ptr, u8 hop_cnt,
 271                                                           u8 direction,
 272                                                           bool dr_dlid_is_permissive,
 273                                                           bool dr_slid_is_permissive)
 274 {
 275         if (!direction) {
 276                 /* C14-9:2 -- intermediate hop */
 277                 if (hop_ptr && hop_ptr < hop_cnt)
 278                         return IB_SMI_FORWARD;
 279 
 280                 /* C14-9:3 -- at the end of the DR segment of path */
 281                 if (hop_ptr == hop_cnt)
 282                         return (dr_dlid_is_permissive ?
 283                                 IB_SMI_SEND : IB_SMI_LOCAL);
 284 
 285                 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
 286                 if (hop_ptr == hop_cnt + 1)
 287                         return IB_SMI_SEND;
 288         } else {
 289                 /* C14-13:2  -- intermediate hop */
 290                 if (2 <= hop_ptr && hop_ptr <= hop_cnt)
 291                         return IB_SMI_FORWARD;
 292 
 293                 /* C14-13:3 -- at the end of the DR segment of path */
 294                 if (hop_ptr == 1)
 295                         return (!dr_slid_is_permissive ?
 296                                 IB_SMI_SEND : IB_SMI_LOCAL);
 297         }
 298         return IB_SMI_LOCAL;
 299 
 300 }
 301 
 302 enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
 303 {
 304         return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
 305                                           ib_get_smp_direction(smp),
 306                                           smp->dr_dlid == IB_LID_PERMISSIVE,
 307                                           smp->dr_slid == IB_LID_PERMISSIVE);
 308 }
 309 
 310 enum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp)
 311 {
 312         return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
 313                                           opa_get_smp_direction(smp),
 314                                           smp->route.dr.dr_dlid ==
 315                                           OPA_LID_PERMISSIVE,
 316                                           smp->route.dr.dr_slid ==
 317                                           OPA_LID_PERMISSIVE);
 318 }
 319 
 320 /*
 321  * Return the forwarding port number from initial_path for outgoing SMP and
 322  * from return_path for returning SMP
 323  */
 324 int smi_get_fwd_port(struct ib_smp *smp)
 325 {
 326         return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
 327                 smp->return_path[smp->hop_ptr-1]);
 328 }
 329 
 330 /*
 331  * Return the forwarding port number from initial_path for outgoing SMP and
 332  * from return_path for returning SMP
 333  */
 334 int opa_smi_get_fwd_port(struct opa_smp *smp)
 335 {
 336         return !opa_get_smp_direction(smp) ? smp->route.dr.initial_path[smp->hop_ptr+1] :
 337                 smp->route.dr.return_path[smp->hop_ptr-1];
 338 }

/* [<][>][^][v][top][bottom][index][help] */