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/*******************************************************************************/
61GLOBAL 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/*******************************************************************************/
516GLOBAL 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