blob: 87236753bce9b7a93f9b41b30297e7d4c5a4d432 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Roland Dreier2a1d9b72005-08-10 23:03:10 -07002 * 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.
Hal Rosenstockde493d42007-04-02 11:24:07 -04006 * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved.
Roland Dreier2a1d9b72005-08-10 23:03:10 -07007 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * This software is available to you under a choice of one of two
10 * licenses. You may choose to be licensed under the terms of the GNU
11 * General Public License (GPL) Version 2, available from the file
12 * COPYING in the main directory of this source tree, or the
13 * OpenIB.org BSD license below:
14 *
15 * Redistribution and use in source and binary forms, with or
16 * without modification, are permitted provided that the following
17 * conditions are met:
18 *
19 * - Redistributions of source code must retain the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer.
22 *
23 * - Redistributions in binary form must reproduce the above
24 * copyright notice, this list of conditions and the following
25 * disclaimer in the documentation and/or other materials
26 * provided with the distribution.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 * SOFTWARE.
36 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 */
38
Roland Dreiera4d61e82005-08-25 13:40:04 -070039#include <rdma/ib_smi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include "smi.h"
41
42/*
43 * Fixup a directed route SMP for sending
44 * Return 0 if the SMP should be discarded
45 */
Hal Rosenstockde493d42007-04-02 11:24:07 -040046enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
47 u8 node_type, int port_num)
Linus Torvalds1da177e2005-04-16 15:20:36 -070048{
49 u8 hop_ptr, hop_cnt;
50
51 hop_ptr = smp->hop_ptr;
52 hop_cnt = smp->hop_cnt;
53
54 /* See section 14.2.2.2, Vol 1 IB spec */
55 if (!ib_get_smp_direction(smp)) {
56 /* C14-9:1 */
57 if (hop_cnt && hop_ptr == 0) {
58 smp->hop_ptr++;
59 return (smp->initial_path[smp->hop_ptr] ==
Hal Rosenstockde493d42007-04-02 11:24:07 -040060 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 }
62
63 /* C14-9:2 */
64 if (hop_ptr && hop_ptr < hop_cnt) {
Tom Tucker07ebafb2006-08-03 16:02:42 -050065 if (node_type != RDMA_NODE_IB_SWITCH)
Hal Rosenstockde493d42007-04-02 11:24:07 -040066 return IB_SMI_DISCARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
68 /* smp->return_path set when received */
69 smp->hop_ptr++;
70 return (smp->initial_path[smp->hop_ptr] ==
Hal Rosenstockde493d42007-04-02 11:24:07 -040071 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 }
73
74 /* C14-9:3 -- We're at the end of the DR segment of path */
75 if (hop_ptr == hop_cnt) {
76 /* smp->return_path set when received */
77 smp->hop_ptr++;
Tom Tucker07ebafb2006-08-03 16:02:42 -050078 return (node_type == RDMA_NODE_IB_SWITCH ||
Hal Rosenstockde493d42007-04-02 11:24:07 -040079 smp->dr_dlid == IB_LID_PERMISSIVE ?
80 IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 }
82
83 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
84 /* C14-9:5 -- Fail unreasonable hop pointer */
Hal Rosenstockde493d42007-04-02 11:24:07 -040085 return (hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
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] ==
Hal Rosenstockde493d42007-04-02 11:24:07 -040092 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 }
94
95 /* C14-13:2 */
96 if (2 <= hop_ptr && hop_ptr <= hop_cnt) {
Tom Tucker07ebafb2006-08-03 16:02:42 -050097 if (node_type != RDMA_NODE_IB_SWITCH)
Hal Rosenstockde493d42007-04-02 11:24:07 -040098 return IB_SMI_DISCARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100 smp->hop_ptr--;
101 return (smp->return_path[smp->hop_ptr] ==
Hal Rosenstockde493d42007-04-02 11:24:07 -0400102 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 }
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 */
Tom Tucker07ebafb2006-08-03 16:02:42 -0500109 return (node_type == RDMA_NODE_IB_SWITCH ||
Hal Rosenstockde493d42007-04-02 11:24:07 -0400110 smp->dr_slid == IB_LID_PERMISSIVE ?
111 IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 }
113
114 /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */
115 if (hop_ptr == 0)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400116 return IB_SMI_HANDLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118 /* C14-13:5 -- Check for unreasonable hop pointer */
Hal Rosenstockde493d42007-04-02 11:24:07 -0400119 return IB_SMI_DISCARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 }
121}
122
123/*
124 * Adjust information for a received SMP
125 * Return 0 if the SMP should be dropped
126 */
Hal Rosenstockde493d42007-04-02 11:24:07 -0400127enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
128 int port_num, int phys_port_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
130 u8 hop_ptr, hop_cnt;
131
132 hop_ptr = smp->hop_ptr;
133 hop_cnt = smp->hop_cnt;
134
135 /* See section 14.2.2.2, Vol 1 IB spec */
136 if (!ib_get_smp_direction(smp)) {
137 /* C14-9:1 -- sender should have incremented hop_ptr */
138 if (hop_cnt && hop_ptr == 0)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400139 return IB_SMI_DISCARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141 /* C14-9:2 -- intermediate hop */
142 if (hop_ptr && hop_ptr < hop_cnt) {
Tom Tucker07ebafb2006-08-03 16:02:42 -0500143 if (node_type != RDMA_NODE_IB_SWITCH)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400144 return IB_SMI_DISCARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
146 smp->return_path[hop_ptr] = port_num;
147 /* smp->hop_ptr updated when sending */
Hal Rosenstockde493d42007-04-02 11:24:07 -0400148 return (smp->initial_path[hop_ptr+1] <= phys_port_cnt ?
149 IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 }
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
Tom Tucker07ebafb2006-08-03 16:02:42 -0500158 return (node_type == RDMA_NODE_IB_SWITCH ||
Hal Rosenstockde493d42007-04-02 11:24:07 -0400159 smp->dr_dlid == IB_LID_PERMISSIVE ?
160 IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 }
162
163 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
164 /* C14-9:5 -- fail unreasonable hop pointer */
Hal Rosenstockde493d42007-04-02 11:24:07 -0400165 return (hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167 } else {
168
169 /* C14-13:1 */
170 if (hop_cnt && hop_ptr == hop_cnt + 1) {
171 smp->hop_ptr--;
172 return (smp->return_path[smp->hop_ptr] ==
Hal Rosenstockde493d42007-04-02 11:24:07 -0400173 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 }
175
176 /* C14-13:2 */
177 if (2 <= hop_ptr && hop_ptr <= hop_cnt) {
Tom Tucker07ebafb2006-08-03 16:02:42 -0500178 if (node_type != RDMA_NODE_IB_SWITCH)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400179 return IB_SMI_DISCARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
181 /* smp->hop_ptr updated when sending */
Hal Rosenstockde493d42007-04-02 11:24:07 -0400182 return (smp->return_path[hop_ptr-1] <= phys_port_cnt ?
183 IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 }
185
186 /* C14-13:3 -- We're at the end of the DR segment of path */
187 if (hop_ptr == 1) {
188 if (smp->dr_slid == IB_LID_PERMISSIVE) {
189 /* giving SMP to SM - update hop_ptr */
190 smp->hop_ptr--;
Hal Rosenstockde493d42007-04-02 11:24:07 -0400191 return IB_SMI_HANDLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 }
193 /* smp->hop_ptr updated when sending */
Hal Rosenstockde493d42007-04-02 11:24:07 -0400194 return (node_type == RDMA_NODE_IB_SWITCH ?
Hal Rosenstock1bae4db2007-05-14 17:21:52 -0400195 IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 }
197
198 /* C14-13:4 -- hop_ptr = 0 -> give to SM */
199 /* C14-13:5 -- Check for unreasonable hop pointer */
Hal Rosenstockde493d42007-04-02 11:24:07 -0400200 return (hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 }
202}
203
Hal Rosenstockde493d42007-04-02 11:24:07 -0400204enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205{
206 u8 hop_ptr, hop_cnt;
207
208 hop_ptr = smp->hop_ptr;
209 hop_cnt = smp->hop_cnt;
210
211 if (!ib_get_smp_direction(smp)) {
212 /* C14-9:2 -- intermediate hop */
213 if (hop_ptr && hop_ptr < hop_cnt)
Hal Rosenstock1bae4db2007-05-14 17:21:52 -0400214 return IB_SMI_FORWARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
216 /* C14-9:3 -- at the end of the DR segment of path */
217 if (hop_ptr == hop_cnt)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400218 return (smp->dr_dlid == IB_LID_PERMISSIVE ?
219 IB_SMI_SEND : IB_SMI_LOCAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
221 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
222 if (hop_ptr == hop_cnt + 1)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400223 return IB_SMI_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 } else {
Hal Rosenstockde493d42007-04-02 11:24:07 -0400225 /* C14-13:2 -- intermediate hop */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 if (2 <= hop_ptr && hop_ptr <= hop_cnt)
Hal Rosenstock1bae4db2007-05-14 17:21:52 -0400227 return IB_SMI_FORWARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
229 /* C14-13:3 -- at the end of the DR segment of path */
230 if (hop_ptr == 1)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400231 return (smp->dr_slid != IB_LID_PERMISSIVE ?
232 IB_SMI_SEND : IB_SMI_LOCAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 }
Hal Rosenstockde493d42007-04-02 11:24:07 -0400234 return IB_SMI_LOCAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235}
Hal Rosenstock1bae4db2007-05-14 17:21:52 -0400236
237/*
238 * Return the forwarding port number from initial_path for outgoing SMP and
239 * from return_path for returning SMP
240 */
241int smi_get_fwd_port(struct ib_smp *smp)
242{
243 return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
244 smp->return_path[smp->hop_ptr-1]);
245}