1 /* 2 * Copyright 2008-2012 Freescale Semiconductor Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * * Neither the name of Freescale Semiconductor nor the 12 * names of its contributors may be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * 16 * ALTERNATIVELY, this software may be distributed under the terms of the 17 * GNU General Public License ("GPL") as published by the Free Software 18 * Foundation, either version 2 of that License or (at your option) any 19 * later version. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34 /****************************************************************************** 35 @File fm_pcd.c 36 37 @Description FM PCD ... 38 *//***************************************************************************/ 39 #include <linux/math64.h> 40 #include "std_ext.h" 41 #include "error_ext.h" 42 #include "string_ext.h" 43 #include "debug_ext.h" 44 #include "net_ext.h" 45 46 #include "fm_common.h" 47 #include "fm_pcd.h" 48 #include "fm_pcd_ipc.h" 49 #include "fm_prs.h" 50 #include "fsl_fman_prs.h" 51 52 53 static void PcdPrsErrorException(t_Handle h_FmPcd) 54 { 55 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; 56 uint32_t event, ev_mask; 57 struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; 58 59 ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); 60 ev_mask = fman_prs_get_err_ev_mask(PrsRegs); 61 62 event = fman_prs_get_err_event(PrsRegs, ev_mask); 63 64 fman_prs_ack_err_event(PrsRegs, event); 65 66 DBG(TRACE, ("parser error - 0x%08x\n",event)); 67 68 if(event & FM_PCD_PRS_DOUBLE_ECC) 69 p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC); 70 } 71 72 static void PcdPrsException(t_Handle h_FmPcd) 73 { 74 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; 75 uint32_t event, ev_mask; 76 struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; 77 78 ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); 79 ev_mask = fman_prs_get_expt_ev_mask(PrsRegs); 80 event = fman_prs_get_expt_event(PrsRegs, ev_mask); 81 82 ASSERT_COND(event & FM_PCD_PRS_SINGLE_ECC); 83 84 DBG(TRACE, ("parser event - 0x%08x\n",event)); 85 86 fman_prs_ack_expt_event(PrsRegs, event); 87 88 p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC); 89 } 90 91 t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams) 92 { 93 t_FmPcdPrs *p_FmPcdPrs; 94 uintptr_t baseAddr; 95 96 UNUSED(p_FmPcd); 97 UNUSED(p_FmPcdParams); 98 99 p_FmPcdPrs = (t_FmPcdPrs *) XX_Malloc(sizeof(t_FmPcdPrs)); 100 if (!p_FmPcdPrs) 101 { 102 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Parser structure allocation FAILED")); 103 return NULL; 104 } 105 memset(p_FmPcdPrs, 0, sizeof(t_FmPcdPrs)); 106 fman_prs_defconfig(&p_FmPcd->p_FmPcdDriverParam->dfltCfg); 107 108 if (p_FmPcd->guestId == NCSW_MASTER_ID) 109 { 110 baseAddr = FmGetPcdPrsBaseAddr(p_FmPcdParams->h_Fm); 111 p_FmPcdPrs->p_SwPrsCode = (uint32_t *)UINT_TO_PTR(baseAddr); 112 p_FmPcdPrs->p_FmPcdPrsRegs = (struct fman_prs_regs *)UINT_TO_PTR(baseAddr + PRS_REGS_OFFSET); 113 } 114 115 p_FmPcdPrs->fmPcdPrsPortIdStatistics = p_FmPcd->p_FmPcdDriverParam->dfltCfg.port_id_stat; 116 p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = p_FmPcd->p_FmPcdDriverParam->dfltCfg.max_prs_cyc_lim; 117 p_FmPcd->exceptions |= p_FmPcd->p_FmPcdDriverParam->dfltCfg.prs_exceptions; 118 119 return p_FmPcdPrs; 120 } 121 122 #if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) 123 static uint8_t swPrsPatch[] = SW_PRS_UDP_LITE_PATCH; 124 #else 125 static uint8_t swPrsPatch[] = SW_PRS_OFFLOAD_PATCH; 126 #endif /* FM_CAPWAP_SUPPORT */ 127 128 t_Error PrsInit(t_FmPcd *p_FmPcd) 129 { 130 t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam; 131 uint32_t *p_TmpCode; 132 uint32_t *p_LoadTarget = (uint32_t *)PTR_MOVE(p_FmPcd->p_FmPcdPrs->p_SwPrsCode, 133 FM_PCD_SW_PRS_SIZE-FM_PCD_PRS_SW_PATCHES_SIZE); 134 struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; 135 uint32_t i; 136 137 ASSERT_COND(sizeof(swPrsPatch) <= (FM_PCD_PRS_SW_PATCHES_SIZE-FM_PCD_PRS_SW_TAIL_SIZE)); 138 139 /* nothing to do in guest-partition */ 140 if (p_FmPcd->guestId != NCSW_MASTER_ID) 141 return E_OK; 142 143 p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(sizeof(swPrsPatch),4), 0, sizeof(uint32_t)); 144 if (!p_TmpCode) 145 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED")); 146 memset((uint8_t *)p_TmpCode, 0, ROUND_UP(sizeof(swPrsPatch),4)); 147 memcpy((uint8_t *)p_TmpCode, (uint8_t *)swPrsPatch, sizeof(swPrsPatch)); 148 149 fman_prs_init(PrsRegs, &p_Param->dfltCfg); 150 151 /* register even if no interrupts enabled, to allow future enablement */ 152 FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR, PcdPrsErrorException, p_FmPcd); 153 154 /* register even if no interrupts enabled, to allow future enablement */ 155 FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL, PcdPrsException, p_FmPcd); 156 157 if(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC) 158 FmEnableRamsEcc(p_FmPcd->h_Fm); 159 160 if(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC) 161 FmEnableRamsEcc(p_FmPcd->h_Fm); 162 163 /* load sw parser Ip-Frag patch */ 164 for (i=0; i<DIV_CEIL(sizeof(swPrsPatch), 4); i++) 165 WRITE_UINT32(p_LoadTarget[i], GET_UINT32(p_TmpCode[i])); 166 167 XX_FreeSmart(p_TmpCode); 168 169 return E_OK; 170 } 171 172 void PrsFree(t_FmPcd *p_FmPcd) 173 { 174 ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); 175 FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR); 176 /* register even if no interrupts enabled, to allow future enablement */ 177 FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL); 178 } 179 180 void PrsEnable(t_FmPcd *p_FmPcd) 181 { 182 struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; 183 184 ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); 185 fman_prs_enable(PrsRegs); 186 } 187 188 void PrsDisable(t_FmPcd *p_FmPcd) 189 { 190 struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; 191 192 ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); 193 fman_prs_disable(PrsRegs); 194 } 195 196 int PrsIsEnabled(t_FmPcd *p_FmPcd) 197 { 198 struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; 199 200 ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); 201 return fman_prs_is_enabled(PrsRegs); 202 } 203 204 t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include) 205 { 206 struct fman_prs_regs *PrsRegs; 207 uint32_t bitMask = 0; 208 uint8_t prsPortId; 209 210 SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE); 211 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 212 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); 213 214 PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; 215 216 GET_FM_PCD_PRS_PORT_ID(prsPortId, hardwarePortId); 217 GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId); 218 219 if (include) 220 p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics |= bitMask; 221 else 222 p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics &= ~bitMask; 223 224 fman_prs_set_stst_port_msk(PrsRegs, 225 p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics); 226 227 return E_OK; 228 } 229 230 t_Error FmPcdPrsIncludePortInStatistics(t_Handle h_FmPcd, uint8_t hardwarePortId, bool include) 231 { 232 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; 233 t_Error err; 234 235 SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE); 236 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 237 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); 238 239 if ((p_FmPcd->guestId != NCSW_MASTER_ID) && 240 p_FmPcd->h_IpcSession) 241 { 242 t_FmPcdIpcPrsIncludePort prsIncludePortParams; 243 t_FmPcdIpcMsg msg; 244 245 prsIncludePortParams.hardwarePortId = hardwarePortId; 246 prsIncludePortParams.include = include; 247 memset(&msg, 0, sizeof(msg)); 248 msg.msgId = FM_PCD_PRS_INC_PORT_STATS; 249 memcpy(msg.msgBody, &prsIncludePortParams, sizeof(prsIncludePortParams)); 250 err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, 251 (uint8_t*)&msg, 252 sizeof(msg.msgId) +sizeof(prsIncludePortParams), 253 NULL, 254 NULL, 255 NULL, 256 NULL); 257 if (err != E_OK) 258 RETURN_ERROR(MAJOR, err, NO_MSG); 259 return E_OK; 260 } 261 else if (p_FmPcd->guestId != NCSW_MASTER_ID) 262 RETURN_ERROR(MINOR, E_NOT_SUPPORTED, 263 ("running in guest-mode without IPC!")); 264 265 return PrsIncludePortInStatistics(p_FmPcd, hardwarePortId, include); 266 } 267 268 uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr) 269 { 270 t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; 271 t_FmPcdPrsLabelParams *p_Label; 272 int i; 273 274 SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, 0); 275 SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE, 0); 276 277 if ((p_FmPcd->guestId != NCSW_MASTER_ID) && 278 p_FmPcd->h_IpcSession) 279 { 280 t_Error err = E_OK; 281 t_FmPcdIpcSwPrsLable labelParams; 282 t_FmPcdIpcMsg msg; 283 uint32_t prsOffset = 0; 284 t_FmPcdIpcReply reply; 285 uint32_t replyLength; 286 287 memset(&reply, 0, sizeof(reply)); 288 memset(&msg, 0, sizeof(msg)); 289 labelParams.enumHdr = (uint32_t)hdr; 290 labelParams.indexPerHdr = indexPerHdr; 291 msg.msgId = FM_PCD_GET_SW_PRS_OFFSET; 292 memcpy(msg.msgBody, &labelParams, sizeof(labelParams)); 293 replyLength = sizeof(uint32_t) + sizeof(uint32_t); 294 err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, 295 (uint8_t*)&msg, 296 sizeof(msg.msgId) +sizeof(labelParams), 297 (uint8_t*)&reply, 298 &replyLength, 299 NULL, 300 NULL); 301 if (err != E_OK) 302 RETURN_ERROR(MAJOR, err, NO_MSG); 303 if (replyLength != sizeof(uint32_t) + sizeof(uint32_t)) 304 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); 305 306 memcpy((uint8_t*)&prsOffset, reply.replyBody, sizeof(uint32_t)); 307 return prsOffset; 308 } 309 else if (p_FmPcd->guestId != NCSW_MASTER_ID) 310 RETURN_ERROR(MINOR, E_NOT_SUPPORTED, 311 ("running in guest-mode without IPC!")); 312 313 ASSERT_COND(p_FmPcd->p_FmPcdPrs->currLabel < FM_PCD_PRS_NUM_OF_LABELS); 314 315 for (i=0; i<p_FmPcd->p_FmPcdPrs->currLabel; i++) 316 { 317 p_Label = &p_FmPcd->p_FmPcdPrs->labelsTable[i]; 318 319 if ((hdr == p_Label->hdr) && (indexPerHdr == p_Label->indexPerHdr)) 320 return p_Label->instructionOffset; 321 } 322 323 REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Sw Parser attachment Not found")); 324 return (uint32_t)ILLEGAL_BASE; 325 } 326 327 void FM_PCD_SetPrsStatistics(t_Handle h_FmPcd, bool enable) 328 { 329 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 330 struct fman_prs_regs *PrsRegs; 331 332 SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE); 333 SANITY_CHECK_RETURN(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); 334 335 PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; 336 337 338 if(p_FmPcd->guestId != NCSW_MASTER_ID) 339 { 340 REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPrsStatistics - guest mode!")); 341 return; 342 } 343 344 fman_prs_set_stst(PrsRegs, enable); 345 } 346 347 t_Error FM_PCD_PrsLoadSw(t_Handle h_FmPcd, t_FmPcdPrsSwParams *p_SwPrs) 348 { 349 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 350 uint32_t *p_LoadTarget; 351 uint32_t *p_TmpCode; 352 int i; 353 354 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 355 SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); 356 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_STATE); 357 SANITY_CHECK_RETURN_ERROR(p_SwPrs, E_INVALID_HANDLE); 358 SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_HANDLE); 359 360 if (p_FmPcd->guestId != NCSW_MASTER_ID) 361 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode!")); 362 363 if (!p_SwPrs->override) 364 { 365 if(p_FmPcd->p_FmPcdPrs->p_CurrSwPrs > p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4) 366 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SW parser base must be larger than current loaded code")); 367 } 368 else 369 p_FmPcd->p_FmPcdPrs->currLabel = 0; 370 371 if (p_SwPrs->size > FM_PCD_SW_PRS_SIZE - FM_PCD_PRS_SW_TAIL_SIZE - p_SwPrs->base*2) 372 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_SwPrs->size may not be larger than MAX_SW_PRS_CODE_SIZE")); 373 374 if (p_FmPcd->p_FmPcdPrs->currLabel + p_SwPrs->numOfLabels > FM_PCD_PRS_NUM_OF_LABELS) 375 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceeded number of labels allowed ")); 376 377 p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(p_SwPrs->size,4), 0, sizeof(uint32_t)); 378 if (!p_TmpCode) 379 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED")); 380 memset((uint8_t *)p_TmpCode, 0, ROUND_UP(p_SwPrs->size,4)); 381 memcpy((uint8_t *)p_TmpCode, p_SwPrs->p_Code, p_SwPrs->size); 382 383 /* save sw parser labels */ 384 memcpy(&p_FmPcd->p_FmPcdPrs->labelsTable[p_FmPcd->p_FmPcdPrs->currLabel], 385 p_SwPrs->labelsTable, 386 p_SwPrs->numOfLabels*sizeof(t_FmPcdPrsLabelParams)); 387 p_FmPcd->p_FmPcdPrs->currLabel += p_SwPrs->numOfLabels; 388 389 /* load sw parser code */ 390 p_LoadTarget = p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4; 391 392 for(i=0; i<DIV_CEIL(p_SwPrs->size, 4); i++) 393 WRITE_UINT32(p_LoadTarget[i], GET_UINT32(p_TmpCode[i])); 394 395 p_FmPcd->p_FmPcdPrs->p_CurrSwPrs = 396 p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4 + ROUND_UP(p_SwPrs->size,4); 397 398 /* copy data parameters */ 399 for (i=0;i<FM_PCD_PRS_NUM_OF_HDRS;i++) 400 WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+PRS_SW_DATA/4+i), p_SwPrs->swPrsDataParams[i]); 401 402 /* Clear last 4 bytes */ 403 WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+(PRS_SW_DATA-FM_PCD_PRS_SW_TAIL_SIZE)/4), 0); 404 405 XX_FreeSmart(p_TmpCode); 406 407 return E_OK; 408 } 409 410 t_Error FM_PCD_ConfigPrsMaxCycleLimit(t_Handle h_FmPcd,uint16_t value) 411 { 412 t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; 413 414 SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); 415 SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); 416 417 if(p_FmPcd->guestId != NCSW_MASTER_ID) 418 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPrsMaxCycleLimit - guest mode!")); 419 420 p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = value; 421 422 return E_OK; 423 } 424