xref: /freebsd/sys/contrib/ncsw/Peripherals/FM/Pcd/fm_prs.c (revision ccb59683b98360afaf5b5bb641a68fea22c68d0b)
1 /*
2  * Copyright 2008-2012 Freescale Semiconductor Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above copyright
9  *       notice, this list of conditions and the following disclaimer in the
10  *       documentation and/or other materials provided with the distribution.
11  *     * Neither the name of Freescale Semiconductor nor the
12  *       names of its contributors may be used to endorse or promote products
13  *       derived from this software without specific prior written permission.
14  *
15  *
16  * ALTERNATIVELY, this software may be distributed under the terms of the
17  * GNU General Public License ("GPL") as published by the Free Software
18  * Foundation, either version 2 of that License or (at your option) any
19  * later version.
20  *
21  * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 
34 /******************************************************************************
35  @File          fm_pcd.c
36 
37  @Description   FM PCD ...
38 *//***************************************************************************/
39 #include <linux/math64.h>
40 #include "std_ext.h"
41 #include "error_ext.h"
42 #include "string_ext.h"
43 #include "debug_ext.h"
44 #include "net_ext.h"
45 
46 #include "fm_common.h"
47 #include "fm_pcd.h"
48 #include "fm_pcd_ipc.h"
49 #include "fm_prs.h"
50 #include "fsl_fman_prs.h"
51 
52 
53 static void PcdPrsErrorException(t_Handle h_FmPcd)
54 {
55     t_FmPcd                 *p_FmPcd = (t_FmPcd *)h_FmPcd;
56     uint32_t                event, ev_mask;
57     struct fman_prs_regs     *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
58 
59     ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
60     ev_mask = fman_prs_get_err_ev_mask(PrsRegs);
61 
62     event = fman_prs_get_err_event(PrsRegs, ev_mask);
63 
64     fman_prs_ack_err_event(PrsRegs, event);
65 
66     DBG(TRACE, ("parser error - 0x%08x\n",event));
67 
68     if(event & FM_PCD_PRS_DOUBLE_ECC)
69         p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC);
70 }
71 
72 static void PcdPrsException(t_Handle h_FmPcd)
73 {
74     t_FmPcd             *p_FmPcd = (t_FmPcd *)h_FmPcd;
75     uint32_t            event, ev_mask;
76     struct fman_prs_regs     *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
77 
78     ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
79     ev_mask = fman_prs_get_expt_ev_mask(PrsRegs);
80     event = fman_prs_get_expt_event(PrsRegs, ev_mask);
81 
82     ASSERT_COND(event & FM_PCD_PRS_SINGLE_ECC);
83 
84     DBG(TRACE, ("parser event - 0x%08x\n",event));
85 
86     fman_prs_ack_expt_event(PrsRegs, event);
87 
88     p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC);
89 }
90 
91 t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams)
92 {
93     t_FmPcdPrs  *p_FmPcdPrs;
94     uintptr_t   baseAddr;
95 
96     UNUSED(p_FmPcd);
97     UNUSED(p_FmPcdParams);
98 
99     p_FmPcdPrs = (t_FmPcdPrs *) XX_Malloc(sizeof(t_FmPcdPrs));
100     if (!p_FmPcdPrs)
101     {
102         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Parser structure allocation FAILED"));
103         return NULL;
104     }
105     memset(p_FmPcdPrs, 0, sizeof(t_FmPcdPrs));
106     fman_prs_defconfig(&p_FmPcd->p_FmPcdDriverParam->dfltCfg);
107 
108     if (p_FmPcd->guestId == NCSW_MASTER_ID)
109     {
110         baseAddr = FmGetPcdPrsBaseAddr(p_FmPcdParams->h_Fm);
111         p_FmPcdPrs->p_SwPrsCode  = (uint32_t *)UINT_TO_PTR(baseAddr);
112         p_FmPcdPrs->p_FmPcdPrsRegs  = (struct fman_prs_regs *)UINT_TO_PTR(baseAddr + PRS_REGS_OFFSET);
113     }
114 
115     p_FmPcdPrs->fmPcdPrsPortIdStatistics = p_FmPcd->p_FmPcdDriverParam->dfltCfg.port_id_stat;
116     p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = p_FmPcd->p_FmPcdDriverParam->dfltCfg.max_prs_cyc_lim;
117     p_FmPcd->exceptions |= p_FmPcd->p_FmPcdDriverParam->dfltCfg.prs_exceptions;
118 
119     return p_FmPcdPrs;
120 }
121 
122 #if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT))
123     static uint8_t             swPrsPatch[] = SW_PRS_UDP_LITE_PATCH;
124 #else
125     static uint8_t             swPrsPatch[] = SW_PRS_OFFLOAD_PATCH;
126 #endif /* FM_CAPWAP_SUPPORT */
127 
128 t_Error PrsInit(t_FmPcd *p_FmPcd)
129 {
130     t_FmPcdDriverParam  *p_Param = p_FmPcd->p_FmPcdDriverParam;
131     uint32_t            *p_TmpCode;
132     uint32_t            *p_LoadTarget = (uint32_t *)PTR_MOVE(p_FmPcd->p_FmPcdPrs->p_SwPrsCode,
133                                                              FM_PCD_SW_PRS_SIZE-FM_PCD_PRS_SW_PATCHES_SIZE);
134     struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
135     uint32_t            i;
136 
137     ASSERT_COND(sizeof(swPrsPatch) <= (FM_PCD_PRS_SW_PATCHES_SIZE-FM_PCD_PRS_SW_TAIL_SIZE));
138 
139     /* nothing to do in guest-partition */
140     if (p_FmPcd->guestId != NCSW_MASTER_ID)
141         return E_OK;
142 
143     p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(sizeof(swPrsPatch),4), 0, sizeof(uint32_t));
144     if (!p_TmpCode)
145         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED"));
146     memset((uint8_t *)p_TmpCode, 0, ROUND_UP(sizeof(swPrsPatch),4));
147     memcpy((uint8_t *)p_TmpCode, (uint8_t *)swPrsPatch, sizeof(swPrsPatch));
148 
149     fman_prs_init(PrsRegs, &p_Param->dfltCfg);
150 
151     /* register even if no interrupts enabled, to allow future enablement */
152     FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR, PcdPrsErrorException, p_FmPcd);
153 
154     /* register even if no interrupts enabled, to allow future enablement */
155     FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL, PcdPrsException, p_FmPcd);
156 
157     if(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC)
158         FmEnableRamsEcc(p_FmPcd->h_Fm);
159 
160     if(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC)
161         FmEnableRamsEcc(p_FmPcd->h_Fm);
162 
163     /* load sw parser Ip-Frag patch */
164     for (i=0; i<DIV_CEIL(sizeof(swPrsPatch), 4); i++)
165         WRITE_UINT32(p_LoadTarget[i], GET_UINT32(p_TmpCode[i]));
166 
167     XX_FreeSmart(p_TmpCode);
168 
169     return E_OK;
170 }
171 
172 void PrsFree(t_FmPcd *p_FmPcd)
173 {
174     ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
175     FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR);
176     /* register even if no interrupts enabled, to allow future enablement */
177     FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL);
178 }
179 
180 void PrsEnable(t_FmPcd *p_FmPcd)
181 {
182     struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
183 
184     ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
185     fman_prs_enable(PrsRegs);
186 }
187 
188 void PrsDisable(t_FmPcd *p_FmPcd)
189 {
190     struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
191 
192     ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
193     fman_prs_disable(PrsRegs);
194 }
195 
196 int PrsIsEnabled(t_FmPcd *p_FmPcd)
197 {
198     struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
199 
200     ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
201     return fman_prs_is_enabled(PrsRegs);
202 }
203 
204 t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include)
205 {
206     struct fman_prs_regs *PrsRegs;
207     uint32_t    bitMask = 0;
208     uint8_t     prsPortId;
209 
210     SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE);
211     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
212     SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
213 
214     PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
215 
216     GET_FM_PCD_PRS_PORT_ID(prsPortId, hardwarePortId);
217     GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId);
218 
219     if (include)
220         p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics |= bitMask;
221     else
222         p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics &= ~bitMask;
223 
224     fman_prs_set_stst_port_msk(PrsRegs,
225             p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics);
226 
227     return E_OK;
228 }
229 
230 t_Error FmPcdPrsIncludePortInStatistics(t_Handle h_FmPcd, uint8_t hardwarePortId, bool include)
231 {
232     t_FmPcd                     *p_FmPcd = (t_FmPcd *)h_FmPcd;
233     t_Error                     err;
234 
235     SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE);
236     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
237     SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
238 
239     if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
240         p_FmPcd->h_IpcSession)
241     {
242         t_FmPcdIpcPrsIncludePort    prsIncludePortParams;
243         t_FmPcdIpcMsg               msg;
244 
245         prsIncludePortParams.hardwarePortId = hardwarePortId;
246         prsIncludePortParams.include = include;
247         memset(&msg, 0, sizeof(msg));
248         msg.msgId = FM_PCD_PRS_INC_PORT_STATS;
249         memcpy(msg.msgBody, &prsIncludePortParams, sizeof(prsIncludePortParams));
250         err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
251                                 (uint8_t*)&msg,
252                                 sizeof(msg.msgId) +sizeof(prsIncludePortParams),
253                                 NULL,
254                                 NULL,
255                                 NULL,
256                                 NULL);
257         if (err != E_OK)
258             RETURN_ERROR(MAJOR, err, NO_MSG);
259         return E_OK;
260     }
261     else if (p_FmPcd->guestId != NCSW_MASTER_ID)
262         RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
263                      ("running in guest-mode without IPC!"));
264 
265     return PrsIncludePortInStatistics(p_FmPcd, hardwarePortId, include);
266 }
267 
268 uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr)
269 {
270     t_FmPcd                 *p_FmPcd = (t_FmPcd *)h_FmPcd;
271     t_FmPcdPrsLabelParams   *p_Label;
272     int                     i;
273 
274     SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, 0);
275     SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE, 0);
276 
277     if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
278         p_FmPcd->h_IpcSession)
279     {
280         t_Error                 err = E_OK;
281         t_FmPcdIpcSwPrsLable    labelParams;
282         t_FmPcdIpcMsg           msg;
283         uint32_t                prsOffset = 0;
284         t_FmPcdIpcReply         reply;
285         uint32_t                replyLength;
286 
287         memset(&reply, 0, sizeof(reply));
288         memset(&msg, 0, sizeof(msg));
289         labelParams.enumHdr = (uint32_t)hdr;
290         labelParams.indexPerHdr = indexPerHdr;
291         msg.msgId = FM_PCD_GET_SW_PRS_OFFSET;
292         memcpy(msg.msgBody, &labelParams, sizeof(labelParams));
293         replyLength = sizeof(uint32_t) + sizeof(uint32_t);
294         err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
295                                 (uint8_t*)&msg,
296                                 sizeof(msg.msgId) +sizeof(labelParams),
297                                 (uint8_t*)&reply,
298                                 &replyLength,
299                                 NULL,
300                                 NULL);
301         if (err != E_OK)
302             RETURN_ERROR(MAJOR, err, NO_MSG);
303         if (replyLength != sizeof(uint32_t) + sizeof(uint32_t))
304             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
305 
306         memcpy((uint8_t*)&prsOffset, reply.replyBody, sizeof(uint32_t));
307         return prsOffset;
308     }
309     else if (p_FmPcd->guestId != NCSW_MASTER_ID)
310         RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
311                      ("running in guest-mode without IPC!"));
312 
313     ASSERT_COND(p_FmPcd->p_FmPcdPrs->currLabel < FM_PCD_PRS_NUM_OF_LABELS);
314 
315     for (i=0; i<p_FmPcd->p_FmPcdPrs->currLabel; i++)
316     {
317         p_Label = &p_FmPcd->p_FmPcdPrs->labelsTable[i];
318 
319         if ((hdr == p_Label->hdr) && (indexPerHdr == p_Label->indexPerHdr))
320             return p_Label->instructionOffset;
321     }
322 
323     REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Sw Parser attachment Not found"));
324     return (uint32_t)ILLEGAL_BASE;
325 }
326 
327 void FM_PCD_SetPrsStatistics(t_Handle h_FmPcd, bool enable)
328 {
329     t_FmPcd             *p_FmPcd = (t_FmPcd*)h_FmPcd;
330     struct fman_prs_regs *PrsRegs;
331 
332     SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE);
333     SANITY_CHECK_RETURN(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
334 
335     PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
336 
337 
338     if(p_FmPcd->guestId != NCSW_MASTER_ID)
339     {
340         REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPrsStatistics - guest mode!"));
341         return;
342     }
343 
344     fman_prs_set_stst(PrsRegs, enable);
345 }
346 
347 t_Error FM_PCD_PrsLoadSw(t_Handle h_FmPcd, t_FmPcdPrsSwParams *p_SwPrs)
348 {
349     t_FmPcd                 *p_FmPcd = (t_FmPcd*)h_FmPcd;
350     uint32_t                *p_LoadTarget;
351     uint32_t                *p_TmpCode;
352     int                     i;
353 
354     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
355     SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
356     SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_STATE);
357     SANITY_CHECK_RETURN_ERROR(p_SwPrs, E_INVALID_HANDLE);
358     SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_HANDLE);
359 
360     if (p_FmPcd->guestId != NCSW_MASTER_ID)
361         RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode!"));
362 
363     if (!p_SwPrs->override)
364     {
365         if(p_FmPcd->p_FmPcdPrs->p_CurrSwPrs > p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4)
366             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SW parser base must be larger than current loaded code"));
367     }
368     else
369         p_FmPcd->p_FmPcdPrs->currLabel = 0;
370 
371     if (p_SwPrs->size > FM_PCD_SW_PRS_SIZE - FM_PCD_PRS_SW_TAIL_SIZE - p_SwPrs->base*2)
372         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_SwPrs->size may not be larger than MAX_SW_PRS_CODE_SIZE"));
373 
374     if (p_FmPcd->p_FmPcdPrs->currLabel + p_SwPrs->numOfLabels > FM_PCD_PRS_NUM_OF_LABELS)
375         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceeded number of labels allowed "));
376 
377     p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(p_SwPrs->size,4), 0, sizeof(uint32_t));
378     if (!p_TmpCode)
379         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED"));
380     memset((uint8_t *)p_TmpCode, 0, ROUND_UP(p_SwPrs->size,4));
381     memcpy((uint8_t *)p_TmpCode, p_SwPrs->p_Code, p_SwPrs->size);
382 
383     /* save sw parser labels */
384     memcpy(&p_FmPcd->p_FmPcdPrs->labelsTable[p_FmPcd->p_FmPcdPrs->currLabel],
385            p_SwPrs->labelsTable,
386            p_SwPrs->numOfLabels*sizeof(t_FmPcdPrsLabelParams));
387     p_FmPcd->p_FmPcdPrs->currLabel += p_SwPrs->numOfLabels;
388 
389     /* load sw parser code */
390     p_LoadTarget = p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4;
391 
392     for(i=0; i<DIV_CEIL(p_SwPrs->size, 4); i++)
393         WRITE_UINT32(p_LoadTarget[i], GET_UINT32(p_TmpCode[i]));
394 
395     p_FmPcd->p_FmPcdPrs->p_CurrSwPrs =
396         p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4 + ROUND_UP(p_SwPrs->size,4);
397 
398     /* copy data parameters */
399     for (i=0;i<FM_PCD_PRS_NUM_OF_HDRS;i++)
400         WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+PRS_SW_DATA/4+i), p_SwPrs->swPrsDataParams[i]);
401 
402     /* Clear last 4 bytes */
403     WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+(PRS_SW_DATA-FM_PCD_PRS_SW_TAIL_SIZE)/4), 0);
404 
405     XX_FreeSmart(p_TmpCode);
406 
407     return E_OK;
408 }
409 
410 t_Error FM_PCD_ConfigPrsMaxCycleLimit(t_Handle h_FmPcd,uint16_t value)
411 {
412     t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
413 
414     SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
415     SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
416 
417     if(p_FmPcd->guestId != NCSW_MASTER_ID)
418         RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPrsMaxCycleLimit - guest mode!"));
419 
420     p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = value;
421 
422     return E_OK;
423 }
424