1 /*******************************************************************************
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright 2014 QLogic Corporation
22 * The contents of this file are subject to the terms of the
23 * QLogic End User License (the "License").
24 * You may not use this file except in compliance with the License.
25 *
26 * You can obtain a copy of the License at
27 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
28 * QLogic_End_User_Software_License.txt
29 * See the License for the specific language governing permissions
30 * and limitations under the License.
31 *
32 *
33 * Module Description:
34 *
35 *
36 * History:
37 * 28/06/11 Shay Haroush Inception.
38 ******************************************************************************/
39
40 #include "lm5710.h"
41 #include "lm_dcbx_mp.h"
42
43 /*******************************************************************************
44 * Constants.
45 ******************************************************************************/
46 #define MAX_NUM_OF_ACTIVE_ETH_CONS_PER_COS(_pdev) LM_SB_CNT(_pdev)
47 #define ETH_CHAIN_COS0_START_OFFSET(_pdev) (0)
48 #define ETH_CHAIN_COS1_START_OFFSET(_pdev) (ETH_CHAIN_COS0_START_OFFSET(_pdev) + LM_SB_CNT(_pdev) + MAX_NON_RSS_CHAINS)
49 #define ETH_CHAIN_COS2_START_OFFSET(_pdev) (ETH_CHAIN_COS1_START_OFFSET(_pdev) + LM_SB_CNT(_pdev))
50
51 /*******************************************************************************
52 * Defines.
53 ******************************************************************************/
54 #define ETH_IS_CHAIN_IN_COS0_RANGE(_pdev, _chain) ( lm_mp_eth_is_chain_in_cosx_range(_pdev, _chain, ETH_CHAIN_COS0_START_OFFSET(_pdev)))
55 #define ETH_IS_CHAIN_IN_COS1_RANGE(_pdev, _chain) ( lm_mp_eth_is_chain_in_cosx_range(_pdev, _chain, ETH_CHAIN_COS1_START_OFFSET(_pdev)))
56 #define ETH_IS_CHAIN_IN_COS2_RANGE(_pdev, _chain) ( lm_mp_eth_is_chain_in_cosx_range(_pdev, _chain, ETH_CHAIN_COS2_START_OFFSET(_pdev)))
57 #define ETH_CID_COSX_END_OFFSET(_pdev, _val) (_val + MAX_NUM_OF_ACTIVE_ETH_CONS_PER_COS(pdev))
58
59 /**
60 * @description
61 * Check if chain is in COS range based on COS start offset.
62 * @param chain
63 * @param cos_start_offset
64 *
65 * @return u8_t
66 */
67 STATIC u8_t
lm_mp_eth_is_chain_in_cosx_range(IN lm_device_t * pdev,IN const u32_t chain,IN const u32_t cos_start_offset)68 lm_mp_eth_is_chain_in_cosx_range(
69 IN lm_device_t *pdev,
70 IN const u32_t chain,
71 IN const u32_t cos_start_offset)
72 {
73 if((cos_start_offset <= chain) &&
74 (chain < ETH_CID_COSX_END_OFFSET(pdev, cos_start_offset)))
75 {
76 return TRUE;
77 }
78 else
79 {
80 return FALSE;
81 }
82 }
83 /**
84 * @description
85 * Get COS number based on chain.
86 * If the chain doesn't belong to a specific COS (e.g. ISCSI L2
87 * chain)
88 * @param pdev
89 * @param chain
90 *
91 * @return u8_t
92 */
93 u8_t
lm_mp_cos_from_chain(IN struct _lm_device_t * pdev,IN const u32_t chain)94 lm_mp_cos_from_chain(IN struct _lm_device_t *pdev,
95 IN const u32_t chain)
96 {
97 // Cos 0 is the default
98 u8_t cos = ETH_MP_MAX_COS_SUPPORTED;
99
100 if (ETH_IS_CHAIN_IN_COS0_RANGE(pdev, chain) )
101 {
102 cos = 0;
103 }
104 else if (ETH_IS_CHAIN_IN_COS1_RANGE(pdev, chain) )
105 {
106 cos = 1;
107 }
108 else if (ETH_IS_CHAIN_IN_COS2_RANGE(pdev, chain) )
109 {
110 cos = 2;
111 }
112 else
113 {
114 DbgMessage(pdev, INFORMi|INFORMl2sp, " lm_mp_cos_from_chain: ");
115 }
116 return cos;
117 }
118 /**
119 * @description
120 * Return chain type.
121 * @param pdev
122 * @param chain
123 *
124 * @return lm_chain_type_t
125 */
126 lm_chain_type_t
lm_mp_get_chain_type(IN struct _lm_device_t * pdev,IN const u32_t chain)127 lm_mp_get_chain_type(IN struct _lm_device_t *pdev,
128 IN const u32_t chain)
129 {
130 const u8_t cos = lm_mp_cos_from_chain(pdev, chain);
131
132 if (0 == cos)
133 {
134 return lm_chain_type_cos_reg;
135 }
136 else if (cos < ETH_MP_MAX_COS_SUPPORTED)
137 {
138 return lm_chain_type_cos_tx_only;
139 }
140 else
141 {
142 return lm_chain_type_not_cos;
143 }
144 }
145 /**
146 * @description
147 * GET L2 chain COS start offset.
148 * @param pdev
149 * @param cos
150 *
151 * @return u8_t
152 */
153 STATIC u8_t
lm_mp_get_eth_chain_cosx_start_offset(IN struct _lm_device_t * pdev,IN const u8_t cos)154 lm_mp_get_eth_chain_cosx_start_offset(IN struct _lm_device_t *pdev,
155 IN const u8_t cos)
156 {
157 u8_t cosx_start_offset = 0;
158
159 switch(cos)
160 {
161 case 0:
162 cosx_start_offset = ETH_CHAIN_COS0_START_OFFSET(pdev);
163 break;
164 case 1:
165 cosx_start_offset = ETH_CHAIN_COS1_START_OFFSET(pdev);
166 break;
167 case 2:
168 cosx_start_offset = ETH_CHAIN_COS2_START_OFFSET(pdev);
169 break;
170 default:
171 DbgBreakMsg("invalid cos");
172 cosx_start_offset = ETH_CHAIN_COS0_START_OFFSET(pdev);
173 }
174
175 return cosx_start_offset;
176 }
177 /**
178 * @description
179 * Get regular chain from chain.
180 * If chain isn't a COS chain(e.g. ISCSI L2) than return
181 * original value.
182 * @param pdev
183 * @param chain
184 *
185 * @return u32_t
186 */
187 u32_t
lm_mp_get_reg_chain_from_chain(IN struct _lm_device_t * pdev,IN u32_t chain)188 lm_mp_get_reg_chain_from_chain(IN struct _lm_device_t *pdev,
189 IN u32_t chain)
190 {
191 const u8_t cos = lm_mp_cos_from_chain(pdev, chain);
192 u8_t cosx_start_offset = 0;
193
194 if( cos >= ETH_MP_MAX_COS_SUPPORTED)
195 {
196 return chain;
197 }
198
199 cosx_start_offset =
200 lm_mp_get_eth_chain_cosx_start_offset(pdev,cos);
201
202 chain -= cosx_start_offset;
203
204 return chain;
205 }
206 /**
207 * @description
208 * Get COS chain from regular chain.
209 * @param pdev
210 * @param chain
211 * @param cos
212 *
213 * @return u32_t
214 */
215 u8_t
lm_mp_get_cos_chain_from_reg_chain(IN struct _lm_device_t * pdev,INOUT u8_t chain,INOUT const u8_t cos)216 lm_mp_get_cos_chain_from_reg_chain(
217 IN struct _lm_device_t *pdev,
218 INOUT u8_t chain,
219 INOUT const u8_t cos)
220 {
221 u8_t cosx_start_offset = 0;
222
223 if( cos >= ETH_MP_MAX_COS_SUPPORTED)
224 {
225 return chain;
226 }
227
228 cosx_start_offset =
229 lm_mp_get_eth_chain_cosx_start_offset(pdev,cos);
230
231 chain += cosx_start_offset;
232
233 return chain;
234 }
235 /**
236 * @description
237 * Get max cos chain used.
238 * @param pdev
239 *
240 * @return u32_t
241 */
242 u8_t
lm_mp_max_cos_chain_used(IN struct _lm_device_t * pdev)243 lm_mp_max_cos_chain_used(
244 IN struct _lm_device_t *pdev)
245 {
246 const u8_t max_num_cos = lm_dcbx_cos_max_num(pdev);
247 const u8_t cosx_start_offset =
248 lm_mp_get_eth_chain_cosx_start_offset(pdev, max_num_cos -1);
249 const u8_t max_chain_used = ETH_CID_COSX_END_OFFSET(pdev, cosx_start_offset);
250
251 DbgBreakIf(FALSE == MM_DCB_MP_L2_IS_ENABLE(pdev));
252 DbgBreakIf(1 == max_num_cos);
253
254 return max_chain_used;
255 }
256