1 /******************************************************************************* 2 *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved. 3 * 4 *Redistribution and use in source and binary forms, with or without modification, are permitted provided 5 *that the following conditions are met: 6 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the 7 *following disclaimer. 8 *2. Redistributions in binary form must reproduce the above copyright notice, 9 *this list of conditions and the following disclaimer in the documentation and/or other materials provided 10 *with the distribution. 11 * 12 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED 13 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 14 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 15 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 16 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 17 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 18 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE 20 21 ********************************************************************************/ 22 /*******************************************************************************/ 23 /*! \file sasmp.c 24 * \brief The file implements the functions for SMP request/response 25 * 26 */ 27 /*******************************************************************************/ 28 #include <sys/cdefs.h> 29 #include <dev/pms/config.h> 30 31 #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h> 32 #ifdef SA_ENABLE_TRACE_FUNCTIONS 33 #ifdef siTraceFileID 34 #undef siTraceFileID 35 #endif 36 #define siTraceFileID 'N' 37 #endif 38 39 /******************************************************************************/ 40 /*! \brief Start SMP request 41 * 42 * Start SMP request 43 * 44 * \param agRoot handles for this instance of SAS/SATA hardware 45 * \param queueNum 46 * \param agIORequest 47 * \param agDevHandle 48 * \param agRequestType 49 * \param agRequestBody 50 * \param agCB 51 * Spc - support direct mode direct response 52 * SpcV - support direct mode direct response 53 * SpcV - support indirect mode direct response 54 * SpcV - support indirect mode indirect response 55 * 56 * \return If request is started successfully 57 * - \e AGSA_RC_SUCCESS request is started successfully 58 * - \e AGSA_RC_BUSY No resource available, try again later 59 */ 60 /*******************************************************************************/ 61 GLOBAL bit32 saSMPStart( 62 agsaRoot_t *agRoot, 63 agsaIORequest_t *agIORequest, 64 bit32 queueNum, 65 agsaDevHandle_t *agDevHandle, 66 bit32 agRequestType, 67 agsaSASRequestBody_t *agRequestBody, 68 ossaSMPCompletedCB_t agCB 69 ) 70 { 71 bit32 ret = AGSA_RC_SUCCESS, retVal; 72 agsaLLRoot_t *saRoot = agNULL; 73 mpiICQueue_t *circularQ; 74 agsaDeviceDesc_t *pDevice; 75 agsaPort_t *pPort; 76 agsaIORequestDesc_t *pRequest; 77 void *pMessage; 78 bit8 i, inq, outq; 79 bit8 using_reserved = agFALSE; 80 bit8 *payload_ptr; 81 agsaSMPFrame_t *pSMPFrame; 82 83 SA_DBG4(("saSMPStart: start\n")); 84 85 smTraceFuncEnter(hpDBG_VERY_LOUD, "9a"); 86 87 /* sanity check */ 88 SA_ASSERT((agNULL != agRoot), ""); 89 SA_ASSERT((agNULL != agIORequest), ""); 90 SA_ASSERT((agNULL != agDevHandle), ""); 91 SA_ASSERT((agNULL != agRequestBody), ""); 92 93 /* sanity check */ 94 saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 95 SA_ASSERT((agNULL != saRoot), ""); 96 97 if(saRoot == agNULL) 98 { 99 SA_DBG1(("saSMPStart : saRoot is NULL!!\n")); 100 return AGSA_RC_FAILURE; 101 } 102 103 /* Assign inbound and outbound queue number */ 104 inq = (bit8)(queueNum & MPI_IB_NUM_MASK); 105 outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT); 106 SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range."); 107 108 /* Find the outgoing port for the device */ 109 if (agNULL == agDevHandle->sdkData) 110 { 111 /* Device has been removed */ 112 SA_DBG1(("saSMPStart, Device has been removed. agDevHandle=%p\n", agDevHandle)); 113 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "9a"); 114 return AGSA_RC_FAILURE; 115 } 116 117 pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData); 118 119 pPort = pDevice->pPort; 120 121 /* Get request from free IO Requests */ 122 ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); 123 pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/ 124 125 /* If no LL IO request entry available */ 126 if ( agNULL == pRequest ) 127 { 128 129 pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); 130 131 if(agNULL != pRequest) 132 { 133 using_reserved = agTRUE; 134 SA_DBG1(("saSMPStart, using saRoot->freeReservedRequests\n")); 135 } 136 else 137 { 138 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); 139 SA_DBG1(("saSMPStart, No request from free list Not using saRoot->freeReservedRequests\n")); 140 smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "9a"); 141 return AGSA_RC_BUSY; 142 } 143 } 144 145 /* If free IOMB avaliable */ 146 /* Remove the request from free list */ 147 if( using_reserved ) 148 { 149 saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode)); 150 } 151 else 152 { 153 saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode)); 154 } 155 156 /* Add the request to the pendingSMPRequests list of the device */ 157 saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode)); 158 SA_ASSERT((!pRequest->valid), "The pRequest is in use"); 159 pRequest->valid = agTRUE; 160 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); 161 162 /* set up pRequest */ 163 pRequest->pIORequestContext = agIORequest; 164 pRequest->pDevice = pDevice; 165 pRequest->pPort = pPort; 166 pRequest->requestType = agRequestType; 167 pRequest->startTick = saRoot->timeTick; 168 pRequest->completionCB = (ossaSSPCompletedCB_t)agCB; 169 170 /* Set request to the sdkData of agIORequest */ 171 agIORequest->sdkData = pRequest; 172 173 /* save tag to IOMap */ 174 saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag; 175 saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest; 176 177 #ifdef SA_LL_IBQ_PROTECT 178 ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq); 179 #endif /* SA_LL_IBQ_PROTECT */ 180 181 /* If LL IO request entry avaliable */ 182 /* Get a free inbound queue entry */ 183 circularQ = &saRoot->inboundQueue[inq]; 184 retVal = mpiMsgFreeGet(circularQ, IOMB_SIZE64, &pMessage); 185 186 if (AGSA_RC_FAILURE == retVal) 187 { 188 #ifdef SA_LL_IBQ_PROTECT 189 ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); 190 #endif /* SA_LL_IBQ_PROTECT */ 191 /* if not sending return to free list rare */ 192 ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); 193 saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); 194 pRequest->valid = agFALSE; 195 saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); 196 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); 197 198 SA_DBG1(("saSMPStart, error when get free IOMB\n")); 199 smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "9a"); 200 return AGSA_RC_FAILURE; 201 } 202 203 /* return busy if inbound queue is full */ 204 if (AGSA_RC_BUSY == retVal) 205 { 206 #ifdef SA_LL_IBQ_PROTECT 207 ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); 208 #endif /* SA_LL_IBQ_PROTECT */ 209 /* if not sending return to free list rare */ 210 ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); 211 saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); 212 pRequest->valid = agFALSE; 213 saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); 214 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); 215 216 SA_DBG1(("saSMPStart, no more IOMB\n")); 217 smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "9a"); 218 return AGSA_RC_BUSY; 219 } 220 221 /* Setup SMP Frame */ 222 pSMPFrame = (agsaSMPFrame_t *) &(agRequestBody->smpFrame); 223 224 SA_DBG2(("saSMPStart:DeviceMapIndex 0x%x portId 0x%x portId 0x%x\n",pDevice->DeviceMapIndex,pPort->portId,pPort->portId)); 225 226 #if defined(SALLSDK_DEBUG) 227 228 SA_DBG2(("saSMPStart: outFrameBuf %p\n",pSMPFrame->outFrameBuf)); 229 230 if(pSMPFrame->outFrameBuf ) 231 { 232 SA_DBG2(("saSMPStart: outFrameBuf 0 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+0) )); 233 SA_DBG2(("saSMPStart: outFrameBuf 1 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+1) )); 234 SA_DBG2(("saSMPStart: outFrameBuf 2 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+2) )); 235 SA_DBG2(("saSMPStart: outFrameBuf 3 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+3) )); 236 SA_DBG2(("saSMPStart: outFrameBuf 4 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+4) )); 237 SA_DBG2(("saSMPStart: outFrameBuf 5 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+5) )); 238 SA_DBG2(("saSMPStart: outFrameBuf 6 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+6) )); 239 SA_DBG2(("saSMPStart: outFrameBuf 7 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+7) )); 240 SA_DBG2(("saSMPStart: outFrameBuf 8 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+8) )); 241 SA_DBG2(("saSMPStart: outFrameBuf 9 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+9) )); 242 SA_DBG2(("saSMPStart: outFrameBuf 11 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+10) )); 243 SA_DBG2(("saSMPStart: outFrameBuf 11 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+11) )); 244 } 245 SA_DBG2(("saSMPStart: outFrameAddrUpper32 0x%08X\n",pSMPFrame->outFrameAddrUpper32)); 246 SA_DBG2(("saSMPStart: outFrameAddrLower32 0x%08X\n",pSMPFrame->outFrameAddrLower32)); 247 SA_DBG2(("saSMPStart: outFrameLen 0x%08X\n",pSMPFrame->outFrameLen)); 248 SA_DBG2(("saSMPStart: inFrameAddrUpper32 0x%08X\n",pSMPFrame->inFrameAddrUpper32)); 249 SA_DBG2(("saSMPStart: inFrameAddrLower32 0x%08X\n",pSMPFrame->inFrameAddrLower32)); 250 SA_DBG2(("saSMPStart: inFrameLen 0x%08X\n",pSMPFrame->inFrameLen)); 251 SA_DBG2(("saSMPStart: expectedRespLen 0x%08X\n",pSMPFrame->expectedRespLen)); 252 SA_DBG2(("saSMPStart: flag 0x%08X\n",pSMPFrame->flag)); 253 #endif /* SALLSDK_DEBUG */ 254 255 if(smIS_SPC(agRoot)) 256 // if(1) 257 { 258 agsaSMPCmd_t payload; 259 switch ( agRequestType ) 260 { 261 case AGSA_SMP_INIT_REQ: 262 { 263 bit32 IR_IP_OV_res_phyId_DPdLen_res = 0; 264 /* Prepare the payload of IOMB */ 265 si_memset(&payload, 0, sizeof(agsaSMPCmd_t)); 266 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, tag), pRequest->HTag); 267 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, deviceId), pDevice->DeviceMapIndex); 268 269 /* check SMP Response Frame with IR mode */ 270 /* check if the SMP Response is indirect mode */ 271 if (0 == pSMPFrame->inFrameLen) 272 { 273 /* PHY override not support */ 274 /* Direct Response mode */ 275 pRequest->IRmode = DIRECT_MODE; 276 } 277 else 278 { 279 /* Indirect Response mode */ 280 pRequest->IRmode = INDIRECT_MODE; 281 IR_IP_OV_res_phyId_DPdLen_res = 1; 282 /* check SMP direct payload mode len */ 283 if (pSMPFrame->outFrameLen > 32) 284 { 285 #ifdef SA_LL_IBQ_PROTECT 286 ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); 287 #endif /* SA_LL_IBQ_PROTECT */ 288 /* if not sending return to free list rare */ 289 ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); 290 saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); 291 pRequest->valid = agFALSE; 292 saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); 293 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); 294 /* can not handle SMP frame length > 32 bytes it if IP=0 and IR=1 */ 295 SA_DBG1(("saSMPStart, outFrameLen > 32 bytes error.\n")); 296 smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "9a"); 297 return AGSA_RC_FAILURE; 298 } 299 } 300 301 /* check Direct mode or Indirect mode for IP mode */ 302 if ( (pSMPFrame->outFrameBuf && 303 (pSMPFrame->outFrameLen <= AGSA_MAX_SMPPAYLOAD_VIA_SFO)) || 304 ((pSMPFrame->outFrameBuf == agNULL) && 305 (pSMPFrame->outFrameLen == 0) ) 306 ) 307 { 308 SA_DBG4(("saSMPStart: DIRECT Request SMP\n")); 309 310 IR_IP_OV_res_phyId_DPdLen_res = (DIRECT_MODE << 1) | IR_IP_OV_res_phyId_DPdLen_res; 311 312 /* Direct payload length */ 313 IR_IP_OV_res_phyId_DPdLen_res |= (((pSMPFrame->outFrameLen) & 0xff) << SHIFT16); 314 315 /* copy payload - upto 48 bytes */ 316 si_memcpy(&(payload.SMPCmd[0]),pSMPFrame->outFrameBuf,pSMPFrame->outFrameLen); 317 for ( i = 0; i < pSMPFrame->outFrameLen / sizeof(bit32)+1; i ++ ) 318 { 319 SA_DBG4(("saSMPStart: payload.SMPCmd[%d] %x\n", i, payload.SMPCmd[i])); 320 } 321 } 322 else 323 { 324 SA_DBG4(("saSMPStart: INDIRECT Request SMP\n")); 325 /* use physical address */ 326 IR_IP_OV_res_phyId_DPdLen_res = (INDIRECT_MODE << 1) | IR_IP_OV_res_phyId_DPdLen_res; 327 328 /* Direct payload length = 0 */ 329 IR_IP_OV_res_phyId_DPdLen_res = IR_IP_OV_res_phyId_DPdLen_res & 0xff00ffff; 330 331 /* payload */ 332 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[4]), (pSMPFrame->outFrameAddrLower32)); 333 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[5]), (pSMPFrame->outFrameAddrUpper32)); 334 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[6]), (pSMPFrame->outFrameLen)); 335 } 336 /* Write IR_IP_OV_res_phyId_DPdLen_res field in the payload*/ 337 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, IR_IP_OV_res_phyId_DPdLen_res), IR_IP_OV_res_phyId_DPdLen_res); 338 339 /* check IR bit */ 340 if (IR_IP_OV_res_phyId_DPdLen_res & INDIRECT_MODE) 341 { 342 /* setup indirect response frame address */ 343 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[8]), (pSMPFrame->inFrameAddrLower32)); 344 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[9]), (pSMPFrame->inFrameAddrUpper32)); 345 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[10]), (pSMPFrame->inFrameLen)); 346 } 347 348 /* Build IOMB command and send it to SPC */ 349 payload_ptr = (bit8 *)&payload; 350 ret = mpiSMPCmd(agRoot, pMessage, OPC_INB_SMP_REQUEST, (agsaSMPCmd_t *)payload_ptr, inq, outq); 351 352 #ifdef SA_LL_IBQ_PROTECT 353 ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); 354 #endif /* SA_LL_IBQ_PROTECT */ 355 356 break; 357 } 358 default: 359 { 360 SA_DBG1(("saSMPStart: SPC unknown agRequestType %x\n",agRequestType)); 361 break; 362 } 363 } 364 365 #ifdef SALL_API_TEST 366 if (ret == AGSA_RC_SUCCESS) 367 saRoot->LLCounters.IOCounter.numSMPStarted++; 368 #endif 369 } 370 else /* IOMB is different for SPCV SMP */ 371 { 372 agsaSMPCmd_V_t vpayload; 373 374 switch ( agRequestType ) 375 { 376 case AGSA_SMP_INIT_REQ: 377 { 378 bit32 IR_IP_OV_res_phyId_DPdLen_res = 0; 379 /* Prepare the payload of IOMB */ 380 si_memset(&vpayload, 0, sizeof(agsaSMPCmd_V_t)); 381 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, tag), pRequest->HTag); 382 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, deviceId), pDevice->DeviceMapIndex); 383 384 /* Request header must be valid regardless of IP bit */ 385 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMPHDR ), *((bit32*)pSMPFrame->outFrameBuf+0) ); 386 387 /* check SMP Response Frame with IR mode */ 388 /* check if the SMP Response is indirect mode */ 389 // smpFrameFlagDirectResponse smpFrameFlagDirectPayload 390 if ( 0 == pSMPFrame->flag && pSMPFrame->outFrameBuf ) 391 { 392 /* PHY override not support */ 393 /* Direct Response mode */ 394 pRequest->IRmode = DIRECT_MODE; 395 SA_DBG2(("saSMPStart:V DIRECT Request SMP\n")); 396 397 IR_IP_OV_res_phyId_DPdLen_res = (DIRECT_MODE << 1) | IR_IP_OV_res_phyId_DPdLen_res; 398 399 /* Direct payload length */ 400 IR_IP_OV_res_phyId_DPdLen_res |= (((pSMPFrame->outFrameLen) & 0xff) << SHIFT16); 401 /* Write IR_IP_OV_res_phyId_DPdLen_res field in the payload*/ 402 /* fatal error if missing */ 403 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, IR_IP_OV_res_phyId_DPdLen_res), IR_IP_OV_res_phyId_DPdLen_res); 404 /* fatal error if missing */ 405 406 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP3_0 ), *((bit32*)pSMPFrame->outFrameBuf+1) ); 407 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP7_4 ), *((bit32*)pSMPFrame->outFrameBuf+2) ); 408 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP11_8), *((bit32*)pSMPFrame->outFrameBuf+3) ); 409 410 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirL_SMPRF15_12 ), *((bit32*)pSMPFrame->outFrameBuf+4) ); 411 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirH_or_SMPRF19_16 ), *((bit32*)pSMPFrame->outFrameBuf+5) ); 412 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirLen_or_SMPRF23_20 ),*((bit32*)pSMPFrame->outFrameBuf+6) ); 413 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,R_or_SMPRF27_24), *((bit32*)pSMPFrame->outFrameBuf+7) ); 414 415 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,ISRAL_or_SMPRF31_28 ), *((bit32*)pSMPFrame->outFrameBuf+8) ); 416 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,ISRAH_or_SMPRF35_32 ), *((bit32*)pSMPFrame->outFrameBuf+9) ); 417 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,ISRL_or_SMPRF39_36 ), *((bit32*)pSMPFrame->outFrameBuf+10) ); 418 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,R_or_SMPRF43_40 ), *((bit32*)pSMPFrame->outFrameBuf+11) ); 419 420 } 421 else if (smpFrameFlagIndirectResponse & pSMPFrame->flag && smpFrameFlagIndirectPayload & pSMPFrame->flag) /* */ 422 { 423 /* IR IP */ 424 SA_DBG2(("saSMPStart:V smpFrameFlagIndirectResponse smpFrameFlagIndirectPayload SMP\n")); 425 426 pRequest->IRmode = INDIRECT_MODE; 427 IR_IP_OV_res_phyId_DPdLen_res = 3; 428 429 /* Indirect payload mode */ 430 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirL_SMPRF15_12 ), pSMPFrame->outFrameAddrLower32); 431 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirH_or_SMPRF19_16 ), pSMPFrame->outFrameAddrUpper32); 432 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirLen_or_SMPRF23_20 ), pSMPFrame->outFrameLen); 433 /* Indirect Response mode */ 434 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAL_or_SMPRF31_28 ), (pSMPFrame->inFrameAddrLower32)); 435 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAH_or_SMPRF35_32 ), (pSMPFrame->inFrameAddrUpper32)); 436 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRL_or_SMPRF39_36 ), (pSMPFrame->inFrameLen)); 437 } 438 else if (smpFrameFlagIndirectPayload & pSMPFrame->flag ) /* */ 439 { 440 /* IP */ 441 SA_DBG2(("saSMPStart:V smpFrameFlagIndirectPayload SMP\n")); 442 pRequest->IRmode = DIRECT_MODE; 443 IR_IP_OV_res_phyId_DPdLen_res = 2; 444 445 /* Indirect payload mode */ 446 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirL_SMPRF15_12 ), pSMPFrame->outFrameAddrLower32); 447 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirH_or_SMPRF19_16 ), pSMPFrame->outFrameAddrUpper32); 448 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirLen_or_SMPRF23_20 ), pSMPFrame->outFrameLen); 449 } 450 else if (smpFrameFlagIndirectResponse & pSMPFrame->flag ) /* */ 451 { 452 /* check IR bit */ 453 /* Indirect Response mode */ 454 pRequest->IRmode = INDIRECT_MODE; 455 SA_DBG2(("saSMPStart:V smpFrameFlagIndirectResponse SMP\n")); 456 /* use physical address */ 457 IR_IP_OV_res_phyId_DPdLen_res = 1; 458 /* Direct payload length */ 459 IR_IP_OV_res_phyId_DPdLen_res |= (((pSMPFrame->outFrameLen) & 0xff) << SHIFT16); 460 461 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP3_0 ), *((bit32*)pSMPFrame->outFrameBuf+1) ); 462 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP7_4 ), *((bit32*)pSMPFrame->outFrameBuf+2) ); 463 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP11_8), *((bit32*)pSMPFrame->outFrameBuf+3) ); 464 465 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirL_SMPRF15_12 ), *((bit32*)pSMPFrame->outFrameBuf+4) ); 466 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirH_or_SMPRF19_16 ), *((bit32*)pSMPFrame->outFrameBuf+5) ); 467 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirLen_or_SMPRF23_20 ),*((bit32*)pSMPFrame->outFrameBuf+6) ); 468 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,R_or_SMPRF27_24), *((bit32*)pSMPFrame->outFrameBuf+7) ); 469 470 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAL_or_SMPRF31_28 ), (pSMPFrame->inFrameAddrLower32)); 471 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAH_or_SMPRF35_32 ), (pSMPFrame->inFrameAddrUpper32)); 472 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRL_or_SMPRF39_36 ), (pSMPFrame->inFrameLen)); 473 } 474 IR_IP_OV_res_phyId_DPdLen_res |= (pSMPFrame->flag & 3); 475 /* fatal error if missing */ 476 OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, IR_IP_OV_res_phyId_DPdLen_res), IR_IP_OV_res_phyId_DPdLen_res); 477 /* fatal error if missing */ 478 } 479 /* Build IOMB command and send it to SPCv */ 480 payload_ptr = (bit8 *)&vpayload; 481 ret = mpiSMPCmd(agRoot, pMessage, OPC_INB_SMP_REQUEST, (agsaSMPCmd_t *)payload_ptr, inq, outq); 482 483 #ifdef SA_LL_IBQ_PROTECT 484 ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); 485 #endif /* SA_LL_IBQ_PROTECT */ 486 487 break; 488 default: 489 { 490 SA_DBG1(("saSMPStart: SPCv unknown agRequestType %x\n",agRequestType)); 491 break; 492 } 493 } 494 } 495 496 smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "9a"); 497 498 /* return */ 499 return ret; 500 } 501 502 /******************************************************************************/ 503 /*! \brief Abort SMP request 504 * 505 * Abort SMP request 506 * 507 * \param agRoot handles for this instance of SAS/SATA hardware 508 * \param queueNum 509 * \param agIORequest 510 * 511 * \return If request is aborted successfully 512 * - \e AGSA_RC_SUCCESS request is aborted successfully 513 * - \e AGSA_RC_FAILURE request is not aborted successfully 514 */ 515 /*******************************************************************************/ 516 GLOBAL bit32 saSMPAbort( 517 agsaRoot_t *agRoot, 518 agsaIORequest_t *agIORequest, 519 bit32 queueNum, 520 agsaDevHandle_t *agDevHandle, 521 bit32 flag, 522 void *abortParam, 523 ossaGenericAbortCB_t agCB 524 ) 525 { 526 bit32 ret = AGSA_RC_SUCCESS; 527 agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 528 agsaIORequestDesc_t *pRequest; 529 agsaIORequestDesc_t *pRequestABT = NULL; 530 agsaIORequest_t *agIOToBeAborted; 531 agsaDeviceDesc_t *pDevice; 532 agsaSMPAbortCmd_t payload; 533 bit32 using_reserved = agFALSE; 534 535 smTraceFuncEnter(hpDBG_VERY_LOUD,"9b"); 536 537 /* sanity check */ 538 SA_ASSERT((agNULL != agRoot), ""); 539 SA_ASSERT((agNULL != agIORequest), ""); 540 SA_ASSERT((agNULL != agDevHandle), ""); 541 542 SA_DBG3(("saSMPAbort: Aborting request %p\n", agIORequest)); 543 544 if( ABORT_SINGLE == (flag & ABORT_MASK) ) 545 { 546 agIOToBeAborted = (agsaIORequest_t *)abortParam; 547 /* Get LL IORequest entry for saSMPAbort() */ 548 pRequestABT = (agsaIORequestDesc_t *) (agIOToBeAborted->sdkData); 549 if (agNULL == pRequestABT) 550 { 551 /* The IO to Be Abort is no longer exist - can not Abort */ 552 SA_DBG1(("saSMPAbort: pRequestABT AGSA_RC_FAILURE\n")); 553 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "9b"); 554 return AGSA_RC_FAILURE; 555 } 556 557 /* Find the device the request Abort to */ 558 pDevice = pRequestABT->pDevice; 559 560 if (agNULL == pDevice) 561 { 562 /* no deviceID - can not build IOMB */ 563 SA_DBG1(("saSMPAbort: pDevice AGSA_RC_FAILURE\n")); 564 smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "9b"); 565 return AGSA_RC_FAILURE; 566 } 567 } 568 else 569 { 570 if (ABORT_ALL == (flag & ABORT_MASK)) 571 { 572 /* abort All with Device or Port */ 573 /* Find the outgoing port for the device */ 574 pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData); 575 if (agNULL == pDevice) 576 { 577 /* no deviceID - can not build IOMB */ 578 SA_DBG1(("saSMPAbort:ABORT_ALL pDevice AGSA_RC_FAILURE\n")); 579 smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "9b"); 580 return AGSA_RC_FAILURE; 581 } 582 } 583 else 584 { 585 /* only support 00 and 01 for flag */ 586 SA_DBG1(("saSMPAbort:flag AGSA_RC_FAILURE\n")); 587 smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "9b"); 588 return AGSA_RC_FAILURE; 589 } 590 } 591 592 /* Get LL IORequest entry */ 593 ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); 594 pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); 595 596 /* If no LL IO request entry available */ 597 if ( agNULL == pRequest ) 598 { 599 pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); /**/ 600 /* If no LL Control request entry available */ 601 if(agNULL != pRequest) 602 { 603 using_reserved = agTRUE; 604 SA_DBG1(("saSMPAbort, using saRoot->freeReservedRequests\n")); 605 } 606 else 607 { 608 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); 609 SA_DBG1(("saSMPAbort, No request from free list Not using saRoot->freeReservedRequests\n")); 610 smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "9b"); 611 return AGSA_RC_BUSY; 612 } 613 } 614 615 /* If free IOMB avaliable */ 616 /* Remove the request from free list */ 617 if( using_reserved ) 618 { 619 saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode)); 620 } 621 else 622 { 623 saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode)); 624 } 625 626 /* Add the request to the pendingSMPRequests list of the device */ 627 saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode)); 628 SA_ASSERT((!pRequest->valid), "The pRequest is in use"); 629 pRequest->valid = agTRUE; 630 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); 631 /* set up pRequest */ 632 pRequest->pIORequestContext = agIORequest; 633 pRequest->requestType = AGSA_SMP_REQTYPE; 634 pRequest->completionCB = (void*)agCB; 635 pRequest->pDevice = pDevice; 636 pRequest->startTick = saRoot->timeTick; 637 638 /* Set request to the sdkData of agIORequest */ 639 agIORequest->sdkData = pRequest; 640 641 /* save tag to IOMap */ 642 saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag; 643 saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest; 644 645 /* setup payload */ 646 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, tag), pRequest->HTag); 647 648 if( ABORT_SINGLE == (flag & ABORT_MASK) ) 649 { 650 if (agNULL == pRequestABT) 651 { 652 /* remove the request from IOMap */ 653 saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF; 654 saRoot->IOMap[pRequest->HTag].IORequest = agNULL; 655 saRoot->IOMap[pRequest->HTag].agContext = agNULL; 656 /* Delete the request from the pendingSMPRequests */ 657 ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); 658 saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); 659 /* return the request to free pool */ 660 if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT) 661 { 662 SA_DBG1(("saSMPAbort: saving pRequest (%p) for later use\n", pRequest)); 663 saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode)); 664 } 665 else 666 { 667 /* return the request to free pool */ 668 saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); 669 } 670 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); 671 SA_DBG1(("saSMPAbort, agNULL == pRequestABT\n")); 672 /* The IO to Be Abort is no longer exist - can not Abort */ 673 smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "9b"); 674 return AGSA_RC_FAILURE; 675 } 676 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, HTagAbort), pRequestABT->HTag); 677 } 678 else 679 { 680 /* abort all */ 681 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, HTagAbort), 0); 682 } 683 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, deviceId), pDevice->DeviceMapIndex); 684 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, Scp), flag); 685 686 SA_DBG1(("saSMPAbort, HTag 0x%x HTagABT 0x%x deviceId 0x%x\n", payload.tag, payload.HTagAbort, payload.deviceId)); 687 688 /* build IOMB command and send to SPC */ 689 ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SMP_ABORT, IOMB_SIZE64, queueNum); 690 if (AGSA_RC_SUCCESS != ret) 691 { 692 /* remove the request from IOMap */ 693 saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF; 694 saRoot->IOMap[pRequest->HTag].IORequest = agNULL; 695 saRoot->IOMap[pRequest->HTag].agContext = agNULL; 696 /* Delete the request from the pendingSMPRequests */ 697 ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); 698 saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); 699 /* return the request to free pool */ 700 if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT) 701 { 702 SA_DBG1(("saSMPAbort: saving pRequest (%p) for later use\n", pRequest)); 703 saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode)); 704 } 705 else 706 { 707 /* return the request to free pool */ 708 saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); 709 } 710 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); 711 SA_DBG1(("saSMPAbort, sending IOMB failed\n" )); 712 } 713 #ifdef SALL_API_TEST 714 else 715 { 716 saRoot->LLCounters.IOCounter.numSMPAborted++; 717 } 718 #endif 719 720 smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "9b"); 721 722 return ret; 723 } 724 725 726 727