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
Cache object: aff1370e0f5c382e8cf3b9d3015ed345
|