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 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 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 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 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 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 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 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