1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 // Software and any modification/derivatives thereof.
18 // No right, ownership, or interest to MStar Software and any
19 // modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 // supplied together with third party`s software and the use of MStar
23 // Software may require additional licenses from third parties.
24 // Therefore, you hereby agree it is your sole responsibility to separately
25 // obtain any and all third party right and license necessary for your use of
26 // such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 // MStar`s confidential information and you agree to keep MStar`s
30 // confidential information in strictest confidence and not disclose to any
31 // third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 // kind. Any warranties are hereby expressly disclaimed by MStar, including
35 // without limitation, any warranties of merchantability, non-infringement of
36 // intellectual property rights, fitness for a particular purpose, error free
37 // and in conformity with any international standard. You agree to waive any
38 // claim against MStar for any loss, damage, cost or expense that you may
39 // incur related to your use of MStar Software.
40 // In no event shall MStar be liable for any direct, indirect, incidental or
41 // consequential damages, including without limitation, lost of profit or
42 // revenues, lost or damage of data, and unauthorized system use.
43 // You agree that this Section 4 shall still apply without being affected
44 // even if MStar Software has been modified by MStar in accordance with your
45 // request or instruction for your use, except otherwise agreed by both
46 // parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 // services in relation with MStar Software to you for your use of
50 // MStar Software in conjunction with your or your customer`s product
51 // ("Services").
52 // You understand and agree that, except otherwise agreed by both parties in
53 // writing, Services are provided on an "AS IS" basis and the warranty
54 // disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 // or otherwise:
58 // (a) conferring any license or right to use MStar name, trademark, service
59 // mark, symbol or any other identification;
60 // (b) obligating MStar or any of its affiliates to furnish any person,
61 // including without limitation, you and your customers, any assistance
62 // of any kind whatsoever, or any information; or
63 // (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 // of Taiwan, R.O.C., excluding its conflict of law rules.
67 // Any and all dispute arising out hereof or related hereto shall be finally
68 // settled by arbitration referred to the Chinese Arbitration Association,
69 // Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 // Rules of the Association by three (3) arbitrators appointed in accordance
71 // with the said Rules.
72 // The place of arbitration shall be in Taipei, Taiwan and the language shall
73 // be English.
74 // The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78
79 //#include <MsCommon.h> // NUSED
80 //#include "include/drvPCIMEM.h" // NUSED
81 #include "include/drvKernel.h"
82 #include "include/drvBitops.h"
83 #include "drvUsbHostConfig.h"
84
85 /**
86 * @brief Return a memory pool to be used to allocate memory by the requested characteristics.
87 *
88 * @param pName name of memory pool
89 *
90 * @param u32Size block size in the pool.
91 *
92 * @param u32AlignLen block alignment size.
93 *
94 * @param U32CrossLimit returned blocks can't cross the boundray.
95 *
96 * @return ms_mem_pool return memory pool with the requested characteristics.
97 */
ms_mem_pool_create(const char * pName,MS_U32 u32Size,MS_U32 u32AlignLen,MS_U32 U32CrossLimit)98 struct ms_mem_pool *ms_mem_pool_create (const char *pName, MS_U32 u32Size, MS_U32 u32AlignLen, MS_U32 U32CrossLimit)
99 {
100 struct ms_mem_pool *pPool;
101
102 if (u32AlignLen == 0)
103 u32AlignLen = 1;
104 if (u32Size == 0)
105 return 0;
106 else if (u32Size < u32AlignLen)
107 u32Size = u32AlignLen;
108 else if ((u32Size % u32AlignLen) != 0)
109 {
110 u32Size += u32AlignLen + 1;
111 u32Size &= ~(u32AlignLen - 1);
112 }
113
114 if (U32CrossLimit == 0)
115 {
116 if (PAGE_SIZE < u32Size)
117 U32CrossLimit = u32Size;
118 else
119 U32CrossLimit = PAGE_SIZE;
120 }
121 else if (U32CrossLimit < u32Size)
122 return 0;
123
124 if (!(pPool = (struct ms_mem_pool*) kmalloc (sizeof (*pPool), SLAB_KERNEL)))
125 return pPool;
126
127 strncpy (pPool->name, pName, sizeof (pPool->name)-1 );
128 pPool->name[sizeof(pPool->name)-1] = '\0';
129 ms_list_init (&pPool->page_list);
130 pPool->size = u32Size;
131 pPool->allocation = U32CrossLimit;
132 pPool->blocks_per_page = U32CrossLimit / u32Size;
133 ms_usbhost_debug("ms_mem_pool_create: size=%d,allocation=%d bytes, %d blocks per page",
134 pPool->size, pPool->allocation, pPool->blocks_per_page);
135 return pPool;
136 }
137
138 static struct ms_mem_page *
pool_alloc_page(struct ms_mem_pool * pMem_pool,int iFlags)139 pool_alloc_page (struct ms_mem_pool *pMem_pool, int iFlags)
140 {
141 struct ms_mem_page *pPage;
142 int mapsize;
143
144 mapsize = pMem_pool->blocks_per_page;
145 mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
146 mapsize *= sizeof (U32);
147
148 pPage = (struct ms_mem_page *) kmalloc (mapsize + sizeof(struct ms_mem_page), iFlags);
149 ms_list_init(&pPage->page_list);
150 if (!pPage)
151 return 0;
152
153 pPage->vaddr = ncmem_alloc_page(&pPage->dma);
154
155 if (pPage->vaddr)
156 {
157 memset (pPage->bitmap, ((U32)-1), mapsize); // bit set == free
158 ms_insert_list_after (&pPage->page_list, &pMem_pool->page_list);
159 }
160 else
161 {
162 kfree (pPage);
163 pPage = 0;
164 }
165 return pPage;
166 }
167
168 /**
169 * @brief Allocate a block of memory
170 *
171 * @param pMem_pool The pool to allocate memory.
172 *
173 * @param iFlags memory flag.
174 *
175 * @param pDma_addr pointer to physical address of block
176 *
177 * @return pointer to virtual address of block
178 */
ms_mem_pool_alloc(struct ms_mem_pool * pMem_pool,int iFlags,dma_addr_t * pDma_addr)179 void *ms_mem_pool_alloc (struct ms_mem_pool *pMem_pool, int iFlags, dma_addr_t *pDma_addr)
180 {
181 U32 u32flag;
182 struct list_head *entry;
183 struct ms_mem_page *ms_page;
184 int iMap, iBlock;
185 U32 u32Offset;
186 void *ms_retval;
187
188 osapi_spin_lock_irqsave (&pMem_pool->lock, u32flag);
189 list_for_loop (entry, &pMem_pool->page_list)
190 {
191 U32 i;
192
193 const struct list_head *__mptr = entry;
194 ms_page = (struct ms_mem_page *)( (char *)__mptr - (char *)offsetof(struct ms_mem_page,page_list));
195
196 /* only cachable accesses here ... */
197 for (iMap = 0, i = 0; i < pMem_pool->blocks_per_page; i += BITS_PER_LONG, iMap++)
198 {
199 if (ms_page->bitmap [iMap] == 0)
200 continue;
201 iBlock = ms_find_1st_zero (~ ms_page->bitmap [iMap]);
202 if ((i + iBlock) < pMem_pool->blocks_per_page)
203 {
204 ms_clear_bit ( iBlock, &ms_page->bitmap [iMap],U32);
205 u32Offset = (BITS_PER_LONG * iMap) + iBlock;
206 u32Offset *= pMem_pool->size;
207 goto ready;
208 }
209 }
210 }
211
212 if (!(ms_page = pool_alloc_page (pMem_pool, iFlags)))
213 {
214 diag_printf("pool allocate page fail\n");
215 ms_retval = 0;
216 goto done;
217 }
218
219 ms_clear_bit (0, &ms_page->bitmap [0],U32);
220 u32Offset = 0;
221 ready:
222 ms_retval = (void*) (u32Offset + (size_t) ( ms_page->vaddr ));
223 *pDma_addr = u32Offset + ms_page->dma;
224 done:
225 osapi_spin_unlock_irqrestore (&pMem_pool->lock, u32flag);
226 //ms_usbhost_debug("The allocated addr is %p, block size is %d ,bit_map[%d] is 0x%08X",
227 // ms_retval, pMem_pool->size ,iMap,(U32)ms_page->bitmap [iMap]);
228 return ms_retval;
229 }
230
__is_page_busy(int ms_blocks,U32 * ms_bitmap)231 static __inline__ int __is_page_busy (int ms_blocks, U32 *ms_bitmap)
232 {
233 while (ms_blocks > 0)
234 {
235 if (*ms_bitmap++ != ~0UL)
236 return 1;
237 ms_blocks -= BITS_PER_LONG;
238 }
239 return 0;
240 }
241
242 /**
243 * @brief Destory memory pool
244 *
245 * @param pMem_pool The pool to be destoryed.
246 *
247 * @return None
248 */
ms_mem_pool_destroy(struct ms_mem_pool * pMem_pool)249 void ms_mem_pool_destroy (struct ms_mem_pool *pMem_pool)
250 {
251 U32 u32flag;
252
253 osapi_spin_lock_irqsave (&pMem_pool->lock, u32flag);
254 while (!ms_is_empty_list (&pMem_pool->page_list))
255 {
256 struct ms_mem_page *ms_page;
257
258 const struct list_head *__mptr = pMem_pool->page_list.next;
259 ms_page = (struct ms_mem_page *)( (char *)__mptr - (char *)offsetof(struct ms_mem_page,page_list) );
260
261 if (__is_page_busy (pMem_pool->blocks_per_page, ms_page->bitmap))
262 {
263 diag_printf ("ms_mem_pool_destroy %s, %p busy\n",
264 pMem_pool->name, ms_page->vaddr);
265 /* leak the still-in-use consistent memory */
266 ms_list_remove (&ms_page->page_list);
267 kfree (ms_page);
268 }
269 else
270 {
271 ncmem_free_page((U32)ms_page->vaddr);
272 ms_list_remove (&ms_page->page_list);
273 kfree (ms_page);
274 }
275
276 }
277 osapi_spin_unlock_irqrestore (&pMem_pool->lock, u32flag);
278 kfree (pMem_pool);
279 }
280
281 /**
282 * @brief Free memory block and put back into pool
283 *
284 * @param pMem_pool The pool contains the block.
285 *
286 * @param pVirt_addr Virtual address of the blcok.
287 *
288 * @param dma_addr Physical address of the block.
289 *
290 * @return BOOL success or not
291 */
ms_mem_pool_free(struct ms_mem_pool * pMem_pool,void * pVirt_addr,dma_addr_t dma_addr)292 MS_BOOL ms_mem_pool_free (struct ms_mem_pool *pMem_pool, void *pVirt_addr, dma_addr_t dma_addr)
293 {
294 struct ms_mem_page *ms_page;
295 struct list_head *pEntry;
296 U32 u32flag;
297 int iMap, iBlock;
298
299 // find page in memory pool
300 osapi_spin_lock_irqsave (&pMem_pool->lock, u32flag);
301 list_for_loop (pEntry, &pMem_pool->page_list)
302 {
303 //page = list_entry (entry, struct ms_mem_page, page_list);
304 const struct list_head *__mptr = pEntry;
305 ms_page = (struct ms_mem_page *)( (char *)__mptr - (char *)offsetof(struct ms_mem_page,page_list) );
306
307 if (dma_addr < ms_page->dma)
308 continue;
309 if (dma_addr < (ms_page->dma + pMem_pool->allocation))
310 goto page_found;
311 }
312
313 //Not found !!
314 osapi_spin_unlock_irqrestore (&pMem_pool->lock, u32flag);
315 ms_usbhost_debug ("ms_mem_pool_free %s, %p/%lx (bad dma)\n", pMem_pool->name, pVirt_addr, (U32) dma_addr);
316 return FALSE;
317
318
319 page_found:
320 osapi_spin_unlock_irqrestore (&pMem_pool->lock, u32flag);
321
322 iBlock = dma_addr - ms_page->dma;
323 iBlock /= pMem_pool->size;
324 iMap = iBlock / BITS_PER_LONG;
325 iBlock %= BITS_PER_LONG;
326
327 osapi_spin_lock_irqsave (&pMem_pool->lock, u32flag);
328 ms_set_bit (iBlock, &ms_page->bitmap [iMap], U32);
329 ms_usbhost_debug("Free Block: addr=0x%08X bitmap is 0x%08X",dma_addr,(U32)ms_page->bitmap [iMap]);
330
331 //// if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page);
332 //// it is not interrupt safe. Better have empty pages hang around.
333
334 osapi_spin_unlock_irqrestore (&pMem_pool->lock, u32flag);
335 return TRUE;
336 }
337
338