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