0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #include <rdma/ib_smi.h>
0041 #include "smi.h"
0042 #include "opa_smi.h"
0043
0044 static enum smi_action __smi_handle_dr_smp_send(bool is_switch, u32 port_num,
0045 u8 *hop_ptr, u8 hop_cnt,
0046 const u8 *initial_path,
0047 const u8 *return_path,
0048 u8 direction,
0049 bool dr_dlid_is_permissive,
0050 bool dr_slid_is_permissive)
0051 {
0052
0053
0054 if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
0055 return IB_SMI_DISCARD;
0056
0057 if (!direction) {
0058
0059 if (hop_cnt && *hop_ptr == 0) {
0060 (*hop_ptr)++;
0061 return (initial_path[*hop_ptr] ==
0062 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0063 }
0064
0065
0066 if (*hop_ptr && *hop_ptr < hop_cnt) {
0067 if (!is_switch)
0068 return IB_SMI_DISCARD;
0069
0070
0071 (*hop_ptr)++;
0072 return (initial_path[*hop_ptr] ==
0073 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0074 }
0075
0076
0077 if (*hop_ptr == hop_cnt) {
0078
0079 (*hop_ptr)++;
0080 return (is_switch ||
0081 dr_dlid_is_permissive ?
0082 IB_SMI_HANDLE : IB_SMI_DISCARD);
0083 }
0084
0085
0086
0087 return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0088
0089 } else {
0090
0091 if (hop_cnt && *hop_ptr == hop_cnt + 1) {
0092 (*hop_ptr)--;
0093 return (return_path[*hop_ptr] ==
0094 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0095 }
0096
0097
0098 if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
0099 if (!is_switch)
0100 return IB_SMI_DISCARD;
0101
0102 (*hop_ptr)--;
0103 return (return_path[*hop_ptr] ==
0104 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0105 }
0106
0107
0108 if (*hop_ptr == 1) {
0109 (*hop_ptr)--;
0110
0111 return (is_switch ||
0112 dr_slid_is_permissive ?
0113 IB_SMI_HANDLE : IB_SMI_DISCARD);
0114 }
0115
0116
0117 if (*hop_ptr == 0)
0118 return IB_SMI_HANDLE;
0119
0120
0121 return IB_SMI_DISCARD;
0122 }
0123 }
0124
0125
0126
0127
0128
0129 enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
0130 bool is_switch, u32 port_num)
0131 {
0132 return __smi_handle_dr_smp_send(is_switch, port_num,
0133 &smp->hop_ptr, smp->hop_cnt,
0134 smp->initial_path,
0135 smp->return_path,
0136 ib_get_smp_direction(smp),
0137 smp->dr_dlid == IB_LID_PERMISSIVE,
0138 smp->dr_slid == IB_LID_PERMISSIVE);
0139 }
0140
0141 enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp,
0142 bool is_switch, u32 port_num)
0143 {
0144 return __smi_handle_dr_smp_send(is_switch, port_num,
0145 &smp->hop_ptr, smp->hop_cnt,
0146 smp->route.dr.initial_path,
0147 smp->route.dr.return_path,
0148 opa_get_smp_direction(smp),
0149 smp->route.dr.dr_dlid ==
0150 OPA_LID_PERMISSIVE,
0151 smp->route.dr.dr_slid ==
0152 OPA_LID_PERMISSIVE);
0153 }
0154
0155 static enum smi_action __smi_handle_dr_smp_recv(bool is_switch, u32 port_num,
0156 int phys_port_cnt,
0157 u8 *hop_ptr, u8 hop_cnt,
0158 const u8 *initial_path,
0159 u8 *return_path,
0160 u8 direction,
0161 bool dr_dlid_is_permissive,
0162 bool dr_slid_is_permissive)
0163 {
0164
0165
0166 if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
0167 return IB_SMI_DISCARD;
0168
0169 if (!direction) {
0170
0171 if (hop_cnt && *hop_ptr == 0)
0172 return IB_SMI_DISCARD;
0173
0174
0175 if (*hop_ptr && *hop_ptr < hop_cnt) {
0176 if (!is_switch)
0177 return IB_SMI_DISCARD;
0178
0179 return_path[*hop_ptr] = port_num;
0180
0181 return (initial_path[*hop_ptr+1] <= phys_port_cnt ?
0182 IB_SMI_HANDLE : IB_SMI_DISCARD);
0183 }
0184
0185
0186 if (*hop_ptr == hop_cnt) {
0187 if (hop_cnt)
0188 return_path[*hop_ptr] = port_num;
0189
0190
0191 return (is_switch ||
0192 dr_dlid_is_permissive ?
0193 IB_SMI_HANDLE : IB_SMI_DISCARD);
0194 }
0195
0196
0197
0198 return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0199
0200 } else {
0201
0202
0203 if (hop_cnt && *hop_ptr == hop_cnt + 1) {
0204 (*hop_ptr)--;
0205 return (return_path[*hop_ptr] ==
0206 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0207 }
0208
0209
0210 if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
0211 if (!is_switch)
0212 return IB_SMI_DISCARD;
0213
0214
0215 return (return_path[*hop_ptr-1] <= phys_port_cnt ?
0216 IB_SMI_HANDLE : IB_SMI_DISCARD);
0217 }
0218
0219
0220 if (*hop_ptr == 1) {
0221 if (dr_slid_is_permissive) {
0222
0223 (*hop_ptr)--;
0224 return IB_SMI_HANDLE;
0225 }
0226
0227 return (is_switch ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0228 }
0229
0230
0231
0232 return (*hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
0233 }
0234 }
0235
0236
0237
0238
0239
0240 enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch,
0241 u32 port_num, int phys_port_cnt)
0242 {
0243 return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
0244 &smp->hop_ptr, smp->hop_cnt,
0245 smp->initial_path,
0246 smp->return_path,
0247 ib_get_smp_direction(smp),
0248 smp->dr_dlid == IB_LID_PERMISSIVE,
0249 smp->dr_slid == IB_LID_PERMISSIVE);
0250 }
0251
0252
0253
0254
0255
0256 enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch,
0257 u32 port_num, int phys_port_cnt)
0258 {
0259 return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
0260 &smp->hop_ptr, smp->hop_cnt,
0261 smp->route.dr.initial_path,
0262 smp->route.dr.return_path,
0263 opa_get_smp_direction(smp),
0264 smp->route.dr.dr_dlid ==
0265 OPA_LID_PERMISSIVE,
0266 smp->route.dr.dr_slid ==
0267 OPA_LID_PERMISSIVE);
0268 }
0269
0270 static enum smi_forward_action __smi_check_forward_dr_smp(u8 hop_ptr, u8 hop_cnt,
0271 u8 direction,
0272 bool dr_dlid_is_permissive,
0273 bool dr_slid_is_permissive)
0274 {
0275 if (!direction) {
0276
0277 if (hop_ptr && hop_ptr < hop_cnt)
0278 return IB_SMI_FORWARD;
0279
0280
0281 if (hop_ptr == hop_cnt)
0282 return (dr_dlid_is_permissive ?
0283 IB_SMI_SEND : IB_SMI_LOCAL);
0284
0285
0286 if (hop_ptr == hop_cnt + 1)
0287 return IB_SMI_SEND;
0288 } else {
0289
0290 if (2 <= hop_ptr && hop_ptr <= hop_cnt)
0291 return IB_SMI_FORWARD;
0292
0293
0294 if (hop_ptr == 1)
0295 return (!dr_slid_is_permissive ?
0296 IB_SMI_SEND : IB_SMI_LOCAL);
0297 }
0298 return IB_SMI_LOCAL;
0299
0300 }
0301
0302 enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
0303 {
0304 return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
0305 ib_get_smp_direction(smp),
0306 smp->dr_dlid == IB_LID_PERMISSIVE,
0307 smp->dr_slid == IB_LID_PERMISSIVE);
0308 }
0309
0310 enum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp)
0311 {
0312 return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
0313 opa_get_smp_direction(smp),
0314 smp->route.dr.dr_dlid ==
0315 OPA_LID_PERMISSIVE,
0316 smp->route.dr.dr_slid ==
0317 OPA_LID_PERMISSIVE);
0318 }
0319
0320
0321
0322
0323
0324 int smi_get_fwd_port(struct ib_smp *smp)
0325 {
0326 return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
0327 smp->return_path[smp->hop_ptr-1]);
0328 }
0329
0330
0331
0332
0333
0334 int opa_smi_get_fwd_port(struct opa_smp *smp)
0335 {
0336 return !opa_get_smp_direction(smp) ? smp->route.dr.initial_path[smp->hop_ptr+1] :
0337 smp->route.dr.return_path[smp->hop_ptr-1];
0338 }