1 /******************************************************************************
2 
3  � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
4  All rights reserved.
5 
6  This is proprietary source code of Freescale Semiconductor Inc.,
7  and its use is subject to the NetComm Device Drivers EULA.
8  The copyright notice above does not evidence any actual or intended
9  publication of such source code.
10 
11  ALTERNATIVELY, redistribution and use in source and binary forms, with
12  or without modification, are permitted provided that the following
13  conditions are met:
14      * Redistributions of source code must retain the above copyright
15        notice, this list of conditions and the following disclaimer.
16      * Redistributions in binary form must reproduce the above copyright
17        notice, this list of conditions and the following disclaimer in the
18        documentation and/or other materials provided with the distribution.
19      * Neither the name of Freescale Semiconductor nor the
20        names of its contributors may be used to endorse or promote products
21        derived from this software without specific prior written permission.
22 
23  THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34 
35  **************************************************************************/
36 /******************************************************************************
37  @File          bm.c
38 
39  @Description   BM
40 *//***************************************************************************/
41 #include "error_ext.h"
42 #include "std_ext.h"
43 #include "string_ext.h"
44 #include "mem_ext.h"
45 #include "core_ext.h"
46 
47 #include "bm.h"
48 
49 
50 #define __ERR_MODULE__  MODULE_BM
51 
52 
53 /****************************************/
54 /*       static functions               */
55 /****************************************/
56 
57 /* (De)Registration of depletion notification callbacks */
58 static void depletion_link(t_BmPool *p_BmPool)
59 {
60     t_BmPortal *p_Portal = (t_BmPortal *)p_BmPool->h_BmPortal;
61 
62     NCSW_PLOCK(p_Portal);
63     p_Portal->depletionPoolsTable[p_BmPool->bpid] = p_BmPool;
64     bm_isr_bscn_mask(p_Portal->p_BmPortalLow, (uint8_t)p_BmPool->bpid, 1);
65     PUNLOCK(p_Portal);
66 }
67 
68 static void depletion_unlink(t_BmPool *p_BmPool)
69 {
70     t_BmPortal *p_Portal = (t_BmPortal *)p_BmPool->h_BmPortal;
71 
72     NCSW_PLOCK(p_Portal);
73     p_Portal->depletionPoolsTable[p_BmPool->bpid] = NULL;
74     bm_isr_bscn_mask(p_Portal->p_BmPortalLow, (uint8_t)p_BmPool->bpid, 0);
75     PUNLOCK(p_Portal);
76 }
77 
78 static t_Error BmPoolRelease(t_BmPool *p_BmPool,
79                              t_Handle h_BmPortal,
80                              struct bm_buffer *bufs,
81                              uint8_t num,
82                              uint32_t flags)
83 {
84     ASSERT_COND(num && (num <= 8));
85     if (p_BmPool->flags & BMAN_POOL_FLAG_NO_RELEASE)
86         return ERROR_CODE(E_INVALID_VALUE);
87 
88     /* Without stockpile, this API is a pass-through to the h/w operation */
89     if (!(p_BmPool->flags & BMAN_POOL_FLAG_STOCKPILE))
90         return BmPortalRelease(h_BmPortal, p_BmPool->bpid, bufs, num, flags);
91 
92     /* This needs some explanation. Adding the given buffers may take the
93      * stockpile over the threshold, but in fact the stockpile may already
94      * *be* over the threshold if a previous release-to-hw attempt had
95      * failed. So we have 3 cases to cover;
96      *   1. we add to the stockpile and don't hit the threshold,
97      *   2. we add to the stockpile, hit the threshold and release-to-hw,
98      *   3. we have to release-to-hw before adding to the stockpile
99      *      (not enough room in the stockpile for case 2).
100      * Our constraints on thresholds guarantee that in case 3, there must be
101      * at least 8 bufs already in the stockpile, so all release-to-hw ops
102      * are for 8 bufs. Despite all this, the API must indicate whether the
103      * given buffers were taken off the caller's hands, irrespective of
104      * whether a release-to-hw was attempted. */
105     while (num)
106     {
107         /* Add buffers to stockpile if they fit */
108         if ((p_BmPool->spFill + num) <= p_BmPool->spMaxBufs)
109         {
110             memcpy(PTR_MOVE(p_BmPool->sp, sizeof(struct bm_buffer) * (p_BmPool->spFill)),
111                    bufs,
112                    sizeof(struct bm_buffer) * num);
113             p_BmPool->spFill += num;
114             num = 0; /* --> will return success no matter what */
115         }
116         else
117         /* Do hw op if hitting the high-water threshold */
118         {
119             t_Error ret = BmPortalRelease(h_BmPortal,
120                                           p_BmPool->bpid,
121                                           (struct bm_buffer *)PTR_MOVE(p_BmPool->sp, sizeof(struct bm_buffer) * (p_BmPool->spFill - p_BmPool->spBufsCmd)),
122                                           p_BmPool->spBufsCmd,
123                                           flags);
124             if (ret)
125                 return (num ? ret : E_OK);
126             p_BmPool->spFill -= p_BmPool->spBufsCmd;
127         }
128     }
129 
130     return E_OK;
131 }
132 
133 static int BmPoolAcquire(t_BmPool *p_BmPool,t_Handle h_BmPortal,
134             struct bm_buffer *bufs, uint8_t num, uint32_t flags)
135 {
136     ASSERT_COND(IN_RANGE(1, num, 8));
137     if (p_BmPool->flags & BMAN_POOL_FLAG_ONLY_RELEASE)
138         return 0;
139 
140     /* Without stockpile, this API is a pass-through to the h/w operation */
141     if (!(p_BmPool->flags & BMAN_POOL_FLAG_STOCKPILE))
142         return BmPortalAcquire(h_BmPortal, p_BmPool->bpid, bufs, num);
143     /* Only need a h/w op if we'll hit the low-water thresh */
144     if (!(flags & BMAN_ACQUIRE_FLAG_STOCKPILE) &&
145             ((p_BmPool->spFill - num) < p_BmPool->spMinBufs))
146     {
147             p_BmPool->spFill += BmPortalAcquire(h_BmPortal,
148                                                p_BmPool->bpid,
149                                                (struct bm_buffer *)PTR_MOVE(p_BmPool->sp, sizeof(struct bm_buffer) * (p_BmPool->spFill)),
150                                                p_BmPool->spBufsCmd);
151     }
152     else if (p_BmPool->spFill < num)
153         return 0;
154     if (!p_BmPool->spFill)
155         return 0;
156     memcpy(bufs,
157            PTR_MOVE(p_BmPool->sp, sizeof(struct bm_buffer) * (p_BmPool->spFill - num)),
158            sizeof(struct bm_buffer) * num);
159     p_BmPool->spFill -= num;
160     return num;
161 }
162 
163 static t_Error BmPoolFree(t_BmPool *p_BmPool, bool discardBuffers)
164 {
165     t_Handle    h_BufContext;
166     void        *p_Data;
167 
168     ASSERT_COND(p_BmPool);
169 
170     if (!p_BmPool->shadowMode)
171     {
172         if (p_BmPool->flags & BMAN_POOL_FLAG_DEPLETION)
173         {
174             depletion_unlink(p_BmPool);
175             BmUnSetPoolThresholds(p_BmPool->h_Bm, p_BmPool->bpid);
176         }
177         while (TRUE)
178         {
179             p_Data = BM_POOL_GetBuf(p_BmPool, p_BmPool->h_BmPortal);
180             if (!p_Data)
181                 break;
182             h_BufContext = BM_POOL_GetBufferContext(p_BmPool, p_Data);
183             if (!discardBuffers)
184                 p_BmPool->bufferPoolInfo.f_PutBuf(p_BmPool->bufferPoolInfo.h_BufferPool, p_Data, h_BufContext);
185         }
186         BmBpidPut(p_BmPool->h_Bm, p_BmPool->bpid);
187     }
188 
189     if (p_BmPool->sp)
190         XX_Free(p_BmPool->sp);
191 
192     XX_Free(p_BmPool);
193 
194     return E_OK;
195 }
196 
197 /****************************************/
198 /*       API Init unit functions        */
199 /****************************************/
200 
201 t_Handle BM_POOL_Config(t_BmPoolParam *p_BmPoolParam)
202 {
203     t_BmPool        *p_BmPool;
204 
205     SANITY_CHECK_RETURN_VALUE(p_BmPoolParam, E_INVALID_HANDLE, NULL);
206     SANITY_CHECK_RETURN_VALUE(p_BmPoolParam->h_Bm, E_INVALID_HANDLE, NULL);
207     SANITY_CHECK_RETURN_VALUE((p_BmPoolParam->shadowMode ||
208                                (p_BmPoolParam->bufferPoolInfo.h_BufferPool &&
209                                p_BmPoolParam->bufferPoolInfo.f_GetBuf &&
210                                p_BmPoolParam->bufferPoolInfo.f_PutBuf &&
211                                p_BmPoolParam->bufferPoolInfo.bufferSize)), E_INVALID_STATE, NULL);
212 
213     p_BmPool = (t_BmPool*)XX_Malloc(sizeof(t_BmPool));
214     if (!p_BmPool)
215     {
216         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("BM Pool obj!!!"));
217         return NULL;
218     }
219     memset(p_BmPool, 0, sizeof(t_BmPool));
220 
221     p_BmPool->p_BmPoolDriverParams = (t_BmPoolDriverParams *)XX_Malloc(sizeof(t_BmPoolDriverParams));
222     if (!p_BmPool->p_BmPoolDriverParams)
223     {
224         XX_Free(p_BmPool);
225         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Bm Pool driver parameters"));
226         return NULL;
227     }
228     memset(p_BmPool->p_BmPoolDriverParams, 0, sizeof(t_BmPoolDriverParams));
229 
230     p_BmPool->h_Bm          = p_BmPoolParam->h_Bm;
231     p_BmPool->h_BmPortal    = p_BmPoolParam->h_BmPortal;
232     p_BmPool->h_App         = p_BmPoolParam->h_App;
233     p_BmPool->numOfBuffers  = p_BmPoolParam->numOfBuffers;
234     p_BmPool->shadowMode    = p_BmPoolParam->shadowMode;
235 
236     if (!p_BmPool->h_BmPortal)
237     {
238         p_BmPool->h_BmPortal = BmGetPortalHandle(p_BmPool->h_Bm);
239         SANITY_CHECK_RETURN_VALUE(p_BmPool->h_BmPortal, E_INVALID_HANDLE, NULL);
240     }
241 
242     memcpy(&p_BmPool->bufferPoolInfo, &p_BmPoolParam->bufferPoolInfo, sizeof(t_BufferPoolInfo));
243     if (!p_BmPool->bufferPoolInfo.f_PhysToVirt)
244         p_BmPool->bufferPoolInfo.f_PhysToVirt = XX_PhysToVirt;
245     if (!p_BmPool->bufferPoolInfo.f_VirtToPhys)
246         p_BmPool->bufferPoolInfo.f_VirtToPhys = XX_VirtToPhys;
247 
248     p_BmPool->p_BmPoolDriverParams->dynamicBpid     = DEFAULT_dynamicBpid;
249     p_BmPool->p_BmPoolDriverParams->useDepletion    = DEFAULT_useDepletion;
250     p_BmPool->p_BmPoolDriverParams->useStockpile    = DEFAULT_useStockpile;
251 
252     if (p_BmPool->shadowMode)
253     {
254         p_BmPool->numOfBuffers = 0;
255         BM_POOL_ConfigBpid(p_BmPool, p_BmPoolParam->bpid);
256     }
257 
258     return p_BmPool;
259 }
260 
261 t_Error BM_POOL_Init(t_Handle h_BmPool)
262 {
263     t_BmPool        *p_BmPool = (t_BmPool *)h_BmPool;
264     t_Error         err;
265 
266     SANITY_CHECK_RETURN_ERROR(p_BmPool, E_INVALID_HANDLE);
267     SANITY_CHECK_RETURN_ERROR(p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE);
268 
269     p_BmPool->flags |= (p_BmPool->p_BmPoolDriverParams->dynamicBpid)?BMAN_POOL_FLAG_DYNAMIC_BPID:0;
270     p_BmPool->flags |= (p_BmPool->p_BmPoolDriverParams->useStockpile)?BMAN_POOL_FLAG_STOCKPILE:0;
271     p_BmPool->flags |= ((!p_BmPool->shadowMode) &&
272                         (p_BmPool->p_BmPoolDriverParams->useDepletion))?BMAN_POOL_FLAG_DEPLETION:0;
273 
274     if (p_BmPool->flags & BMAN_POOL_FLAG_DYNAMIC_BPID)
275     {
276         if((p_BmPool->bpid = (uint8_t)BmBpidGet(p_BmPool->h_Bm, FALSE, (uint32_t)0)) == (uint8_t)ILLEGAL_BASE)
277         {
278             BM_POOL_Free(p_BmPool);
279             RETURN_ERROR(CRITICAL, E_INVALID_STATE, ("can't allocate new dynamic pool id"));
280         }
281     }
282     else
283     {
284         if (BmBpidGet(p_BmPool->h_Bm, TRUE, (uint32_t)p_BmPool->bpid) == (uint32_t)ILLEGAL_BASE)
285         {
286             BM_POOL_Free(p_BmPool);
287             RETURN_ERROR(CRITICAL, E_INVALID_STATE, ("can't force pool id %d", p_BmPool->bpid));
288         }
289     }
290     if (p_BmPool->flags & BMAN_POOL_FLAG_DEPLETION)
291     {
292         if(BmSetPoolThresholds(p_BmPool->h_Bm, p_BmPool->bpid, p_BmPool->p_BmPoolDriverParams->depletionThresholds))
293         {
294             BM_POOL_Free(p_BmPool);
295             RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can't set thresh for pool bpid %d",p_BmPool->bpid));
296         }
297 
298         depletion_link(p_BmPool);
299     }
300 
301     if (p_BmPool->flags & BMAN_POOL_FLAG_STOCKPILE)
302     {
303         p_BmPool->sp = (struct bm_buffer *)XX_Malloc(sizeof(struct bm_buffer) * p_BmPool->spMaxBufs);
304         if (!p_BmPool->sp)
305         {
306             BM_POOL_Free(p_BmPool);
307             RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Bm Pool Stockpile"));
308         }
309         memset(p_BmPool->sp, 0, sizeof(struct bm_buffer) * p_BmPool->spMaxBufs);
310     }
311 
312     XX_Free(p_BmPool->p_BmPoolDriverParams);
313     p_BmPool->p_BmPoolDriverParams = NULL;
314 
315     /*******************/
316     /* Create buffers  */
317     /*******************/
318     if ((err = BM_POOL_FillBufs (p_BmPool, p_BmPool->h_BmPortal, p_BmPool->numOfBuffers)) != E_OK)
319     {
320         BM_POOL_Free(p_BmPool);
321         RETURN_ERROR(MAJOR, err, NO_MSG);
322     }
323 
324     return E_OK;
325 }
326 
327 t_Error BM_POOL_Free(t_Handle h_BmPool)
328 {
329     SANITY_CHECK_RETURN_ERROR(h_BmPool, E_INVALID_HANDLE);
330 
331     return BmPoolFree(h_BmPool, FALSE);
332 }
333 
334 t_Error  BM_POOL_ConfigBpid(t_Handle h_BmPool, uint8_t bpid)
335 {
336     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
337 
338     SANITY_CHECK_RETURN_ERROR(p_BmPool, E_INVALID_HANDLE);
339     SANITY_CHECK_RETURN_ERROR(p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE);
340     SANITY_CHECK_RETURN_ERROR(bpid < BM_MAX_NUM_OF_POOLS, E_INVALID_VALUE);
341 
342     p_BmPool->p_BmPoolDriverParams->dynamicBpid = FALSE;
343     p_BmPool->bpid = bpid;
344 
345     return E_OK;
346 }
347 
348 
349 t_Error  BM_POOL_ConfigDepletion(t_Handle h_BmPool, t_BmDepletionCallback *f_Depletion, uint32_t *p_Thresholds)
350 {
351     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
352 
353     SANITY_CHECK_RETURN_ERROR(p_BmPool, E_INVALID_HANDLE);
354     SANITY_CHECK_RETURN_ERROR(p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE);
355     SANITY_CHECK_RETURN_ERROR(f_Depletion, E_INVALID_HANDLE);
356 
357     p_BmPool->p_BmPoolDriverParams->useDepletion = TRUE;
358     p_BmPool->f_Depletion = f_Depletion;
359     memcpy(&p_BmPool->p_BmPoolDriverParams->depletionThresholds,
360            p_Thresholds,
361            sizeof(p_BmPool->p_BmPoolDriverParams->depletionThresholds));
362 
363     return E_OK;
364 }
365 
366 t_Error  BM_POOL_ConfigStockpile(t_Handle h_BmPool, uint16_t maxBuffers, uint16_t minBuffers)
367 {
368     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
369 
370     SANITY_CHECK_RETURN_ERROR(p_BmPool, E_INVALID_HANDLE);
371     SANITY_CHECK_RETURN_ERROR(p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE);
372     SANITY_CHECK_RETURN_ERROR(maxBuffers, E_INVALID_STATE);
373     SANITY_CHECK_RETURN_ERROR(maxBuffers >= minBuffers, E_INVALID_STATE);
374     SANITY_CHECK_RETURN_ERROR((p_BmPool->shadowMode ||
375                               ((maxBuffers * 2) <= p_BmPool->numOfBuffers)),
376                               E_INVALID_STATE);
377 
378     p_BmPool->p_BmPoolDriverParams->useStockpile = TRUE;
379     p_BmPool->spMaxBufs     = maxBuffers;
380     p_BmPool->spMinBufs     = minBuffers;
381     p_BmPool->spBufsCmd     = DEFAULT_numOfBufsPerCmd;
382 
383     SANITY_CHECK_RETURN_ERROR((p_BmPool->spMaxBufs >=
384                                (p_BmPool->spMinBufs + p_BmPool->spBufsCmd)),
385                               E_INVALID_STATE);
386 
387     return E_OK;
388 }
389 
390 t_Error  BM_POOL_ConfigBuffContextMode(t_Handle h_BmPool, bool en)
391 {
392     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
393 
394     SANITY_CHECK_RETURN_ERROR(p_BmPool, E_INVALID_HANDLE);
395     SANITY_CHECK_RETURN_ERROR(p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE);
396 
397     p_BmPool->noBuffCtxt = !en;
398 
399     return E_OK;
400 }
401 
402 void * BM_POOL_GetBuf(t_Handle h_BmPool, t_Handle h_BmPortal)
403 {
404     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
405     struct bm_buffer    bufs[1];
406     uint8_t             retBufsNum;
407     uint64_t            physAddr;
408     uint32_t            flags = 0;
409 
410     SANITY_CHECK_RETURN_VALUE(p_BmPool, E_INVALID_HANDLE, NULL);
411     SANITY_CHECK_RETURN_VALUE(!p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE, NULL);
412     SANITY_CHECK_RETURN_VALUE(p_BmPool->bufferPoolInfo.f_PhysToVirt, E_INVALID_STATE, NULL);
413 
414     if (!h_BmPortal)
415     {
416         if (p_BmPool->h_BmPortal)
417             h_BmPortal = p_BmPool->h_BmPortal;
418         else
419         {
420             SANITY_CHECK_RETURN_VALUE(p_BmPool->h_Bm, E_INVALID_HANDLE, NULL);
421             h_BmPortal = BmGetPortalHandle(p_BmPool->h_Bm);
422             SANITY_CHECK_RETURN_VALUE(h_BmPortal, E_INVALID_HANDLE, NULL);
423         }
424     }
425 
426     retBufsNum = (uint8_t)BmPoolAcquire(p_BmPool, h_BmPortal, bufs, 1, flags);
427     if (!retBufsNum)
428     {
429         REPORT_ERROR(TRACE, E_NOT_AVAILABLE, ("buffer"));
430         return NULL;
431     }
432     physAddr  = (uint64_t)bufs[0].lo;
433     physAddr |= (uint64_t)(((uint64_t)bufs[0].hi << 32) & 0x000000ff00000000LL);
434     DBG(TRACE,("Get Buffer : poolId %d, address 0x%016llx",
435                p_BmPool->bpid,
436                p_BmPool->bufferPoolInfo.f_PhysToVirt((physAddress_t)physAddr)));
437 
438     return p_BmPool->bufferPoolInfo.f_PhysToVirt((physAddress_t)physAddr);
439 }
440 
441 t_Error BM_POOL_PutBuf(t_Handle h_BmPool, t_Handle h_BmPortal, void *p_Buff)
442 {
443     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
444     uint64_t            physAddress;
445     struct bm_buffer    bufs[1];
446 
447     SANITY_CHECK_RETURN_ERROR(p_BmPool, E_INVALID_HANDLE);
448     SANITY_CHECK_RETURN_ERROR(!p_BmPool->p_BmPoolDriverParams, E_INVALID_STATE);
449     SANITY_CHECK_RETURN_ERROR(p_Buff, E_NULL_POINTER);
450 
451     physAddress = (uint64_t)(XX_VirtToPhys(p_Buff));
452 
453     bufs[0].bpid = p_BmPool->bpid;
454     bufs[0].hi = (uint8_t)((physAddress & 0x000000ff00000000LL) >> 32);
455     bufs[0].lo = (uint32_t)(physAddress & 0xffffffff);
456 
457     DBG(TRACE,("Put Buffer : poolId %d, address 0x%016llx, phys 0x%016llx",
458                p_BmPool->bpid, (uint64_t)PTR_TO_UINT(p_Buff), physAddress));
459 
460     if (!h_BmPortal)
461     {
462         if (p_BmPool->h_BmPortal)
463             h_BmPortal = p_BmPool->h_BmPortal;
464         else
465         {
466             SANITY_CHECK_RETURN_ERROR(p_BmPool->h_Bm, E_INVALID_HANDLE);
467             h_BmPortal = BmGetPortalHandle(p_BmPool->h_Bm);
468             SANITY_CHECK_RETURN_ERROR(h_BmPortal, E_INVALID_HANDLE);
469         }
470     }
471 
472     return BmPoolRelease(p_BmPool, h_BmPortal, bufs, 1, BMAN_RELEASE_FLAG_WAIT);
473 }
474 
475 t_Error BM_POOL_FillBufs(t_Handle h_BmPool, t_Handle h_BmPortal, uint32_t numBufs)
476 {
477     t_BmPool    *p_BmPool   = (t_BmPool *)h_BmPool;
478 
479     SANITY_CHECK_RETURN_ERROR(p_BmPool, E_INVALID_HANDLE);
480     SANITY_CHECK_RETURN_ERROR(!p_BmPool->p_BmPoolDriverParams, E_INVALID_STATE);
481 
482     if (!h_BmPortal)
483     {
484         if (p_BmPool->h_BmPortal)
485             h_BmPortal = p_BmPool->h_BmPortal;
486         else
487         {
488             SANITY_CHECK_RETURN_ERROR(p_BmPool->h_Bm, E_INVALID_HANDLE);
489             h_BmPortal = BmGetPortalHandle(p_BmPool->h_Bm);
490             SANITY_CHECK_RETURN_ERROR(h_BmPortal, E_INVALID_HANDLE);
491         }
492     }
493 
494     while (numBufs--)
495     {
496         uint8_t             *p_Data;
497         t_Error             res;
498         t_Handle            h_BufContext;
499 
500         p_Data = p_BmPool->bufferPoolInfo.f_GetBuf(p_BmPool->bufferPoolInfo.h_BufferPool, &h_BufContext);
501         if(!p_Data)
502             RETURN_ERROR(MAJOR, E_INVALID_STATE, ("run-out of buffers for bpid %d",p_BmPool->bpid));
503 
504         if (!p_BmPool->noBuffCtxt)
505             *(t_Handle *)(p_Data - sizeof(t_Handle)) = h_BufContext;
506 
507         if ((res = BM_POOL_PutBuf(p_BmPool, h_BmPortal, p_Data)) != E_OK)
508             RETURN_ERROR(CRITICAL, res, ("Seeding reserved buffer pool failed"));
509     }
510 
511     return E_OK;
512 }
513 
514 uint8_t BM_POOL_GetId(t_Handle h_BmPool)
515 {
516     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
517 
518     SANITY_CHECK_RETURN_VALUE(p_BmPool, E_INVALID_HANDLE, 0);
519     SANITY_CHECK_RETURN_VALUE(!p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE, 0);
520 
521     return p_BmPool->bpid;
522 }
523 
524 uint16_t BM_POOL_GetBufferSize(t_Handle h_BmPool)
525 {
526     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
527 
528     SANITY_CHECK_RETURN_VALUE(p_BmPool, E_INVALID_HANDLE, 0);
529     SANITY_CHECK_RETURN_VALUE(!p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE, 0);
530 
531     return p_BmPool->bufferPoolInfo.bufferSize;
532 }
533 
534 t_Handle BM_POOL_GetBufferContext(t_Handle h_BmPool, void *p_Buff)
535 {
536     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
537 
538     SANITY_CHECK_RETURN_VALUE(p_BmPool, E_INVALID_HANDLE, NULL);
539     SANITY_CHECK_RETURN_VALUE(!p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE, NULL);
540     SANITY_CHECK_RETURN_VALUE(p_Buff, E_NULL_POINTER, NULL);
541 
542     if (p_BmPool->noBuffCtxt)
543         return NULL;
544 
545     return *(t_Handle *)PTR_MOVE(p_Buff, -(sizeof(t_Handle)));
546 }
547 
548 void * BM_POOL_PhysToVirt(t_Handle h_BmPool, physAddress_t addr)
549 {
550     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
551 
552     SANITY_CHECK_RETURN_VALUE(p_BmPool, E_INVALID_HANDLE, NULL);
553     SANITY_CHECK_RETURN_VALUE(!p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE, NULL);
554 
555     return p_BmPool->bufferPoolInfo.f_PhysToVirt(addr);
556 }
557 
558 physAddress_t BM_POOL_VirtToPhys(t_Handle h_BmPool, void *p_Buff)
559 {
560     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
561 
562     SANITY_CHECK_RETURN_VALUE(p_BmPool, E_INVALID_HANDLE, (physAddress_t)0);
563     SANITY_CHECK_RETURN_VALUE(!p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE, (physAddress_t)0);
564 
565     return p_BmPool->bufferPoolInfo.f_VirtToPhys(p_Buff);
566 }
567 
568 uint32_t BM_POOL_GetCounter(t_Handle h_BmPool, e_BmPoolCounters counter)
569 {
570     t_BmPool            *p_BmPool   = (t_BmPool *)h_BmPool;
571 
572     SANITY_CHECK_RETURN_VALUE(p_BmPool, E_INVALID_HANDLE, 0);
573     SANITY_CHECK_RETURN_VALUE(!p_BmPool->p_BmPoolDriverParams, E_INVALID_HANDLE, 0);
574 
575     switch(counter)
576     {
577         case(e_BM_POOL_COUNTERS_CONTENT):
578             return BmGetCounter(p_BmPool->h_Bm, e_BM_IM_COUNTERS_POOL_CONTENT, p_BmPool->bpid);
579         case(e_BM_POOL_COUNTERS_SW_DEPLETION):
580             return (p_BmPool->swDepletionCount +=
581                 BmGetCounter(p_BmPool->h_Bm, e_BM_IM_COUNTERS_POOL_SW_DEPLETION, p_BmPool->bpid));
582         case(e_BM_POOL_COUNTERS_HW_DEPLETION):
583             return (p_BmPool->hwDepletionCount +=
584                 BmGetCounter(p_BmPool->h_Bm, e_BM_IM_COUNTERS_POOL_HW_DEPLETION, p_BmPool->bpid));
585         default:
586             break;
587     }
588 
589     /* should never get here */
590     ASSERT_COND(FALSE);
591 
592     return 0;
593 }
594