162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (c) 2004, 2005 Mellanox Technologies Ltd.  All rights reserved.
362306a36Sopenharmony_ci * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
462306a36Sopenharmony_ci * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
562306a36Sopenharmony_ci * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
662306a36Sopenharmony_ci * Copyright (c) 2004-2007 Voltaire Corporation.  All rights reserved.
762306a36Sopenharmony_ci * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
862306a36Sopenharmony_ci * Copyright (c) 2014 Intel Corporation.  All rights reserved.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * This software is available to you under a choice of one of two
1162306a36Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
1262306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
1362306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the
1462306a36Sopenharmony_ci * OpenIB.org BSD license below:
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci *     Redistribution and use in source and binary forms, with or
1762306a36Sopenharmony_ci *     without modification, are permitted provided that the following
1862306a36Sopenharmony_ci *     conditions are met:
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci *      - Redistributions of source code must retain the above
2162306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
2262306a36Sopenharmony_ci *        disclaimer.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci *      - Redistributions in binary form must reproduce the above
2562306a36Sopenharmony_ci *        copyright notice, this list of conditions and the following
2662306a36Sopenharmony_ci *        disclaimer in the documentation and/or other materials
2762306a36Sopenharmony_ci *        provided with the distribution.
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3062306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3162306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
3262306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
3362306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
3462306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3562306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3662306a36Sopenharmony_ci * SOFTWARE.
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#include <rdma/ib_smi.h>
4162306a36Sopenharmony_ci#include "smi.h"
4262306a36Sopenharmony_ci#include "opa_smi.h"
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic enum smi_action __smi_handle_dr_smp_send(bool is_switch, u32 port_num,
4562306a36Sopenharmony_ci						u8 *hop_ptr, u8 hop_cnt,
4662306a36Sopenharmony_ci						const u8 *initial_path,
4762306a36Sopenharmony_ci						const u8 *return_path,
4862306a36Sopenharmony_ci						u8 direction,
4962306a36Sopenharmony_ci						bool dr_dlid_is_permissive,
5062306a36Sopenharmony_ci						bool dr_slid_is_permissive)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	/* See section 14.2.2.2, Vol 1 IB spec */
5362306a36Sopenharmony_ci	/* C14-6 -- valid hop_cnt values are from 0 to 63 */
5462306a36Sopenharmony_ci	if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
5562306a36Sopenharmony_ci		return IB_SMI_DISCARD;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	if (!direction) {
5862306a36Sopenharmony_ci		/* C14-9:1 */
5962306a36Sopenharmony_ci		if (hop_cnt && *hop_ptr == 0) {
6062306a36Sopenharmony_ci			(*hop_ptr)++;
6162306a36Sopenharmony_ci			return (initial_path[*hop_ptr] ==
6262306a36Sopenharmony_ci				port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
6362306a36Sopenharmony_ci		}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci		/* C14-9:2 */
6662306a36Sopenharmony_ci		if (*hop_ptr && *hop_ptr < hop_cnt) {
6762306a36Sopenharmony_ci			if (!is_switch)
6862306a36Sopenharmony_ci				return IB_SMI_DISCARD;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci			/* return_path set when received */
7162306a36Sopenharmony_ci			(*hop_ptr)++;
7262306a36Sopenharmony_ci			return (initial_path[*hop_ptr] ==
7362306a36Sopenharmony_ci				port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
7462306a36Sopenharmony_ci		}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci		/* C14-9:3 -- We're at the end of the DR segment of path */
7762306a36Sopenharmony_ci		if (*hop_ptr == hop_cnt) {
7862306a36Sopenharmony_ci			/* return_path set when received */
7962306a36Sopenharmony_ci			(*hop_ptr)++;
8062306a36Sopenharmony_ci			return (is_switch ||
8162306a36Sopenharmony_ci				dr_dlid_is_permissive ?
8262306a36Sopenharmony_ci				IB_SMI_HANDLE : IB_SMI_DISCARD);
8362306a36Sopenharmony_ci		}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci		/* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
8662306a36Sopenharmony_ci		/* C14-9:5 -- Fail unreasonable hop pointer */
8762306a36Sopenharmony_ci		return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	} else {
9062306a36Sopenharmony_ci		/* C14-13:1 */
9162306a36Sopenharmony_ci		if (hop_cnt && *hop_ptr == hop_cnt + 1) {
9262306a36Sopenharmony_ci			(*hop_ptr)--;
9362306a36Sopenharmony_ci			return (return_path[*hop_ptr] ==
9462306a36Sopenharmony_ci				port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
9562306a36Sopenharmony_ci		}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci		/* C14-13:2 */
9862306a36Sopenharmony_ci		if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
9962306a36Sopenharmony_ci			if (!is_switch)
10062306a36Sopenharmony_ci				return IB_SMI_DISCARD;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci			(*hop_ptr)--;
10362306a36Sopenharmony_ci			return (return_path[*hop_ptr] ==
10462306a36Sopenharmony_ci				port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
10562306a36Sopenharmony_ci		}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci		/* C14-13:3 -- at the end of the DR segment of path */
10862306a36Sopenharmony_ci		if (*hop_ptr == 1) {
10962306a36Sopenharmony_ci			(*hop_ptr)--;
11062306a36Sopenharmony_ci			/* C14-13:3 -- SMPs destined for SM shouldn't be here */
11162306a36Sopenharmony_ci			return (is_switch ||
11262306a36Sopenharmony_ci				dr_slid_is_permissive ?
11362306a36Sopenharmony_ci				IB_SMI_HANDLE : IB_SMI_DISCARD);
11462306a36Sopenharmony_ci		}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci		/* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */
11762306a36Sopenharmony_ci		if (*hop_ptr == 0)
11862306a36Sopenharmony_ci			return IB_SMI_HANDLE;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		/* C14-13:5 -- Check for unreasonable hop pointer */
12162306a36Sopenharmony_ci		return IB_SMI_DISCARD;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci/*
12662306a36Sopenharmony_ci * Fixup a directed route SMP for sending
12762306a36Sopenharmony_ci * Return IB_SMI_DISCARD if the SMP should be discarded
12862306a36Sopenharmony_ci */
12962306a36Sopenharmony_cienum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
13062306a36Sopenharmony_ci				       bool is_switch, u32 port_num)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	return __smi_handle_dr_smp_send(is_switch, port_num,
13362306a36Sopenharmony_ci					&smp->hop_ptr, smp->hop_cnt,
13462306a36Sopenharmony_ci					smp->initial_path,
13562306a36Sopenharmony_ci					smp->return_path,
13662306a36Sopenharmony_ci					ib_get_smp_direction(smp),
13762306a36Sopenharmony_ci					smp->dr_dlid == IB_LID_PERMISSIVE,
13862306a36Sopenharmony_ci					smp->dr_slid == IB_LID_PERMISSIVE);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cienum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp,
14262306a36Sopenharmony_ci				       bool is_switch, u32 port_num)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	return __smi_handle_dr_smp_send(is_switch, port_num,
14562306a36Sopenharmony_ci					&smp->hop_ptr, smp->hop_cnt,
14662306a36Sopenharmony_ci					smp->route.dr.initial_path,
14762306a36Sopenharmony_ci					smp->route.dr.return_path,
14862306a36Sopenharmony_ci					opa_get_smp_direction(smp),
14962306a36Sopenharmony_ci					smp->route.dr.dr_dlid ==
15062306a36Sopenharmony_ci					OPA_LID_PERMISSIVE,
15162306a36Sopenharmony_ci					smp->route.dr.dr_slid ==
15262306a36Sopenharmony_ci					OPA_LID_PERMISSIVE);
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic enum smi_action __smi_handle_dr_smp_recv(bool is_switch, u32 port_num,
15662306a36Sopenharmony_ci						int phys_port_cnt,
15762306a36Sopenharmony_ci						u8 *hop_ptr, u8 hop_cnt,
15862306a36Sopenharmony_ci						const u8 *initial_path,
15962306a36Sopenharmony_ci						u8 *return_path,
16062306a36Sopenharmony_ci						u8 direction,
16162306a36Sopenharmony_ci						bool dr_dlid_is_permissive,
16262306a36Sopenharmony_ci						bool dr_slid_is_permissive)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	/* See section 14.2.2.2, Vol 1 IB spec */
16562306a36Sopenharmony_ci	/* C14-6 -- valid hop_cnt values are from 0 to 63 */
16662306a36Sopenharmony_ci	if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
16762306a36Sopenharmony_ci		return IB_SMI_DISCARD;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	if (!direction) {
17062306a36Sopenharmony_ci		/* C14-9:1 -- sender should have incremented hop_ptr */
17162306a36Sopenharmony_ci		if (hop_cnt && *hop_ptr == 0)
17262306a36Sopenharmony_ci			return IB_SMI_DISCARD;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci		/* C14-9:2 -- intermediate hop */
17562306a36Sopenharmony_ci		if (*hop_ptr && *hop_ptr < hop_cnt) {
17662306a36Sopenharmony_ci			if (!is_switch)
17762306a36Sopenharmony_ci				return IB_SMI_DISCARD;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci			return_path[*hop_ptr] = port_num;
18062306a36Sopenharmony_ci			/* hop_ptr updated when sending */
18162306a36Sopenharmony_ci			return (initial_path[*hop_ptr+1] <= phys_port_cnt ?
18262306a36Sopenharmony_ci				IB_SMI_HANDLE : IB_SMI_DISCARD);
18362306a36Sopenharmony_ci		}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci		/* C14-9:3 -- We're at the end of the DR segment of path */
18662306a36Sopenharmony_ci		if (*hop_ptr == hop_cnt) {
18762306a36Sopenharmony_ci			if (hop_cnt)
18862306a36Sopenharmony_ci				return_path[*hop_ptr] = port_num;
18962306a36Sopenharmony_ci			/* hop_ptr updated when sending */
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci			return (is_switch ||
19262306a36Sopenharmony_ci				dr_dlid_is_permissive ?
19362306a36Sopenharmony_ci				IB_SMI_HANDLE : IB_SMI_DISCARD);
19462306a36Sopenharmony_ci		}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci		/* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
19762306a36Sopenharmony_ci		/* C14-9:5 -- fail unreasonable hop pointer */
19862306a36Sopenharmony_ci		return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	} else {
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci		/* C14-13:1 */
20362306a36Sopenharmony_ci		if (hop_cnt && *hop_ptr == hop_cnt + 1) {
20462306a36Sopenharmony_ci			(*hop_ptr)--;
20562306a36Sopenharmony_ci			return (return_path[*hop_ptr] ==
20662306a36Sopenharmony_ci				port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
20762306a36Sopenharmony_ci		}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		/* C14-13:2 */
21062306a36Sopenharmony_ci		if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
21162306a36Sopenharmony_ci			if (!is_switch)
21262306a36Sopenharmony_ci				return IB_SMI_DISCARD;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci			/* hop_ptr updated when sending */
21562306a36Sopenharmony_ci			return (return_path[*hop_ptr-1] <= phys_port_cnt ?
21662306a36Sopenharmony_ci				IB_SMI_HANDLE : IB_SMI_DISCARD);
21762306a36Sopenharmony_ci		}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci		/* C14-13:3 -- We're at the end of the DR segment of path */
22062306a36Sopenharmony_ci		if (*hop_ptr == 1) {
22162306a36Sopenharmony_ci			if (dr_slid_is_permissive) {
22262306a36Sopenharmony_ci				/* giving SMP to SM - update hop_ptr */
22362306a36Sopenharmony_ci				(*hop_ptr)--;
22462306a36Sopenharmony_ci				return IB_SMI_HANDLE;
22562306a36Sopenharmony_ci			}
22662306a36Sopenharmony_ci			/* hop_ptr updated when sending */
22762306a36Sopenharmony_ci			return (is_switch ? IB_SMI_HANDLE : IB_SMI_DISCARD);
22862306a36Sopenharmony_ci		}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci		/* C14-13:4 -- hop_ptr = 0 -> give to SM */
23162306a36Sopenharmony_ci		/* C14-13:5 -- Check for unreasonable hop pointer */
23262306a36Sopenharmony_ci		return (*hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
23362306a36Sopenharmony_ci	}
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci/*
23762306a36Sopenharmony_ci * Adjust information for a received SMP
23862306a36Sopenharmony_ci * Return IB_SMI_DISCARD if the SMP should be dropped
23962306a36Sopenharmony_ci */
24062306a36Sopenharmony_cienum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch,
24162306a36Sopenharmony_ci				       u32 port_num, int phys_port_cnt)
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
24462306a36Sopenharmony_ci					&smp->hop_ptr, smp->hop_cnt,
24562306a36Sopenharmony_ci					smp->initial_path,
24662306a36Sopenharmony_ci					smp->return_path,
24762306a36Sopenharmony_ci					ib_get_smp_direction(smp),
24862306a36Sopenharmony_ci					smp->dr_dlid == IB_LID_PERMISSIVE,
24962306a36Sopenharmony_ci					smp->dr_slid == IB_LID_PERMISSIVE);
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci/*
25362306a36Sopenharmony_ci * Adjust information for a received SMP
25462306a36Sopenharmony_ci * Return IB_SMI_DISCARD if the SMP should be dropped
25562306a36Sopenharmony_ci */
25662306a36Sopenharmony_cienum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch,
25762306a36Sopenharmony_ci					   u32 port_num, int phys_port_cnt)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt,
26062306a36Sopenharmony_ci					&smp->hop_ptr, smp->hop_cnt,
26162306a36Sopenharmony_ci					smp->route.dr.initial_path,
26262306a36Sopenharmony_ci					smp->route.dr.return_path,
26362306a36Sopenharmony_ci					opa_get_smp_direction(smp),
26462306a36Sopenharmony_ci					smp->route.dr.dr_dlid ==
26562306a36Sopenharmony_ci					OPA_LID_PERMISSIVE,
26662306a36Sopenharmony_ci					smp->route.dr.dr_slid ==
26762306a36Sopenharmony_ci					OPA_LID_PERMISSIVE);
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic enum smi_forward_action __smi_check_forward_dr_smp(u8 hop_ptr, u8 hop_cnt,
27162306a36Sopenharmony_ci							  u8 direction,
27262306a36Sopenharmony_ci							  bool dr_dlid_is_permissive,
27362306a36Sopenharmony_ci							  bool dr_slid_is_permissive)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	if (!direction) {
27662306a36Sopenharmony_ci		/* C14-9:2 -- intermediate hop */
27762306a36Sopenharmony_ci		if (hop_ptr && hop_ptr < hop_cnt)
27862306a36Sopenharmony_ci			return IB_SMI_FORWARD;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci		/* C14-9:3 -- at the end of the DR segment of path */
28162306a36Sopenharmony_ci		if (hop_ptr == hop_cnt)
28262306a36Sopenharmony_ci			return (dr_dlid_is_permissive ?
28362306a36Sopenharmony_ci				IB_SMI_SEND : IB_SMI_LOCAL);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci		/* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
28662306a36Sopenharmony_ci		if (hop_ptr == hop_cnt + 1)
28762306a36Sopenharmony_ci			return IB_SMI_SEND;
28862306a36Sopenharmony_ci	} else {
28962306a36Sopenharmony_ci		/* C14-13:2  -- intermediate hop */
29062306a36Sopenharmony_ci		if (2 <= hop_ptr && hop_ptr <= hop_cnt)
29162306a36Sopenharmony_ci			return IB_SMI_FORWARD;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci		/* C14-13:3 -- at the end of the DR segment of path */
29462306a36Sopenharmony_ci		if (hop_ptr == 1)
29562306a36Sopenharmony_ci			return (!dr_slid_is_permissive ?
29662306a36Sopenharmony_ci				IB_SMI_SEND : IB_SMI_LOCAL);
29762306a36Sopenharmony_ci	}
29862306a36Sopenharmony_ci	return IB_SMI_LOCAL;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cienum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
30562306a36Sopenharmony_ci					  ib_get_smp_direction(smp),
30662306a36Sopenharmony_ci					  smp->dr_dlid == IB_LID_PERMISSIVE,
30762306a36Sopenharmony_ci					  smp->dr_slid == IB_LID_PERMISSIVE);
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cienum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
31362306a36Sopenharmony_ci					  opa_get_smp_direction(smp),
31462306a36Sopenharmony_ci					  smp->route.dr.dr_dlid ==
31562306a36Sopenharmony_ci					  OPA_LID_PERMISSIVE,
31662306a36Sopenharmony_ci					  smp->route.dr.dr_slid ==
31762306a36Sopenharmony_ci					  OPA_LID_PERMISSIVE);
31862306a36Sopenharmony_ci}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci/*
32162306a36Sopenharmony_ci * Return the forwarding port number from initial_path for outgoing SMP and
32262306a36Sopenharmony_ci * from return_path for returning SMP
32362306a36Sopenharmony_ci */
32462306a36Sopenharmony_ciint smi_get_fwd_port(struct ib_smp *smp)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
32762306a36Sopenharmony_ci		smp->return_path[smp->hop_ptr-1]);
32862306a36Sopenharmony_ci}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci/*
33162306a36Sopenharmony_ci * Return the forwarding port number from initial_path for outgoing SMP and
33262306a36Sopenharmony_ci * from return_path for returning SMP
33362306a36Sopenharmony_ci */
33462306a36Sopenharmony_ciint opa_smi_get_fwd_port(struct opa_smp *smp)
33562306a36Sopenharmony_ci{
33662306a36Sopenharmony_ci	return !opa_get_smp_direction(smp) ? smp->route.dr.initial_path[smp->hop_ptr+1] :
33762306a36Sopenharmony_ci		smp->route.dr.return_path[smp->hop_ptr-1];
33862306a36Sopenharmony_ci}
339