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 /*******************************************************************************/
saSMPStart(agsaRoot_t * agRoot,agsaIORequest_t * agIORequest,bit32 queueNum,agsaDevHandle_t * agDevHandle,bit32 agRequestType,agsaSASRequestBody_t * agRequestBody,ossaSMPCompletedCB_t agCB)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 /*******************************************************************************/
saSMPAbort(agsaRoot_t * agRoot,agsaIORequest_t * agIORequest,bit32 queueNum,agsaDevHandle_t * agDevHandle,bit32 flag,void * abortParam,ossaGenericAbortCB_t agCB)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