sonic-buildimage/platform/centec/centec-dal/dal_mpool.c
guxianghong be4cf09b5d
[Centec][arm64] support new board E530-48s4x and E530-24x2q (#7189)
1. support new board E530-48s4x E530-24x2q
2. optimize platform driver for Centec TsingMa board

Co-authored-by: shi lei <shil@centecnetworks.com>
2021-05-01 10:37:07 -07:00

350 lines
7.3 KiB
C

#ifdef CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-designator"
#endif
#include "dal_mpool.h"
#include "dal_common.h"
#include <linux/spinlock.h>
#include <linux/slab.h>
#define DAL_MALLOC(x) kmalloc(x, GFP_ATOMIC)
#define DAL_FREE(x) kfree(x)
static spinlock_t dal_mpool_lock[DAL_MAX_CHIP_NUM];
#define MPOOL_LOCK_INIT() spin_lock_init(&dal_mpool_lock[lchip])
#define MPOOL_LOCK_DEINIT()
#define MPOOL_LOCK() unsigned long flags; spin_lock_irqsave(&dal_mpool_lock[lchip], flags)
#define MPOOL_UNLOCK() spin_unlock_irqrestore(&dal_mpool_lock[lchip], flags)
#define DAL_PRINT(fmt,arg...) printk(fmt,##arg)
dal_mpool_mem_t* g_free_block_ptr = NULL;
/* System cache line size */
#ifndef DAL_CACHE_LINE_BYTES
#define DAL_CACHE_LINE_BYTES 256
#endif
static dal_mpool_mem_t* p_desc_pool[DAL_MAX_CHIP_NUM] = {0};
static dal_mpool_mem_t* p_data_pool[DAL_MAX_CHIP_NUM] = {0};
int
dal_mpool_init(uint8_t lchip)
{
MPOOL_LOCK_INIT();
return 0;
}
int
dal_mpool_deinit(uint8_t lchip)
{
MPOOL_LOCK_DEINIT();
return 0;
}
dal_mpool_mem_t*
_dal_mpool_create(void* base, int size, int type)
{
dal_mpool_mem_t* head = NULL;
dal_mpool_mem_t* tail = NULL;
head = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t));
if (head == NULL)
{
return NULL;
}
tail = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t));
if (tail == NULL)
{
DAL_FREE(head);
return NULL;
}
head->size = tail->size = 0;
head->type = type;
head->address = base;
tail->address = head->address + size;
head->next = tail;
tail->next = NULL;
return head;
}
dal_mpool_mem_t*
dal_mpool_create(unsigned char lchip, void* base, int size)
{
dal_mpool_mem_t* head = NULL;
int mod = (int)(((unsigned long)base) & (DAL_CACHE_LINE_BYTES - 1));
MPOOL_LOCK();
if (mod)
{
base = (char*)base + (DAL_CACHE_LINE_BYTES - mod);
size -= (DAL_CACHE_LINE_BYTES - mod);
}
size &= ~(DAL_CACHE_LINE_BYTES - 1);
/* init for common linkptr, only used for GB */
head = _dal_mpool_create(base, size, DAL_MPOOL_TYPE_USELESS);
if (NULL == head)
{
MPOOL_UNLOCK();
return NULL;
}
/* init for desc linkptr */
p_desc_pool[lchip] = _dal_mpool_create(base, DAL_MPOOL_MAX_DESX_SIZE, DAL_MPOOL_TYPE_DESC);
if (NULL == p_desc_pool[lchip])
{
MPOOL_UNLOCK();
DAL_FREE(head->next);
DAL_FREE(head);
return NULL;
}
/* init for data linkptr */
p_data_pool[lchip] = _dal_mpool_create(((char*)base+DAL_MPOOL_MAX_DESX_SIZE), (size - DAL_MPOOL_MAX_DESX_SIZE), DAL_MPOOL_TYPE_DATA);
if (NULL == p_data_pool[lchip])
{
MPOOL_UNLOCK();
DAL_FREE(head->next);
DAL_FREE(head);
DAL_FREE(p_desc_pool[lchip]->next);
DAL_FREE(p_desc_pool[lchip]);
return NULL;
}
MPOOL_UNLOCK();
return head;
}
dal_mpool_mem_t*
_dal_mpool_alloc_comon(dal_mpool_mem_t* ptr, int size, int type)
{
dal_mpool_mem_t* new_ptr = NULL;
while (ptr && ptr->next)
{
if (ptr->next->address - (ptr->address + ptr->size) >= size)
{
break;
}
ptr = ptr->next;
}
if (!(ptr && ptr->next))
{
return NULL;
}
new_ptr = DAL_MALLOC(sizeof(dal_mpool_mem_t));
if (!new_ptr)
{
return NULL;
}
new_ptr->type = type;
new_ptr->address = ptr->address + ptr->size;
new_ptr->size = size;
new_ptr->next = ptr->next;
ptr->next = new_ptr;
return new_ptr;
}
void*
dal_mpool_alloc(unsigned char lchip, dal_mpool_mem_t* pool, int size, int type)
{
dal_mpool_mem_t* ptr = NULL;
dal_mpool_mem_t* new_ptr = NULL;
int mod;
MPOOL_LOCK();
mod = size & (DAL_CACHE_LINE_BYTES - 1);
if (mod != 0)
{
size += (DAL_CACHE_LINE_BYTES - mod);
}
switch(type)
{
case DAL_MPOOL_TYPE_USELESS:
ptr = pool;
new_ptr = _dal_mpool_alloc_comon(ptr, size, type);
if (NULL == new_ptr)
{
MPOOL_UNLOCK();
return NULL;
}
break;
case DAL_MPOOL_TYPE_DESC:
ptr = p_desc_pool[lchip];
new_ptr = _dal_mpool_alloc_comon(ptr, size, type);
if (NULL == new_ptr)
{
MPOOL_UNLOCK();
return NULL;
}
break;
case DAL_MPOOL_TYPE_DATA:
ptr = p_data_pool[lchip];
new_ptr = _dal_mpool_alloc_comon(ptr, size, type);
if (NULL == new_ptr)
{
MPOOL_UNLOCK();
return NULL;
}
break;
default:
MPOOL_UNLOCK();
return NULL;
break;
}
MPOOL_UNLOCK();
if( NULL == new_ptr )
{
return NULL;
}
return new_ptr->address;
}
void
_dal_mpool_free(dal_mpool_mem_t* ptr, void* addr, int type)
{
unsigned char* address = (unsigned char*)addr;
dal_mpool_mem_t* prev = NULL;
while (ptr && ptr->next)
{
if (ptr->next->address == address)
{
break;
}
ptr = ptr->next;
}
if (ptr && ptr->next)
{
prev = ptr;
ptr = ptr->next;
prev->next = ptr->next;
DAL_FREE(ptr);
}
return;
}
void
dal_mpool_free(unsigned char lchip, dal_mpool_mem_t* pool, void* addr)
{
dal_mpool_mem_t* ptr = pool;
MPOOL_LOCK();
switch(pool->type)
{
case DAL_MPOOL_TYPE_USELESS:
ptr = pool;
_dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_USELESS);
break;
case DAL_MPOOL_TYPE_DESC:
ptr = p_desc_pool[lchip];
_dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DESC);
break;
case DAL_MPOOL_TYPE_DATA:
ptr = p_data_pool[lchip];
_dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DATA);
break;
default:
break;
}
MPOOL_UNLOCK();
return;
}
int
dal_mpool_destroy(unsigned char lchip, dal_mpool_mem_t* pool)
{
dal_mpool_mem_t* ptr, * next;
MPOOL_LOCK();
for (ptr = pool; ptr; ptr = next)
{
next = ptr->next;
DAL_FREE(ptr);
}
for (ptr = p_desc_pool[lchip]; ptr; ptr = next)
{
next = ptr->next;
DAL_FREE(ptr);
}
for (ptr = p_data_pool[lchip]; ptr; ptr = next)
{
next = ptr->next;
DAL_FREE(ptr);
}
MPOOL_UNLOCK();
return 0;
}
int
dal_mpool_usage(dal_mpool_mem_t* pool, int type)
{
int usage = 0;
dal_mpool_mem_t* ptr;
uint8_t lchip = 0;
MPOOL_LOCK();
for (ptr = pool; ptr; ptr = ptr->next)
{
if (ptr->type == type || ptr->type == -1)
{
usage += ptr->size;
}
}
MPOOL_UNLOCK();
return usage;
}
int
dal_mpool_debug(dal_mpool_mem_t* pool)
{
dal_mpool_mem_t* ptr;
int index = 0;
uint8_t lchip = 0;
MPOOL_LOCK();
for (ptr = pool; ptr; ptr = ptr->next)
{
/* DAL_PRINT("%2dst mpool block: address=0x%8x, size=0x%x \n", index, (unsigned int)ptr->address, ptr->size);*/
DAL_PRINT("%2dst mpool block: address=%p, size=0x%x \n", index, ptr->address, ptr->size); /* note*/
index++;
}
MPOOL_UNLOCK();
return 0;
}
#ifdef CLANG
#pragma clang diagnostic pop
#endif