1 /* 2 * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved. 3 * Copyright (c) 2004 Infinicon Corporation. All rights reserved. 4 * Copyright (c) 2004 Intel Corporation. All rights reserved. 5 * Copyright (c) 2004 Topspin Corporation. All rights reserved. 6 * Copyright (c) 2004 Voltaire Corporation. All rights reserved. 7 * 8 * This software is available to you under a choice of one of two 9 * licenses. You may choose to be licensed under the terms of the GNU 10 * General Public License (GPL) Version 2, available from the file 11 * COPYING in the main directory of this source tree, or the 12 * OpenIB.org BSD license below: 13 * 14 * Redistribution and use in source and binary forms, with or 15 * without modification, are permitted provided that the following 16 * conditions are met: 17 * 18 * - Redistributions of source code must retain the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer. 21 * 22 * - Redistributions in binary form must reproduce the above 23 * copyright notice, this list of conditions and the following 24 * disclaimer in the documentation and/or other materials 25 * provided with the distribution. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 31 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 32 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 * SOFTWARE. 35 * 36 * $Id: smi.c 1389 2004-12-27 22:56:47Z roland $ 37 */ 38 39 #include <ib_smi.h> 40 #include "smi.h" 41 42 /* 43 * Fixup a directed route SMP for sending 44 * Return 0 if the SMP should be discarded 45 */ 46 int smi_handle_dr_smp_send(struct ib_smp *smp, 47 u8 node_type, 48 int port_num) 49 { 50 u8 hop_ptr, hop_cnt; 51 52 hop_ptr = smp->hop_ptr; 53 hop_cnt = smp->hop_cnt; 54 55 /* See section 14.2.2.2, Vol 1 IB spec */ 56 if (!ib_get_smp_direction(smp)) { 57 /* C14-9:1 */ 58 if (hop_cnt && hop_ptr == 0) { 59 smp->hop_ptr++; 60 return (smp->initial_path[smp->hop_ptr] == 61 port_num); 62 } 63 64 /* C14-9:2 */ 65 if (hop_ptr && hop_ptr < hop_cnt) { 66 if (node_type != IB_NODE_SWITCH) 67 return 0; 68 69 /* smp->return_path set when received */ 70 smp->hop_ptr++; 71 return (smp->initial_path[smp->hop_ptr] == 72 port_num); 73 } 74 75 /* C14-9:3 -- We're at the end of the DR segment of path */ 76 if (hop_ptr == hop_cnt) { 77 /* smp->return_path set when received */ 78 smp->hop_ptr++; 79 return (node_type == IB_NODE_SWITCH || 80 smp->dr_dlid == IB_LID_PERMISSIVE); 81 } 82 83 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ 84 /* C14-9:5 -- Fail unreasonable hop pointer */ 85 return (hop_ptr == hop_cnt + 1); 86 87 } else { 88 /* C14-13:1 */ 89 if (hop_cnt && hop_ptr == hop_cnt + 1) { 90 smp->hop_ptr--; 91 return (smp->return_path[smp->hop_ptr] == 92 port_num); 93 } 94 95 /* C14-13:2 */ 96 if (2 <= hop_ptr && hop_ptr <= hop_cnt) { 97 if (node_type != IB_NODE_SWITCH) 98 return 0; 99 100 smp->hop_ptr--; 101 return (smp->return_path[smp->hop_ptr] == 102 port_num); 103 } 104 105 /* C14-13:3 -- at the end of the DR segment of path */ 106 if (hop_ptr == 1) { 107 smp->hop_ptr--; 108 /* C14-13:3 -- SMPs destined for SM shouldn't be here */ 109 return (node_type == IB_NODE_SWITCH || 110 smp->dr_slid == IB_LID_PERMISSIVE); 111 } 112 113 /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */ 114 if (hop_ptr == 0) 115 return 1; 116 117 /* C14-13:5 -- Check for unreasonable hop pointer */ 118 return 0; 119 } 120 } 121 122 /* 123 * Adjust information for a received SMP 124 * Return 0 if the SMP should be dropped 125 */ 126 int smi_handle_dr_smp_recv(struct ib_smp *smp, 127 u8 node_type, 128 int port_num, 129 int phys_port_cnt) 130 { 131 u8 hop_ptr, hop_cnt; 132 133 hop_ptr = smp->hop_ptr; 134 hop_cnt = smp->hop_cnt; 135 136 /* See section 14.2.2.2, Vol 1 IB spec */ 137 if (!ib_get_smp_direction(smp)) { 138 /* C14-9:1 -- sender should have incremented hop_ptr */ 139 if (hop_cnt && hop_ptr == 0) 140 return 0; 141 142 /* C14-9:2 -- intermediate hop */ 143 if (hop_ptr && hop_ptr < hop_cnt) { 144 if (node_type != IB_NODE_SWITCH) 145 return 0; 146 147 smp->return_path[hop_ptr] = port_num; 148 /* smp->hop_ptr updated when sending */ 149 return (smp->initial_path[hop_ptr+1] <= phys_port_cnt); 150 } 151 152 /* C14-9:3 -- We're at the end of the DR segment of path */ 153 if (hop_ptr == hop_cnt) { 154 if (hop_cnt) 155 smp->return_path[hop_ptr] = port_num; 156 /* smp->hop_ptr updated when sending */ 157 158 return (node_type == IB_NODE_SWITCH || 159 smp->dr_dlid == IB_LID_PERMISSIVE); 160 } 161 162 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ 163 /* C14-9:5 -- fail unreasonable hop pointer */ 164 return (hop_ptr == hop_cnt + 1); 165 166 } else { 167 168 /* C14-13:1 */ 169 if (hop_cnt && hop_ptr == hop_cnt + 1) { 170 smp->hop_ptr--; 171 return (smp->return_path[smp->hop_ptr] == 172 port_num); 173 } 174 175 /* C14-13:2 */ 176 if (2 <= hop_ptr && hop_ptr <= hop_cnt) { 177 if (node_type != IB_NODE_SWITCH) 178 return 0; 179 180 /* smp->hop_ptr updated when sending */ 181 return (smp->return_path[hop_ptr-1] <= phys_port_cnt); 182 } 183 184 /* C14-13:3 -- We're at the end of the DR segment of path */ 185 if (hop_ptr == 1) { 186 if (smp->dr_slid == IB_LID_PERMISSIVE) { 187 /* giving SMP to SM - update hop_ptr */ 188 smp->hop_ptr--; 189 return 1; 190 } 191 /* smp->hop_ptr updated when sending */ 192 return (node_type == IB_NODE_SWITCH); 193 } 194 195 /* C14-13:4 -- hop_ptr = 0 -> give to SM */ 196 /* C14-13:5 -- Check for unreasonable hop pointer */ 197 return (hop_ptr == 0); 198 } 199 } 200 201 /* 202 * Return 1 if the received DR SMP should be forwarded to the send queue 203 * Return 0 if the SMP should be completed up the stack 204 */ 205 int smi_check_forward_dr_smp(struct ib_smp *smp) 206 { 207 u8 hop_ptr, hop_cnt; 208 209 hop_ptr = smp->hop_ptr; 210 hop_cnt = smp->hop_cnt; 211 212 if (!ib_get_smp_direction(smp)) { 213 /* C14-9:2 -- intermediate hop */ 214 if (hop_ptr && hop_ptr < hop_cnt) 215 return 1; 216 217 /* C14-9:3 -- at the end of the DR segment of path */ 218 if (hop_ptr == hop_cnt) 219 return (smp->dr_dlid == IB_LID_PERMISSIVE); 220 221 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ 222 if (hop_ptr == hop_cnt + 1) 223 return 1; 224 } else { 225 /* C14-13:2 */ 226 if (2 <= hop_ptr && hop_ptr <= hop_cnt) 227 return 1; 228 229 /* C14-13:3 -- at the end of the DR segment of path */ 230 if (hop_ptr == 1) 231 return (smp->dr_slid != IB_LID_PERMISSIVE); 232 } 233 return 0; 234 } 235