1 /****************************************************************************** 2 3 � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. 4 All rights reserved. 5 6 This is proprietary source code of Freescale Semiconductor Inc., 7 and its use is subject to the NetComm Device Drivers EULA. 8 The copyright notice above does not evidence any actual or intended 9 publication of such source code. 10 11 ALTERNATIVELY, redistribution and use in source and binary forms, with 12 or without modification, are permitted provided that the following 13 conditions are met: 14 * Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 * Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in the 18 documentation and/or other materials provided with the distribution. 19 * Neither the name of Freescale Semiconductor nor the 20 names of its contributors may be used to endorse or promote products 21 derived from this software without specific prior written permission. 22 23 THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 35 **************************************************************************/ 36 /****************************************************************************** 37 @File qm.c 38 39 @Description QM & Portal implementation 40 *//***************************************************************************/ 41 42 #include <sys/cdefs.h> 43 #include <sys/types.h> 44 #include <machine/atomic.h> 45 #include "error_ext.h" 46 #include "std_ext.h" 47 #include "string_ext.h" 48 #include "sprint_ext.h" 49 #include "mm_ext.h" 50 #include "core_ext.h" 51 #include "debug_ext.h" 52 53 #include "qm.h" 54 55 56 static volatile bool blockingFlag = FALSE; 57 static void QmIpcMsgCompletionCB(t_Handle h_Module, 58 uint8_t *p_Msg, 59 uint8_t *p_Reply, 60 uint32_t replyLength, 61 t_Error status) 62 { 63 SANITY_CHECK_RETURN(h_Module, E_INVALID_HANDLE); 64 65 UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status);UNUSED(h_Module); 66 blockingFlag = FALSE; 67 } 68 69 static t_Error QmHandleIpcMsgCB(t_Handle h_Qm, 70 uint8_t *p_Msg, 71 uint32_t msgLength, 72 uint8_t *p_Reply, 73 uint32_t *p_ReplyLength) 74 { 75 t_Qm *p_Qm = (t_Qm*)h_Qm; 76 t_QmIpcMsg *p_IpcMsg = (t_QmIpcMsg*)p_Msg; 77 t_QmIpcReply *p_IpcReply = (t_QmIpcReply *)p_Reply; 78 79 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 80 SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE); 81 82 #ifdef DISABLE_SANITY_CHECKS 83 UNUSED(msgLength); 84 #endif /* DISABLE_SANITY_CHECKS */ 85 86 ASSERT_COND(p_IpcMsg); 87 88 memset(p_IpcReply, 0, (sizeof(uint8_t) * QM_IPC_MAX_REPLY_SIZE)); 89 *p_ReplyLength = 0; 90 91 switch(p_IpcMsg->msgId) 92 { 93 case (QM_MASTER_IS_ALIVE): 94 *(uint8_t*)p_IpcReply->replyBody = 1; 95 *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); 96 break; 97 case (QM_FORCE_FQID): 98 { 99 t_QmIpcFqidParams ipcFqid; 100 uint32_t fqid; 101 102 memcpy((uint8_t*)&ipcFqid, p_IpcMsg->msgBody, sizeof(t_QmIpcFqidParams)); 103 fqid = QmFqidGet(p_Qm, ipcFqid.size, 1, TRUE, ipcFqid.fqid); 104 memcpy(p_IpcReply->replyBody, (uint8_t*)&fqid, sizeof(uint32_t)); 105 *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); 106 break; 107 } 108 case (QM_PUT_FQID): 109 { 110 t_Error err; 111 t_QmIpcFqidParams ipcFqid; 112 113 memcpy((uint8_t*)&ipcFqid, p_IpcMsg->msgBody, sizeof(t_QmIpcFqidParams)); 114 if ((err = QmFqidPut(p_Qm, ipcFqid.fqid)) != E_OK) 115 REPORT_ERROR(MINOR, err, NO_MSG); 116 break; 117 } 118 case (QM_GET_COUNTER): 119 { 120 t_QmIpcGetCounter ipcCounter; 121 uint32_t count; 122 123 memcpy((uint8_t*)&ipcCounter, p_IpcMsg->msgBody, sizeof(t_QmIpcGetCounter)); 124 count = QmGetCounter(p_Qm, (e_QmInterModuleCounters)ipcCounter.enumId); 125 memcpy(p_IpcReply->replyBody, (uint8_t*)&count, sizeof(uint32_t)); 126 *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); 127 break; 128 } 129 case (QM_GET_SET_PORTAL_PARAMS): 130 { 131 t_Error err; 132 t_QmIpcPortalInitParams ipcPortalInitParams; 133 t_QmInterModulePortalInitParams portalInitParams; 134 135 memcpy((uint8_t*)&ipcPortalInitParams, p_IpcMsg->msgBody, sizeof(t_QmIpcPortalInitParams)); 136 portalInitParams.portalId = ipcPortalInitParams.portalId; 137 portalInitParams.stashDestQueue = ipcPortalInitParams.stashDestQueue; 138 portalInitParams.liodn = ipcPortalInitParams.liodn; 139 portalInitParams.dqrrLiodn = ipcPortalInitParams.dqrrLiodn; 140 portalInitParams.fdFqLiodn = ipcPortalInitParams.fdFqLiodn; 141 if ((err = QmGetSetPortalParams(p_Qm, &portalInitParams)) != E_OK) 142 REPORT_ERROR(MINOR, err, NO_MSG); 143 break; 144 } 145 case (QM_GET_REVISION): 146 { 147 t_QmRevisionInfo revInfo; 148 t_QmIpcRevisionInfo ipcRevInfo; 149 150 p_IpcReply->error = (uint32_t)QmGetRevision(h_Qm, &revInfo); 151 ipcRevInfo.majorRev = revInfo.majorRev; 152 ipcRevInfo.minorRev = revInfo.minorRev; 153 memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcRevInfo, sizeof(t_QmIpcRevisionInfo)); 154 *p_ReplyLength = sizeof(uint32_t) + sizeof(t_QmIpcRevisionInfo); 155 break; 156 } 157 default: 158 *p_ReplyLength = 0; 159 RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); 160 } 161 return E_OK; 162 } 163 164 static t_Error CheckQmParameters(t_Qm *p_Qm) 165 { 166 if ((p_Qm->p_QmDriverParams->partFqidBase + p_Qm->p_QmDriverParams->partNumOfFqids) > QM_MAX_NUM_OF_FQIDS) 167 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partFqidBase+partNumOfFqids out of range!!!")); 168 if ((p_Qm->partCgsBase + p_Qm->partNumOfCgs) > QM_MAX_NUM_OF_CGS) 169 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partCgsBase+partNumOfCgs out of range!!!")); 170 171 if (p_Qm->guestId == NCSW_MASTER_ID) 172 { 173 uint64_t phyAddr; 174 175 phyAddr = XX_VirtToPhys(UINT_TO_PTR(p_Qm->p_QmDriverParams->swPortalsBaseAddress)); 176 177 if (phyAddr & 0x00000000001fffffLL) 178 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("swPortalsBaseAddress isn't properly aligned")); 179 if (!p_Qm->p_QmDriverParams->rtFramesDepth) 180 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rtFramesDepth must be larger than '0'!!!")); 181 if (p_Qm->p_QmDriverParams->rtFramesDepth > ((16*MEGABYTE)*3)) 182 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rtFramesDepth must be equal or smaller than 48MB!!!")); 183 if (!p_Qm->p_QmDriverParams->totalNumOfFqids) 184 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfFqids must be larger than '0'!!!")); 185 if (p_Qm->p_QmDriverParams->totalNumOfFqids > (16*MEGABYTE)) 186 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfFqids must be equal or smaller than 16MB!!!")); 187 if(!p_Qm->f_Exception) 188 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); 189 } 190 191 return E_OK; 192 } 193 194 static t_Error QmInitPfdr(t_Qm *p_Qm, uint32_t pfdr_start, uint32_t num) 195 { 196 uint8_t rslt; 197 uint32_t timeout = 100000; 198 199 ASSERT_COND(p_Qm); 200 201 ASSERT_COND(pfdr_start && !(pfdr_start & 7) && !(num & 7) && num); 202 203 /* Make sure te command interface is 'idle' */ 204 rslt = MCR_get_rslt(GET_UINT32(p_Qm->p_QmRegs->mcr)); 205 if (!MCR_rslt_idle(rslt)) 206 RETURN_ERROR(CRITICAL,E_INVALID_STATE,("QMAN_MCR isn't idle")); 207 208 /* Write the MCR command params then the verb */ 209 WRITE_UINT32(p_Qm->p_QmRegs->mcp0, pfdr_start); 210 /* TODO: remove this - it's a workaround for a model bug that is 211 * corrected in more recent versions. We use the workaround until 212 * everyone has upgraded. */ 213 WRITE_UINT32(p_Qm->p_QmRegs->mcp1, (pfdr_start + num - 16)); 214 WRITE_UINT32(p_Qm->p_QmRegs->mcp1, (pfdr_start + num - 1)); 215 216 mb(); 217 WRITE_UINT32(p_Qm->p_QmRegs->mcr, MCR_INIT_PFDR); 218 219 /* Poll for the result */ 220 do { 221 XX_UDelay(1); 222 rslt = MCR_get_rslt(GET_UINT32(p_Qm->p_QmRegs->mcr)); 223 } while(!MCR_rslt_idle(rslt) && --timeout); 224 225 if (MCR_rslt_ok(rslt)) 226 return E_OK; 227 WRITE_UINT32(p_Qm->p_QmRegs->mcr, 0); 228 if (!timeout) 229 RETURN_ERROR(MAJOR, E_TIMEOUT, NO_MSG); 230 if (MCR_rslt_eaccess(rslt)) 231 RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); 232 if (MCR_rslt_inval(rslt)) 233 RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); 234 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unexpected result from MCR_INIT_PFDR: %02x\n", rslt)); 235 } 236 237 static __inline__ void QmSetWqScheduling(t_Qm *p_Qm, 238 e_QmWqClass wqClass, 239 uint8_t csElev, 240 uint8_t csw2, 241 uint8_t csw3, 242 uint8_t csw4, 243 uint8_t csw5, 244 uint8_t csw6, 245 uint8_t csw7) 246 { 247 ASSERT_COND(p_Qm); 248 249 WRITE_UINT32(p_Qm->p_QmRegs->wq_cs_cfg[wqClass], 250 (uint32_t)(((csElev & 0xff) << 24) | 251 ((csw2 & 0x7) << 20) | 252 ((csw3 & 0x7) << 16) | 253 ((csw4 & 0x7) << 12) | 254 ((csw5 & 0x7) << 8) | 255 ((csw6 & 0x7) << 4) | 256 (csw7 & 0x7))); 257 } 258 259 static uint32_t ReserveFqids(t_Qm *p_Qm, uint32_t size, uint32_t alignment, bool force, uint32_t base) 260 { 261 uint64_t ans; 262 uint32_t intFlags; 263 264 intFlags = XX_LockIntrSpinlock(p_Qm->lock); 265 if (force) 266 ans = MM_GetForce(p_Qm->h_FqidMm, 267 (uint64_t)base, 268 (uint64_t)size, 269 "QM FQID MEM"); 270 else 271 ans = MM_Get(p_Qm->h_FqidMm, 272 (uint64_t)size, 273 alignment, 274 "QM FQID MEM"); 275 if (ans == ILLEGAL_BASE) 276 { 277 XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); 278 return (uint32_t)ans; 279 } 280 base = (uint32_t)ans; 281 ans = MM_GetForce(p_Qm->h_RsrvFqidMm, 282 (uint64_t)base, 283 (uint64_t)size, 284 "QM rsrv FQID MEM"); 285 if (ans == ILLEGAL_BASE) 286 { 287 MM_Put(p_Qm->h_FqidMm, (uint64_t)base); 288 XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); 289 return (uint32_t)ans; 290 } 291 XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); 292 293 return (uint32_t)base; 294 } 295 296 static void FreeInitResources(t_Qm *p_Qm) 297 { 298 if (p_Qm->p_FqdBase) 299 XX_FreeSmart(p_Qm->p_FqdBase); 300 if (p_Qm->p_PfdrBase) 301 XX_FreeSmart(p_Qm->p_PfdrBase); 302 if (p_Qm->h_Session) 303 XX_IpcFreeSession(p_Qm->h_Session); 304 if (p_Qm->h_RsrvFqidMm) 305 MM_Free(p_Qm->h_RsrvFqidMm); 306 if (p_Qm->h_FqidMm) 307 MM_Free(p_Qm->h_FqidMm); 308 } 309 310 311 /****************************************/ 312 /* Inter-Module functions */ 313 /****************************************/ 314 315 uint32_t QmGetCounter(t_Handle h_Qm, e_QmInterModuleCounters counter) 316 { 317 t_Qm *p_Qm = (t_Qm*)h_Qm; 318 319 SANITY_CHECK_RETURN_VALUE(p_Qm, E_INVALID_HANDLE, 0); 320 SANITY_CHECK_RETURN_VALUE((((p_Qm->guestId == NCSW_MASTER_ID) && p_Qm->p_QmRegs) || 321 (p_Qm->guestId != NCSW_MASTER_ID)), E_INVALID_STATE, 0); 322 323 if ((p_Qm->guestId == NCSW_MASTER_ID) || 324 (!p_Qm->h_Session && p_Qm->p_QmRegs)) 325 { 326 switch(counter) 327 { 328 case(e_QM_IM_COUNTERS_SFDR_IN_USE): 329 return GET_UINT32(p_Qm->p_QmRegs->sfdr_in_use); 330 case(e_QM_IM_COUNTERS_PFDR_IN_USE): 331 return (p_Qm->numOfPfdr - GET_UINT32(p_Qm->p_QmRegs->pfdr_fpc)); 332 case(e_QM_IM_COUNTERS_PFDR_FREE_POOL): 333 return (GET_UINT32(p_Qm->p_QmRegs->pfdr_fpc) - GET_UINT32(p_Qm->p_QmRegs->pfdr_cfg)); 334 default: 335 break; 336 } 337 /* should never get here */ 338 ASSERT_COND(FALSE); 339 } 340 else if (p_Qm->h_Session) 341 { 342 t_QmIpcMsg msg; 343 t_QmIpcReply reply; 344 t_QmIpcGetCounter ipcCounter; 345 uint32_t replyLength, count; 346 t_Error errCode = E_OK; 347 348 memset(&msg, 0, sizeof(t_QmIpcMsg)); 349 memset(&reply, 0, sizeof(t_QmIpcReply)); 350 ipcCounter.enumId = (uint32_t)counter; 351 msg.msgId = QM_GET_COUNTER; 352 memcpy(msg.msgBody, &ipcCounter, sizeof(t_QmIpcGetCounter)); 353 replyLength = sizeof(uint32_t) + sizeof(uint32_t); 354 if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, 355 (uint8_t*)&msg, 356 sizeof(msg.msgId) + sizeof(t_QmIpcGetCounter), 357 (uint8_t*)&reply, 358 &replyLength, 359 NULL, 360 NULL)) != E_OK) 361 REPORT_ERROR(MAJOR, errCode, NO_MSG); 362 if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) 363 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); 364 if ((errCode == E_OK) && (replyLength == (sizeof(uint32_t) + sizeof(uint32_t)))) 365 { 366 memcpy((uint8_t*)&count, reply.replyBody, sizeof(uint32_t)); 367 return count; 368 } 369 } 370 else 371 REPORT_ERROR(WARNING, E_NOT_SUPPORTED, 372 ("In 'guest', either IPC or 'baseAddress' is required!")); 373 374 return 0; 375 } 376 377 t_Error QmGetRevision(t_Handle h_Qm, t_QmRevisionInfo *p_QmRevisionInfo) 378 { 379 t_Qm *p_Qm = (t_Qm *)h_Qm; 380 uint32_t tmpReg; 381 382 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 383 SANITY_CHECK_RETURN_ERROR(p_QmRevisionInfo, E_NULL_POINTER); 384 SANITY_CHECK_RETURN_ERROR((((p_Qm->guestId == NCSW_MASTER_ID) && p_Qm->p_QmRegs) || 385 (p_Qm->guestId != NCSW_MASTER_ID)), E_INVALID_STATE); 386 387 if ((p_Qm->guestId == NCSW_MASTER_ID) || 388 (!p_Qm->h_Session && p_Qm->p_QmRegs)) 389 { 390 /* read revision register 1 */ 391 tmpReg = GET_UINT32(p_Qm->p_QmRegs->ip_rev_1); 392 p_QmRevisionInfo->majorRev = (uint8_t)((tmpReg & REV1_MAJOR_MASK) >> REV1_MAJOR_SHIFT); 393 p_QmRevisionInfo->minorRev = (uint8_t)((tmpReg & REV1_MINOR_MASK) >> REV1_MINOR_SHIFT); 394 } 395 else if (p_Qm->h_Session) 396 { 397 t_QmIpcMsg msg; 398 t_QmIpcReply reply; 399 t_QmIpcRevisionInfo ipcRevInfo; 400 uint32_t replyLength; 401 t_Error errCode = E_OK; 402 403 memset(&msg, 0, sizeof(t_QmIpcMsg)); 404 memset(&reply, 0, sizeof(reply)); 405 msg.msgId = QM_GET_REVISION; 406 replyLength = sizeof(uint32_t) + sizeof(t_QmIpcRevisionInfo); 407 if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, 408 (uint8_t*)&msg, 409 sizeof(msg.msgId), 410 (uint8_t*)&reply, 411 &replyLength, 412 NULL, 413 NULL)) != E_OK) 414 RETURN_ERROR(MAJOR, errCode, NO_MSG); 415 if (replyLength != (sizeof(uint32_t) + sizeof(t_QmIpcRevisionInfo))) 416 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); 417 418 memcpy((uint8_t*)&ipcRevInfo, reply.replyBody, sizeof(t_QmIpcRevisionInfo)); 419 p_QmRevisionInfo->majorRev = ipcRevInfo.majorRev; 420 p_QmRevisionInfo->minorRev = ipcRevInfo.minorRev; 421 422 return (t_Error)(reply.error); 423 } 424 else 425 RETURN_ERROR(WARNING, E_NOT_SUPPORTED, 426 ("In 'guest', either IPC or 'baseAddress' is required!")); 427 428 return E_OK; 429 } 430 431 t_Error QmGetSetPortalParams(t_Handle h_Qm, t_QmInterModulePortalInitParams *p_PortalParams) 432 { 433 t_Qm *p_Qm = (t_Qm *)h_Qm; 434 t_QmRevisionInfo revInfo; 435 uint32_t lioReg,ioReg; 436 437 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 438 SANITY_CHECK_RETURN_ERROR(p_PortalParams, E_NULL_POINTER); 439 440 if (p_Qm->guestId == NCSW_MASTER_ID) 441 { 442 QmGetRevision(p_Qm, &revInfo); 443 444 if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0)) 445 { 446 lioReg = (uint32_t)(p_PortalParams->stashDestQueue << 24) | 447 (p_PortalParams->liodn << 16) | 448 (p_PortalParams->dqrrLiodn); 449 ioReg = (p_PortalParams->fdFqLiodn); 450 } 451 else 452 { 453 lioReg = (uint32_t)(p_PortalParams->liodn << 16) | 454 (p_PortalParams->dqrrLiodn); 455 ioReg = (uint32_t)(p_PortalParams->stashDestQueue << 16) | 456 (p_PortalParams->fdFqLiodn); 457 } 458 459 WRITE_UINT32(p_Qm->p_QmRegs->swpConfRegs[p_PortalParams->portalId].lio_cfg, lioReg); 460 WRITE_UINT32(p_Qm->p_QmRegs->swpConfRegs[p_PortalParams->portalId].io_cfg, ioReg); 461 } 462 else if (p_Qm->h_Session) 463 { 464 t_QmIpcMsg msg; 465 t_QmIpcPortalInitParams portalParams; 466 t_Error errCode; 467 468 memset(&msg, 0, sizeof(t_QmIpcMsg)); 469 portalParams.portalId = p_PortalParams->portalId; 470 portalParams.stashDestQueue = p_PortalParams->stashDestQueue; 471 portalParams.liodn = p_PortalParams->liodn; 472 portalParams.dqrrLiodn = p_PortalParams->dqrrLiodn; 473 portalParams.fdFqLiodn = p_PortalParams->fdFqLiodn; 474 msg.msgId = QM_GET_SET_PORTAL_PARAMS; 475 memcpy(msg.msgBody, &portalParams, sizeof(t_QmIpcPortalInitParams)); 476 XX_LockSpinlock(p_Qm->lock); 477 if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, 478 (uint8_t*)&msg, 479 sizeof(msg.msgId) + sizeof(t_QmIpcPortalInitParams), 480 NULL, 481 NULL, 482 NULL, 483 NULL)) != E_OK) 484 { 485 XX_UnlockSpinlock(p_Qm->lock); 486 RETURN_ERROR(MAJOR, errCode, NO_MSG); 487 } 488 XX_UnlockSpinlock(p_Qm->lock); 489 } 490 else 491 DBG(WARNING, ("Can't set portal parameters (e.g. liodns). " \ 492 "probably QM is running in guest-mode with no IPC!")); 493 494 return E_OK; 495 } 496 497 uint32_t QmFqidGet(t_Qm *p_Qm, uint32_t size, uint32_t alignment, bool force, uint32_t base) 498 { 499 uint64_t ans; 500 uint32_t intFlags; 501 502 intFlags = XX_LockIntrSpinlock(p_Qm->lock); 503 if (force) 504 { 505 ans = MM_GetForce(p_Qm->h_FqidMm, 506 (uint64_t)base, 507 (uint64_t)size, 508 "QM FQID MEM"); 509 if (ans == ILLEGAL_BASE) 510 { 511 ans = MM_GetForce(p_Qm->h_RsrvFqidMm, 512 (uint64_t)base, 513 (uint64_t)size, 514 "QM rsrv FQID MEM"); 515 if (ans == ILLEGAL_BASE) 516 ans = base; 517 else if (p_Qm->h_Session) 518 { 519 t_QmIpcMsg msg; 520 t_QmIpcReply reply; 521 uint32_t replyLength; 522 t_QmIpcFqidParams ipcFqid; 523 t_Error errCode = E_OK; 524 525 memset(&msg, 0, sizeof(t_QmIpcMsg)); 526 memset(&reply, 0, sizeof(t_QmIpcReply)); 527 ipcFqid.fqid = base; 528 ipcFqid.size = size; 529 msg.msgId = QM_FORCE_FQID; 530 memcpy(msg.msgBody, &ipcFqid, sizeof(t_QmIpcFqidParams)); 531 replyLength = sizeof(uint32_t) + sizeof(uint32_t); 532 if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, 533 (uint8_t*)&msg, 534 sizeof(msg.msgId) + sizeof(t_QmIpcFqidParams), 535 (uint8_t*)&reply, 536 &replyLength, 537 NULL, 538 NULL)) != E_OK) 539 REPORT_ERROR(MAJOR, errCode, NO_MSG); 540 if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) 541 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); 542 543 if ((errCode != E_OK) || 544 (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))) 545 ans = ILLEGAL_BASE; 546 else 547 memcpy((uint8_t*)&ans, reply.replyBody, sizeof(uint32_t)); 548 } 549 else 550 { 551 DBG(WARNING, ("No Ipc - can't validate fqid.")); 552 ans = base; 553 } 554 } 555 } 556 else 557 ans = MM_Get(p_Qm->h_FqidMm, 558 size, 559 alignment, 560 "QM FQID MEM"); 561 XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); 562 563 KASSERT(ans < UINT32_MAX, ("Oops, %jx > UINT32_MAX!\n", (uintmax_t)ans)); 564 return (uint32_t)ans; 565 } 566 567 t_Error QmFqidPut(t_Qm *p_Qm, uint32_t base) 568 { 569 uint32_t intFlags; 570 571 intFlags = XX_LockIntrSpinlock(p_Qm->lock); 572 /* Check maybe this fqid was reserved in the past */ 573 if (MM_GetForce(p_Qm->h_RsrvFqidMm, 574 (uint64_t)base, 575 (uint64_t)1, 576 "QM rsrv FQID MEM") == ILLEGAL_BASE) 577 { 578 XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); 579 return E_OK; 580 } 581 else 582 MM_PutForce(p_Qm->h_RsrvFqidMm, 583 (uint64_t)base, 584 (uint64_t)1); 585 if (MM_InRange(p_Qm->h_FqidMm, (uint64_t)base)) 586 { 587 if (MM_Put(p_Qm->h_FqidMm, (uint64_t)base) != 0) 588 { 589 XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); 590 return E_OK; 591 } 592 else 593 { 594 XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); 595 return ERROR_CODE(E_NOT_FOUND); 596 } 597 } 598 else if (p_Qm->h_Session) 599 { 600 t_QmIpcMsg msg; 601 t_QmIpcFqidParams ipcFqid; 602 t_Error errCode = E_OK; 603 604 memset(&msg, 0, sizeof(t_QmIpcMsg)); 605 ipcFqid.fqid = (uint8_t)base; 606 ipcFqid.size = 0; 607 msg.msgId = QM_PUT_FQID; 608 memcpy(msg.msgBody, &ipcFqid, sizeof(t_QmIpcFqidParams)); 609 if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, 610 (uint8_t*)&msg, 611 sizeof(msg.msgId) + sizeof(t_QmIpcFqidParams), 612 NULL, 613 NULL, 614 NULL, 615 NULL)) != E_OK) 616 { 617 XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); 618 RETURN_ERROR(MAJOR, errCode, NO_MSG); 619 } 620 } 621 else 622 DBG(WARNING, ("No Ipc - can't validate fqid.")); 623 XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); 624 625 return E_OK; 626 } 627 628 t_Error QmGetCgId(t_Handle h_Qm, uint8_t *p_CgId) 629 { 630 t_Qm *p_Qm = (t_Qm *)h_Qm; 631 uint16_t i; 632 633 for(i = p_Qm->partCgsBase;i<p_Qm->partCgsBase+p_Qm->partNumOfCgs;i++) 634 if (!p_Qm->cgsUsed[i]) 635 { 636 p_Qm->cgsUsed[i] = (uint8_t)TRUE; 637 *p_CgId = (uint8_t)i; 638 break; 639 } 640 if(i == (p_Qm->partCgsBase+p_Qm->partNumOfCgs)) 641 RETURN_ERROR(MINOR, E_BUSY, ("No available CG")); 642 else 643 return E_OK; 644 } 645 646 t_Error QmFreeCgId(t_Handle h_Qm, uint8_t cgId) 647 { 648 t_Qm *p_Qm = (t_Qm *)h_Qm; 649 650 if (!p_Qm->cgsUsed[cgId]) 651 RETURN_ERROR(MINOR, E_INVALID_STATE, ("CG is not in use")); 652 else 653 p_Qm->cgsUsed[cgId] = (uint8_t)FALSE; 654 655 return E_OK; 656 } 657 658 659 /****************************************/ 660 /* API Init unit functions */ 661 /****************************************/ 662 663 t_Handle QM_Config(t_QmParam *p_QmParam) 664 { 665 t_Qm *p_Qm; 666 uint8_t i; 667 668 SANITY_CHECK_RETURN_VALUE(p_QmParam, E_INVALID_HANDLE, NULL); 669 670 p_Qm = (t_Qm *)XX_Malloc(sizeof(t_Qm)); 671 if (!p_Qm) 672 { 673 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM obj!!!")); 674 return NULL; 675 } 676 memset(p_Qm, 0, sizeof(t_Qm)); 677 p_Qm->p_QmDriverParams = (t_QmDriverParams *)XX_Malloc(sizeof(t_QmDriverParams)); 678 if (!p_Qm->p_QmDriverParams) 679 { 680 XX_Free(p_Qm); 681 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm driver parameters")); 682 return NULL; 683 } 684 memset(p_Qm->p_QmDriverParams, 0, sizeof(t_QmDriverParams)); 685 686 p_Qm->guestId = p_QmParam->guestId; 687 p_Qm->p_QmDriverParams->partFqidBase = p_QmParam->partFqidBase; 688 p_Qm->p_QmDriverParams->partNumOfFqids = p_QmParam->partNumOfFqids; 689 p_Qm->partCgsBase = p_QmParam->partCgsBase; 690 p_Qm->partNumOfCgs = p_QmParam->partNumOfCgs; 691 p_Qm->p_QmRegs = (t_QmRegs *)UINT_TO_PTR(p_QmParam->baseAddress); 692 693 if (p_Qm->guestId == NCSW_MASTER_ID) 694 { 695 p_Qm->exceptions = DEFAULT_exceptions; 696 p_Qm->f_Exception = p_QmParam->f_Exception; 697 p_Qm->h_App = p_QmParam->h_App; 698 p_Qm->errIrq = p_QmParam->errIrq; 699 p_Qm->p_QmDriverParams->liodn = p_QmParam->liodn; 700 p_Qm->p_QmDriverParams->rtFramesDepth = DEFAULT_rtFramesDepth; 701 p_Qm->p_QmDriverParams->fqdMemPartitionId = p_QmParam->fqdMemPartitionId; 702 p_Qm->p_QmDriverParams->pfdrMemPartitionId = p_QmParam->pfdrMemPartitionId; 703 p_Qm->p_QmDriverParams->swPortalsBaseAddress = p_QmParam->swPortalsBaseAddress; 704 p_Qm->p_QmDriverParams->totalNumOfFqids = p_QmParam->totalNumOfFqids; 705 p_Qm->p_QmDriverParams->pfdrThreshold = DEFAULT_pfdrThreshold; 706 p_Qm->p_QmDriverParams->sfdrThreshold = DEFAULT_sfdrThreshold; 707 p_Qm->p_QmDriverParams->pfdrBaseConstant = DEFAULT_pfdrBaseConstant; 708 for(i= 0;i<DPAA_MAX_NUM_OF_DC_PORTALS;i++) 709 p_Qm->p_QmDriverParams->dcPortalsParams[i].sendToSw = 710 (bool)((i < e_DPAA_DCPORTAL2) ? FALSE : TRUE); 711 712 #ifdef QMAN_SFDR_LEAK_ERRATA_QMAN5 713 { 714 #define WORKAROUND_TMP_VAL 0x00000003 715 t_QmRevisionInfo revInfo; 716 QmGetRevision(p_Qm, &revInfo); 717 if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0)) 718 { 719 uint32_t *tmp = (uint32_t *)UINT_TO_PTR(p_QmParam->baseAddress + 0xbf0); 720 uint32_t tmpReg = WORKAROUND_TMP_VAL; 721 WRITE_UINT32(*tmp, tmpReg); 722 while ((tmpReg = GET_UINT32(*tmp)) != WORKAROUND_TMP_VAL) ; 723 } 724 } 725 #endif /* QMAN_SFDR_LEAK_ERRATA_QMAN5 */ 726 } 727 728 /* build the QM partition IPC address */ 729 memset(p_Qm->moduleName, 0, MODULE_NAME_SIZE); 730 if(Sprint (p_Qm->moduleName, "QM_0_%d",p_Qm->guestId) != (p_Qm->guestId<10 ? 6:7)) 731 { 732 XX_Free(p_Qm->p_QmDriverParams); 733 XX_Free(p_Qm); 734 REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); 735 return NULL; 736 } 737 738 return p_Qm; 739 } 740 741 t_Error QM_Init(t_Handle h_Qm) 742 { 743 t_Qm *p_Qm = (t_Qm *)h_Qm; 744 t_QmDriverParams *p_QmDriverParams; 745 t_Error err; 746 747 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 748 SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE); 749 750 CHECK_INIT_PARAMETERS(p_Qm, CheckQmParameters); 751 752 p_QmDriverParams = p_Qm->p_QmDriverParams; 753 754 if (p_QmDriverParams->partNumOfFqids) 755 { 756 if (MM_Init(&p_Qm->h_FqidMm, p_QmDriverParams->partFqidBase, p_QmDriverParams->partNumOfFqids) != E_OK) 757 RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("QM-FQIDS-MEM partition!!!")); 758 if (MM_Init(&p_Qm->h_RsrvFqidMm, p_QmDriverParams->partFqidBase, p_QmDriverParams->partNumOfFqids) != E_OK) 759 RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("QM-Reserve-FQIDS-MEM partition!!!")); 760 } 761 762 if (p_Qm->guestId == NCSW_MASTER_ID) 763 { 764 uint64_t phyAddr; 765 t_QmRevisionInfo revInfo; 766 uint32_t dsSize, exp, i; 767 768 QmGetRevision(p_Qm, &revInfo); 769 DBG(TRACE, ("Qman ver:%02x,%02x", revInfo.majorRev, revInfo.minorRev)); 770 771 phyAddr = XX_VirtToPhys(UINT_TO_PTR(p_QmDriverParams->swPortalsBaseAddress)); 772 WRITE_UINT32(p_Qm->p_QmRegs->qcsp_bare, ((uint32_t)(phyAddr >> 32) & 0x000000ff)); 773 WRITE_UINT32(p_Qm->p_QmRegs->qcsp_bar, (uint32_t)phyAddr); 774 WRITE_UINT32(p_Qm->p_QmRegs->liodnr, (uint16_t)p_QmDriverParams->liodn); 775 776 /* FQD memory */ 777 dsSize = (uint32_t)(p_QmDriverParams->totalNumOfFqids * FQD_ENTRY_SIZE); 778 LOG2(dsSize, exp); 779 if (!POWER_OF_2(dsSize)) (exp++); 780 dsSize = (uint32_t)(1 << exp); 781 if (dsSize < (4*KILOBYTE)) 782 { 783 dsSize = (4*KILOBYTE); 784 LOG2(dsSize, exp); 785 } 786 p_Qm->p_FqdBase = XX_MallocSmart(dsSize, (int)p_QmDriverParams->fqdMemPartitionId, dsSize); 787 if (!p_Qm->p_FqdBase) 788 { 789 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQD obj!!!")); 790 } 791 memset(p_Qm->p_FqdBase, 0, dsSize); 792 mb(); 793 for (i=0; i<dsSize; i+=64) 794 dcbf(PTR_MOVE(p_Qm->p_FqdBase, i)); 795 mb(); 796 797 phyAddr = XX_VirtToPhys(p_Qm->p_FqdBase); 798 WRITE_UINT32(p_Qm->p_QmRegs->fqd_bare, ((uint32_t)(phyAddr >> 32) & 0x000000ff)); 799 WRITE_UINT32(p_Qm->p_QmRegs->fqd_bar, (uint32_t)phyAddr); 800 WRITE_UINT32(p_Qm->p_QmRegs->fqd_ar, AR_ENABLE | (exp - 1)); 801 802 /* PFDR memory */ 803 dsSize = (uint32_t)(p_QmDriverParams->rtFramesDepth * (PFDR_ENTRY_SIZE/3)); 804 LOG2(dsSize, exp); 805 if (!POWER_OF_2(dsSize)) (exp++); 806 dsSize = (uint32_t)(1 << exp); 807 if (dsSize < (4*KILOBYTE)) 808 { 809 dsSize = (4*KILOBYTE); 810 LOG2(dsSize, exp); 811 } 812 813 p_Qm->p_PfdrBase = XX_MallocSmart(dsSize, (int)p_QmDriverParams->pfdrMemPartitionId, dsSize); 814 if (!p_Qm->p_PfdrBase) 815 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("PFDR obj!!!")); 816 817 phyAddr = XX_VirtToPhys(p_Qm->p_PfdrBase); 818 WRITE_UINT32(p_Qm->p_QmRegs->pfdr_bare, ((uint32_t)(phyAddr >> 32) & 0x000000ff)); 819 WRITE_UINT32(p_Qm->p_QmRegs->pfdr_bar, (uint32_t)phyAddr); 820 WRITE_UINT32(p_Qm->p_QmRegs->pfdr_ar, AR_ENABLE | (exp - 1)); 821 822 if (QmInitPfdr(p_Qm, 8, dsSize / 64 - 8) != E_OK) 823 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PFDR init failed!!!")); 824 825 /* thresholds */ 826 WRITE_UINT32(p_Qm->p_QmRegs->pfdr_fp_lwit, (p_Qm->p_QmDriverParams->pfdrThreshold & 0xffffff)); 827 WRITE_UINT32(p_Qm->p_QmRegs->pfdr_cfg, p_Qm->p_QmDriverParams->pfdrBaseConstant); 828 WRITE_UINT32(p_Qm->p_QmRegs->sfdr_cfg, (p_Qm->p_QmDriverParams->sfdrThreshold & 0x3ff)); 829 830 p_Qm->numOfPfdr = GET_UINT32(p_Qm->p_QmRegs->pfdr_fpc); 831 832 /* corenet initiator settings */ 833 WRITE_UINT32(p_Qm->p_QmRegs->ci_sched_cfg, 834 (CI_SCHED_CFG_EN | 835 (DEFAULT_initiatorSrcciv << CI_SCHED_CFG_SRCCIV_SHIFT) | 836 (DEFAULT_initiatorSrqW << CI_SCHED_CFG_SRQ_W_SHIFT) | 837 (DEFAULT_initiatorRwW << CI_SCHED_CFG_RW_W_SHIFT) | 838 (DEFAULT_initiatorBmanW << CI_SCHED_CFG_BMAN_W_SHIFT))); 839 840 /* HID settings */ 841 if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0)) 842 /* offset 0x0bf0 */ 843 WRITE_UINT32(p_Qm->p_QmRegs->res23[144], 0x3); 844 else 845 WRITE_UINT32(p_Qm->p_QmRegs->res23[144], 0x0); 846 847 for(i=0;i<DPAA_MAX_NUM_OF_DC_PORTALS;i++) 848 { 849 if(p_Qm->p_QmDriverParams->dcPortalsParams[i].sendToSw) 850 WRITE_UINT32(p_Qm->p_QmRegs->dcpConfRegs[i].cfg, 851 p_Qm->p_QmDriverParams->dcPortalsParams[i].swPortalId); 852 else 853 WRITE_UINT32(p_Qm->p_QmRegs->dcpConfRegs[i].cfg, QM_DCP_CFG_ED); 854 } 855 856 #ifdef QMAN_WQ_CS_CFG_ERRATA_QMAN4 857 { 858 t_QmRevisionInfo revInfo; 859 QmGetRevision(p_Qm, &revInfo); 860 if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0)) 861 { 862 QmSetWqScheduling(p_Qm, e_QM_WQ_SW_PORTALS,0,1,1,1,1,1,1); 863 QmSetWqScheduling(p_Qm, e_QM_WQ_POOLS,0,1,1,1,1,1,1); 864 QmSetWqScheduling(p_Qm, e_QM_WQ_DCP0,0,1,1,1,1,1,1); 865 QmSetWqScheduling(p_Qm, e_QM_WQ_DCP1,0,1,1,1,1,1,1); 866 QmSetWqScheduling(p_Qm, e_QM_WQ_DCP2,0,1,1,1,1,1,1); 867 QmSetWqScheduling(p_Qm, e_QM_WQ_DCP3,0,1,1,1,1,1,1); 868 } 869 } 870 #endif /* QMAN_WQ_CS_CFG_ERRATA_QMAN4 */ 871 872 WRITE_UINT32(p_Qm->p_QmRegs->err_isr, p_Qm->exceptions); 873 WRITE_UINT32(p_Qm->p_QmRegs->err_ier, p_Qm->exceptions); 874 WRITE_UINT32(p_Qm->p_QmRegs->err_isdr, 0x0); 875 if (p_Qm->errIrq != NO_IRQ) 876 { 877 XX_SetIntr(p_Qm->errIrq, QM_ErrorIsr, p_Qm); 878 XX_EnableIntr(p_Qm->errIrq); 879 } 880 if ((err = XX_IpcRegisterMsgHandler(p_Qm->moduleName, QmHandleIpcMsgCB, p_Qm, QM_IPC_MAX_REPLY_SIZE)) != E_OK) 881 RETURN_ERROR(MAJOR, err, NO_MSG); 882 } 883 else /* guest mode */ 884 { 885 char masterModuleName[MODULE_NAME_SIZE]; 886 887 memset(masterModuleName, 0, MODULE_NAME_SIZE); 888 if(Sprint (masterModuleName, "QM_0_%d", NCSW_MASTER_ID) != (NCSW_MASTER_ID<10 ? 6:7)) 889 { 890 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); 891 } 892 893 p_Qm->h_Session = XX_IpcInitSession(masterModuleName, p_Qm->moduleName); 894 if (p_Qm->h_Session) 895 { 896 t_QmIpcMsg msg; 897 uint8_t isMasterAlive = 0; 898 t_QmIpcReply reply; 899 uint32_t replyLength; 900 901 memset(&msg, 0, sizeof(t_QmIpcMsg)); 902 memset(&reply, 0, sizeof(t_QmIpcReply)); 903 msg.msgId = QM_MASTER_IS_ALIVE; 904 do 905 { 906 blockingFlag = TRUE; 907 replyLength = sizeof(uint32_t) + sizeof(uint8_t); 908 if ((err = XX_IpcSendMessage(p_Qm->h_Session, 909 (uint8_t*)&msg, 910 sizeof(msg.msgId), 911 (uint8_t*)&reply, 912 &replyLength, 913 QmIpcMsgCompletionCB, 914 p_Qm)) != E_OK) 915 REPORT_ERROR(MAJOR, err, NO_MSG); 916 while(blockingFlag) ; 917 if(replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) 918 REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); 919 isMasterAlive = *(uint8_t*)(reply.replyBody); 920 } while (!isMasterAlive); 921 } 922 } 923 924 p_Qm->lock = XX_InitSpinlock(); 925 XX_Free(p_Qm->p_QmDriverParams); 926 p_Qm->p_QmDriverParams = NULL; 927 928 return E_OK; 929 } 930 931 t_Error QM_Free(t_Handle h_Qm) 932 { 933 t_Qm *p_Qm = (t_Qm *)h_Qm; 934 935 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 936 937 if (p_Qm->lock) 938 XX_FreeSpinlock(p_Qm->lock); 939 940 if (p_Qm->guestId == NCSW_MASTER_ID) 941 { 942 XX_IpcUnregisterMsgHandler(p_Qm->moduleName); 943 if (p_Qm->errIrq != NO_IRQ) 944 { 945 XX_DisableIntr(p_Qm->errIrq); 946 XX_FreeIntr(p_Qm->errIrq); 947 } 948 } 949 FreeInitResources(p_Qm); 950 951 if (p_Qm->p_QmDriverParams) 952 XX_Free(p_Qm->p_QmDriverParams); 953 954 XX_Free(p_Qm); 955 956 return E_OK; 957 } 958 959 t_Error QM_ConfigRTFramesDepth(t_Handle h_Qm, uint32_t rtFramesDepth) 960 { 961 t_Qm *p_Qm = (t_Qm *)h_Qm; 962 963 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 964 SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE); 965 966 p_Qm->p_QmDriverParams->rtFramesDepth = rtFramesDepth; 967 968 return E_OK; 969 } 970 971 t_Error QM_ConfigPfdrThreshold(t_Handle h_Qm, uint32_t threshold) 972 { 973 t_Qm *p_Qm = (t_Qm *)h_Qm; 974 975 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 976 SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE); 977 978 p_Qm->p_QmDriverParams->pfdrThreshold = threshold; 979 980 return E_OK; 981 } 982 983 t_Error QM_ConfigSfdrReservationThreshold(t_Handle h_Qm, uint32_t threshold) 984 { 985 t_Qm *p_Qm = (t_Qm *)h_Qm; 986 987 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 988 SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE); 989 990 p_Qm->p_QmDriverParams->sfdrThreshold = threshold; 991 992 return E_OK; 993 } 994 995 996 t_Error QM_ConfigErrorRejectionNotificationDest(t_Handle h_Qm, e_DpaaDcPortal id, t_QmDcPortalParams *p_Params) 997 { 998 UNUSED(h_Qm); UNUSED(id); UNUSED(p_Params); 999 1000 RETURN_ERROR(INFO, E_NOT_SUPPORTED, ("Only default ERN destination available.")); 1001 } 1002 1003 1004 t_Error QM_Poll(t_Handle h_Qm, e_QmPortalPollSource source) 1005 { 1006 t_Qm *p_Qm = (t_Qm *)h_Qm; 1007 t_QmPortal *p_QmPortal; 1008 1009 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 1010 p_QmPortal = QmGetPortalHandle(p_Qm); 1011 SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE); 1012 1013 return QM_PORTAL_Poll(p_QmPortal, source); 1014 } 1015 1016 uint32_t QM_GetCounter(t_Handle h_Qm, e_QmCounters counter) 1017 { 1018 t_Qm *p_Qm = (t_Qm *)h_Qm; 1019 1020 SANITY_CHECK_RETURN_VALUE(p_Qm, E_INVALID_HANDLE, 0); 1021 SANITY_CHECK_RETURN_VALUE(!p_Qm->p_QmDriverParams, E_INVALID_STATE, 0); 1022 1023 switch(counter) 1024 { 1025 case(e_QM_COUNTERS_SFDR_IN_USE): 1026 return QmGetCounter(p_Qm, e_QM_IM_COUNTERS_SFDR_IN_USE); 1027 case(e_QM_COUNTERS_PFDR_IN_USE): 1028 return QmGetCounter(p_Qm, e_QM_IM_COUNTERS_PFDR_IN_USE); 1029 case(e_QM_COUNTERS_PFDR_FREE_POOL): 1030 return QmGetCounter(p_Qm, e_QM_IM_COUNTERS_PFDR_FREE_POOL); 1031 default: 1032 break; 1033 } 1034 /* should never get here */ 1035 ASSERT_COND(FALSE); 1036 1037 return 0; 1038 } 1039 1040 void QM_ErrorIsr(t_Handle h_Qm) 1041 { 1042 t_Qm *p_Qm = (t_Qm *)h_Qm; 1043 uint32_t tmpReg; 1044 1045 SANITY_CHECK_RETURN(p_Qm, E_INVALID_HANDLE); 1046 1047 if (p_Qm->guestId != NCSW_MASTER_ID) 1048 { 1049 REPORT_ERROR(WARNING, E_INVALID_OPERATION, ("Master Only")); 1050 return; 1051 } 1052 1053 tmpReg = GET_UINT32(p_Qm->p_QmRegs->err_isr); 1054 tmpReg &= GET_UINT32(p_Qm->p_QmRegs->err_ier); 1055 WRITE_UINT32(p_Qm->p_QmRegs->err_isr, tmpReg); 1056 1057 if (tmpReg & QM_EX_CORENET_INITIATOR_DATA) 1058 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_CORENET_INITIATOR_DATA); 1059 if (tmpReg & QM_EX_CORENET_TARGET_DATA) 1060 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_CORENET_TARGET_DATA); 1061 if (tmpReg & QM_EX_CORENET_INVALID_TARGET_TRANSACTION) 1062 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_CORENET_INVALID_TARGET_TRANSACTION); 1063 if (tmpReg & QM_EX_PFDR_THRESHOLD) 1064 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_PFDR_THRESHOLD); 1065 if (tmpReg & QM_EX_MULTI_ECC) 1066 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_MULTI_ECC); 1067 if (tmpReg & QM_EX_SINGLE_ECC) 1068 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_SINGLE_ECC); 1069 if (tmpReg & QM_EX_PFDR_ENQUEUE_BLOCKED) 1070 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_PFDR_ENQUEUE_BLOCKED); 1071 if (tmpReg & QM_EX_INVALID_COMMAND) 1072 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_INVALID_COMMAND); 1073 if (tmpReg & QM_EX_DEQUEUE_DCP) 1074 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_DCP); 1075 if (tmpReg & QM_EX_DEQUEUE_FQ) 1076 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_FQ); 1077 if (tmpReg & QM_EX_DEQUEUE_SOURCE) 1078 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_SOURCE); 1079 if (tmpReg & QM_EX_DEQUEUE_QUEUE) 1080 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_QUEUE); 1081 if (tmpReg & QM_EX_ENQUEUE_OVERFLOW) 1082 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_OVERFLOW); 1083 if (tmpReg & QM_EX_ENQUEUE_STATE) 1084 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_STATE); 1085 if (tmpReg & QM_EX_ENQUEUE_CHANNEL) 1086 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_CHANNEL); 1087 if (tmpReg & QM_EX_ENQUEUE_QUEUE) 1088 p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_QUEUE); 1089 } 1090 1091 t_Error QM_SetException(t_Handle h_Qm, e_QmExceptions exception, bool enable) 1092 { 1093 t_Qm *p_Qm = (t_Qm*)h_Qm; 1094 t_Error err = E_OK; 1095 1096 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 1097 SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_HANDLE); 1098 1099 if ((err = SetException(p_Qm, exception, enable)) != E_OK) 1100 RETURN_ERROR(MINOR, err, NO_MSG); 1101 1102 WRITE_UINT32(p_Qm->p_QmRegs->err_ier, p_Qm->exceptions); 1103 1104 return E_OK; 1105 } 1106 1107 t_Error QM_GetRevision(t_Handle h_Qm, t_QmRevisionInfo *p_QmRevisionInfo) 1108 { 1109 t_Qm *p_Qm = (t_Qm*)h_Qm; 1110 1111 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 1112 SANITY_CHECK_RETURN_ERROR(p_QmRevisionInfo, E_NULL_POINTER); 1113 1114 return QmGetRevision(p_Qm, p_QmRevisionInfo); 1115 } 1116 1117 t_Error QM_ReserveQueues(t_Handle h_Qm, t_QmRsrvFqrParams *p_QmFqrParams, uint32_t *p_BaseFqid) 1118 { 1119 t_Qm *p_Qm = (t_Qm*)h_Qm; 1120 1121 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 1122 SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_HANDLE); 1123 1124 *p_BaseFqid = ReserveFqids(p_Qm, 1125 (uint32_t)((p_QmFqrParams->useForce && !p_QmFqrParams->numOfFqids) ? 1126 1 : p_QmFqrParams->numOfFqids), 1127 p_QmFqrParams->qs.nonFrcQs.align, 1128 p_QmFqrParams->useForce, 1129 p_QmFqrParams->qs.frcQ.fqid); 1130 if (*p_BaseFqid == ILLEGAL_BASE) 1131 RETURN_ERROR(CRITICAL,E_INVALID_STATE,("can't allocate a fqid")); 1132 1133 return E_OK; 1134 } 1135 1136 t_Error QM_GetErrorInformation(t_Handle h_Qm, t_QmErrorInfo *p_errInfo) 1137 { 1138 uint32_t ecsr, ecir; 1139 t_Qm *p_Qm = (t_Qm*)h_Qm; 1140 t_Error err = E_OK; 1141 1142 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 1143 SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_HANDLE); 1144 SANITY_CHECK_RETURN_ERROR(p_errInfo, E_NULL_POINTER); 1145 1146 ecsr = GET_UINT32(p_Qm->p_QmRegs->ecsr); 1147 ecir = GET_UINT32(p_Qm->p_QmRegs->ecir); 1148 if ((ecsr & QM_EX_MULTI_ECC) || 1149 (ecsr & QM_EX_SINGLE_ECC)) 1150 { 1151 err = E_NOT_SUPPORTED; 1152 REPORT_ERROR(INFO, E_NOT_SUPPORTED, ("single and multi ecc, use QM_DumpRegs")); 1153 } 1154 if ((ecsr & QM_EX_ENQUEUE_QUEUE) || 1155 (ecsr & QM_EX_ENQUEUE_STATE) || 1156 (ecsr & QM_EX_ENQUEUE_OVERFLOW) || 1157 (ecsr & QM_EX_DEQUEUE_DCP) || 1158 (ecsr & QM_EX_DEQUEUE_FQ) || 1159 (ecsr & QM_EX_DEQUEUE_QUEUE) || 1160 (ecsr & QM_EX_DEQUEUE_SOURCE) || 1161 (ecsr & QM_EX_INVALID_COMMAND)) 1162 { 1163 p_errInfo->portalValid = TRUE; 1164 p_errInfo->hwPortal = (bool)(ecir & ECIR_PORTAL_TYPE); 1165 if (p_errInfo->hwPortal) 1166 p_errInfo->dcpId = (e_DpaaDcPortal)((ecir & ECIR_PORTAL_MASK) >> ECIR_PORTAL_SHIFT); 1167 else 1168 p_errInfo->swPortalId = (e_DpaaSwPortal)((ecir & ECIR_PORTAL_MASK) >> ECIR_PORTAL_SHIFT); 1169 } 1170 1171 if ((ecsr & QM_EX_ENQUEUE_QUEUE) || 1172 (ecsr & QM_EX_ENQUEUE_STATE) || 1173 (ecsr & QM_EX_ENQUEUE_OVERFLOW) || 1174 (ecsr & QM_EX_ENQUEUE_CHANNEL) || 1175 (ecsr & QM_EX_DEQUEUE_QUEUE) || 1176 (ecsr & QM_EX_DEQUEUE_FQ)) 1177 { 1178 p_errInfo->fqidValid = TRUE; 1179 p_errInfo->fqid = ((ecir & ECIR_FQID_MASK) >> ECIR_FQID_SHIFT); 1180 } 1181 1182 WRITE_UINT32(p_Qm->p_QmRegs->ecsr, ecsr); 1183 1184 return ERROR_CODE(err); 1185 } 1186 1187 #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) 1188 t_Error QM_DumpRegs(t_Handle h_Qm) 1189 { 1190 t_Qm *p_Qm = (t_Qm *)h_Qm; 1191 uint8_t i = 0; 1192 1193 DECLARE_DUMP; 1194 1195 SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); 1196 SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_STATE); 1197 1198 DUMP_SUBTITLE(("\n")); 1199 DUMP_TITLE(p_Qm->p_QmRegs, ("QmRegs Regs")); 1200 1201 DUMP_SUBSTRUCT_ARRAY(i, QM_NUM_OF_SWP) 1202 { 1203 DUMP_VAR(&p_Qm->p_QmRegs->swpConfRegs[i], lio_cfg); 1204 DUMP_VAR(&p_Qm->p_QmRegs->swpConfRegs[i], io_cfg); 1205 DUMP_VAR(&p_Qm->p_QmRegs->swpConfRegs[i], dd_cfg); 1206 } 1207 DUMP_VAR(p_Qm->p_QmRegs, qman_dd_cfg); 1208 DUMP_VAR(p_Qm->p_QmRegs, qcsp_dd_ihrsr); 1209 DUMP_VAR(p_Qm->p_QmRegs, qcsp_dd_ihrfr); 1210 DUMP_VAR(p_Qm->p_QmRegs, qcsp_dd_hasr); 1211 DUMP_VAR(p_Qm->p_QmRegs, dcp_dd_ihrsr); 1212 DUMP_VAR(p_Qm->p_QmRegs, dcp_dd_ihrfr); 1213 DUMP_VAR(p_Qm->p_QmRegs, dcp_dd_hasr); 1214 DUMP_SUBSTRUCT_ARRAY(i, QM_NUM_OF_DCP) 1215 { 1216 DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], cfg); 1217 DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], dd_cfg); 1218 DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], dlm_cfg); 1219 DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], dlm_avg); 1220 } 1221 DUMP_VAR(p_Qm->p_QmRegs, pfdr_fpc); 1222 DUMP_VAR(p_Qm->p_QmRegs, pfdr_fp_head); 1223 DUMP_VAR(p_Qm->p_QmRegs, pfdr_fp_tail); 1224 DUMP_VAR(p_Qm->p_QmRegs, pfdr_fp_lwit); 1225 DUMP_VAR(p_Qm->p_QmRegs, pfdr_cfg); 1226 DUMP_VAR(p_Qm->p_QmRegs, sfdr_cfg); 1227 DUMP_VAR(p_Qm->p_QmRegs, sfdr_in_use); 1228 DUMP_ARR(p_Qm->p_QmRegs, wq_cs_cfg); 1229 DUMP_VAR(p_Qm->p_QmRegs, wq_def_enq_wqid); 1230 DUMP_ARR(p_Qm->p_QmRegs, wq_sc_dd_cfg); 1231 DUMP_ARR(p_Qm->p_QmRegs, wq_pc_dd_cs_cfg); 1232 DUMP_ARR(p_Qm->p_QmRegs, wq_dc0_dd_cs_cfg); 1233 DUMP_ARR(p_Qm->p_QmRegs, wq_dc1_dd_cs_cfg); 1234 DUMP_VAR(p_Qm->p_QmRegs, wq_dc2_dd_cs_cfg); 1235 DUMP_VAR(p_Qm->p_QmRegs, wq_dc3_dd_cs_cfg); 1236 DUMP_VAR(p_Qm->p_QmRegs, cm_cfg); 1237 DUMP_VAR(p_Qm->p_QmRegs, ecsr); 1238 DUMP_VAR(p_Qm->p_QmRegs, ecir); 1239 DUMP_VAR(p_Qm->p_QmRegs, eadr); 1240 DUMP_ARR(p_Qm->p_QmRegs, edata); 1241 DUMP_VAR(p_Qm->p_QmRegs, sbet); 1242 DUMP_ARR(p_Qm->p_QmRegs, sbec); 1243 DUMP_VAR(p_Qm->p_QmRegs, mcr); 1244 DUMP_VAR(p_Qm->p_QmRegs, mcp0); 1245 DUMP_VAR(p_Qm->p_QmRegs, mcp1); 1246 DUMP_ARR(p_Qm->p_QmRegs, mr); 1247 DUMP_VAR(p_Qm->p_QmRegs, idle_stat); 1248 DUMP_VAR(p_Qm->p_QmRegs, ip_rev_1); 1249 DUMP_VAR(p_Qm->p_QmRegs, ip_rev_2); 1250 DUMP_VAR(p_Qm->p_QmRegs, fqd_bare); 1251 DUMP_VAR(p_Qm->p_QmRegs, fqd_bar); 1252 DUMP_VAR(p_Qm->p_QmRegs, fqd_ar); 1253 DUMP_VAR(p_Qm->p_QmRegs, pfdr_bare); 1254 DUMP_VAR(p_Qm->p_QmRegs, pfdr_bar); 1255 DUMP_VAR(p_Qm->p_QmRegs, pfdr_ar); 1256 DUMP_VAR(p_Qm->p_QmRegs, qcsp_bare); 1257 DUMP_VAR(p_Qm->p_QmRegs, qcsp_bar); 1258 DUMP_VAR(p_Qm->p_QmRegs, ci_sched_cfg); 1259 DUMP_VAR(p_Qm->p_QmRegs, srcidr); 1260 DUMP_VAR(p_Qm->p_QmRegs, liodnr); 1261 DUMP_VAR(p_Qm->p_QmRegs, ci_rlm_cfg); 1262 DUMP_VAR(p_Qm->p_QmRegs, ci_rlm_avg); 1263 DUMP_VAR(p_Qm->p_QmRegs, err_isr); 1264 DUMP_VAR(p_Qm->p_QmRegs, err_ier); 1265 DUMP_VAR(p_Qm->p_QmRegs, err_isdr); 1266 DUMP_VAR(p_Qm->p_QmRegs, err_iir); 1267 DUMP_VAR(p_Qm->p_QmRegs, err_her); 1268 1269 return E_OK; 1270 } 1271 #endif /* (defined(DEBUG_ERRORS) && ... */ 1272