mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-13 08:07:32 -04:00
qcacld-3.0: optimize data path memory allocation
When allocate HTT descriptor, instead of allocating large single chunk of memory, allocate small sized multiple chunk of memory. Then not need to allocate order 5 memory. Will have less chance to have memory alloc fail problem. HTT descriptor. Frag descriptor. OL descriptor. TSO descriptor Change-Id: Ib9d4a3f10adbc0656e1418cf3a67429322bb7164 CRs-fixed: 845666
This commit is contained in:
parent
19a7dd28f5
commit
f24b357bf8
15 changed files with 726 additions and 326 deletions
|
|
@ -37,6 +37,32 @@
|
|||
/* Include Files */
|
||||
#include <cdf_types.h>
|
||||
|
||||
/**
|
||||
* struct cdf_mem_dma_page_t - Allocated dmaable page
|
||||
* @page_v_addr_start: Page start virtual address
|
||||
* @page_v_addr_end: Page end virtual address
|
||||
* @page_p_addr: Page start physical address
|
||||
*/
|
||||
struct cdf_mem_dma_page_t {
|
||||
char *page_v_addr_start;
|
||||
char *page_v_addr_end;
|
||||
cdf_dma_addr_t page_p_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cdf_mem_multi_page_t - multiple page allocation information storage
|
||||
* @num_element_per_page: Number of element in single page
|
||||
* @num_pages: Number of allocation needed pages
|
||||
* @dma_pages: page information storage in case of coherent memory
|
||||
* @cacheable_pages: page information storage in case of cacheable memory
|
||||
*/
|
||||
struct cdf_mem_multi_page_t {
|
||||
uint16_t num_element_per_page;
|
||||
uint16_t num_pages;
|
||||
struct cdf_mem_dma_page_t *dma_pages;
|
||||
void **cacheable_pages;
|
||||
};
|
||||
|
||||
/* Preprocessor definitions and constants */
|
||||
|
||||
#ifdef MEMORY_DEBUG
|
||||
|
|
@ -222,4 +248,15 @@ static inline int32_t cdf_str_len(const char *str)
|
|||
return strlen(str);
|
||||
}
|
||||
|
||||
void cdf_mem_multi_pages_alloc(cdf_device_t osdev,
|
||||
struct cdf_mem_multi_page_t *pages,
|
||||
size_t element_size,
|
||||
uint16_t element_num,
|
||||
cdf_dma_context_t memctxt,
|
||||
bool cacheable);
|
||||
|
||||
void cdf_mem_multi_pages_free(cdf_device_t osdev,
|
||||
struct cdf_mem_multi_page_t *pages,
|
||||
cdf_dma_context_t memctxt,
|
||||
bool cacheable);
|
||||
#endif /* __CDF_MEMORY_H */
|
||||
|
|
|
|||
|
|
@ -106,6 +106,14 @@ CDF_INLINE_FN int cdf_status_to_os_return(CDF_STATUS status)
|
|||
#define cdf_container_of(ptr, type, member) \
|
||||
__cdf_container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* cdf_is_pwr2 - test input value is power of 2 integer
|
||||
*
|
||||
* @value: input integer
|
||||
*
|
||||
*/
|
||||
#define CDF_IS_PWR2(value) (((value) ^ ((value)-1)) == ((value) << 1) - 1)
|
||||
|
||||
/**
|
||||
* cdf_is_macaddr_equal() - compare two CDF MacAddress
|
||||
* @pMacAddr1: Pointer to one cdf MacAddress to compare
|
||||
|
|
@ -322,4 +330,26 @@ CDF_INLINE_FN uint8_t *cdf_get_u32(uint8_t *ptr, uint32_t *pValue)
|
|||
return ptr + 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdf_get_pwr2() - get next power of 2 integer from input value
|
||||
* @value: input value to find next power of 2 integer
|
||||
*
|
||||
* Get next power of 2 integer from input value
|
||||
*
|
||||
* Return: Power of 2 integer
|
||||
*/
|
||||
CDF_INLINE_FN int cdf_get_pwr2(int value)
|
||||
{
|
||||
int log2;
|
||||
if (CDF_IS_PWR2(value))
|
||||
return value;
|
||||
|
||||
log2 = 0;
|
||||
while (value) {
|
||||
value >>= 1;
|
||||
log2++;
|
||||
}
|
||||
return 1 << log2;
|
||||
}
|
||||
|
||||
#endif /*_CDF_UTIL_H*/
|
||||
|
|
|
|||
|
|
@ -374,6 +374,154 @@ void cdf_mem_free(void *ptr)
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cdf_mem_multi_pages_alloc() - allocate large size of kernel memory
|
||||
* @osdev: OS device handle pointer
|
||||
* @pages: Multi page information storage
|
||||
* @element_size: Each element size
|
||||
* @element_num: Total number of elements should be allocated
|
||||
* @memctxt: Memory context
|
||||
* @cacheable: Coherent memory or cacheable memory
|
||||
*
|
||||
* This function will allocate large size of memory over multiple pages.
|
||||
* Large size of contiguous memory allocation will fail frequentely, then
|
||||
* instead of allocate large memory by one shot, allocate through multiple, non
|
||||
* contiguous memory and combine pages when actual usage
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void cdf_mem_multi_pages_alloc(cdf_device_t osdev,
|
||||
struct cdf_mem_multi_page_t *pages,
|
||||
size_t element_size,
|
||||
uint16_t element_num,
|
||||
cdf_dma_context_t memctxt,
|
||||
bool cacheable)
|
||||
{
|
||||
uint16_t page_idx;
|
||||
struct cdf_mem_dma_page_t *dma_pages;
|
||||
void **cacheable_pages = NULL;
|
||||
uint16_t i;
|
||||
|
||||
pages->num_element_per_page = PAGE_SIZE / element_size;
|
||||
if (!pages->num_element_per_page) {
|
||||
cdf_print("Invalid page %d or element size %d",
|
||||
(int)PAGE_SIZE, (int)element_size);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
pages->num_pages = element_num / pages->num_element_per_page;
|
||||
if (element_num % pages->num_element_per_page)
|
||||
pages->num_pages++;
|
||||
|
||||
if (cacheable) {
|
||||
/* Pages information storage */
|
||||
pages->cacheable_pages = cdf_mem_malloc(
|
||||
pages->num_pages * sizeof(pages->cacheable_pages));
|
||||
if (!pages->cacheable_pages) {
|
||||
cdf_print("Cacheable page storage alloc fail");
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
cacheable_pages = pages->cacheable_pages;
|
||||
for (page_idx = 0; page_idx < pages->num_pages; page_idx++) {
|
||||
cacheable_pages[page_idx] = cdf_mem_malloc(PAGE_SIZE);
|
||||
if (!cacheable_pages[page_idx]) {
|
||||
cdf_print("cacheable page alloc fail, pi %d",
|
||||
page_idx);
|
||||
goto page_alloc_fail;
|
||||
}
|
||||
}
|
||||
pages->dma_pages = NULL;
|
||||
} else {
|
||||
pages->dma_pages = cdf_mem_malloc(
|
||||
pages->num_pages * sizeof(struct cdf_mem_dma_page_t));
|
||||
if (!pages->dma_pages) {
|
||||
cdf_print("dmaable page storage alloc fail");
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
dma_pages = pages->dma_pages;
|
||||
for (page_idx = 0; page_idx < pages->num_pages; page_idx++) {
|
||||
dma_pages->page_v_addr_start =
|
||||
cdf_os_mem_alloc_consistent(osdev, PAGE_SIZE,
|
||||
&dma_pages->page_p_addr, memctxt);
|
||||
if (!dma_pages->page_v_addr_start) {
|
||||
cdf_print("dmaable page alloc fail pi %d",
|
||||
page_idx);
|
||||
goto page_alloc_fail;
|
||||
}
|
||||
dma_pages->page_v_addr_end =
|
||||
dma_pages->page_v_addr_start + PAGE_SIZE;
|
||||
dma_pages++;
|
||||
}
|
||||
pages->cacheable_pages = NULL;
|
||||
}
|
||||
return;
|
||||
|
||||
page_alloc_fail:
|
||||
if (cacheable) {
|
||||
for (i = 0; i < page_idx; i++)
|
||||
cdf_mem_free(pages->cacheable_pages[i]);
|
||||
cdf_mem_free(pages->cacheable_pages);
|
||||
} else {
|
||||
dma_pages = pages->dma_pages;
|
||||
for (i = 0; i < page_idx; i++) {
|
||||
cdf_os_mem_free_consistent(osdev, PAGE_SIZE,
|
||||
dma_pages->page_v_addr_start,
|
||||
dma_pages->page_p_addr, memctxt);
|
||||
dma_pages++;
|
||||
}
|
||||
cdf_mem_free(pages->dma_pages);
|
||||
}
|
||||
|
||||
out_fail:
|
||||
pages->cacheable_pages = NULL;
|
||||
pages->dma_pages = NULL;
|
||||
pages->num_pages = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* cdf_mem_multi_pages_free() - free large size of kernel memory
|
||||
* @osdev: OS device handle pointer
|
||||
* @pages: Multi page information storage
|
||||
* @memctxt: Memory context
|
||||
* @cacheable: Coherent memory or cacheable memory
|
||||
*
|
||||
* This function will free large size of memory over multiple pages.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void cdf_mem_multi_pages_free(cdf_device_t osdev,
|
||||
struct cdf_mem_multi_page_t *pages,
|
||||
cdf_dma_context_t memctxt,
|
||||
bool cacheable)
|
||||
{
|
||||
unsigned int page_idx;
|
||||
struct cdf_mem_dma_page_t *dma_pages;
|
||||
|
||||
if (cacheable) {
|
||||
for (page_idx = 0; page_idx < pages->num_pages; page_idx++)
|
||||
cdf_mem_free(pages->cacheable_pages[page_idx]);
|
||||
cdf_mem_free(pages->cacheable_pages);
|
||||
} else {
|
||||
dma_pages = pages->dma_pages;
|
||||
for (page_idx = 0; page_idx < pages->num_pages; page_idx++) {
|
||||
cdf_os_mem_free_consistent(osdev, PAGE_SIZE,
|
||||
dma_pages->page_v_addr_start,
|
||||
dma_pages->page_p_addr, memctxt);
|
||||
dma_pages++;
|
||||
}
|
||||
cdf_mem_free(pages->dma_pages);
|
||||
}
|
||||
|
||||
pages->cacheable_pages = NULL;
|
||||
pages->dma_pages = NULL;
|
||||
pages->num_pages = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* cdf_mem_set() - set (fill) memory with a specified byte value.
|
||||
* @pMemory: Pointer to memory that will be set
|
||||
|
|
@ -629,3 +777,4 @@ cdf_os_mem_dma_sync_single_for_device(cdf_device_t osdev,
|
|||
{
|
||||
dma_sync_single_for_device(osdev->dev, bus_addr, size, direction);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,10 +154,12 @@ A_STATUS htt_h2t_frag_desc_bank_cfg_msg(struct htt_pdev_t *pdev)
|
|||
|
||||
/** Bank specific data structure.*/
|
||||
#if HTT_PADDR64
|
||||
bank_cfg->bank_base_address[0].lo = pdev->frag_descs.pool_paddr;
|
||||
bank_cfg->bank_base_address[0].lo =
|
||||
pdev->frag_descs.desc_pages.dma_pages->page_p_addr;
|
||||
bank_cfg->bank_base_address[0].hi = 0;
|
||||
#else /* ! HTT_PADDR64 */
|
||||
bank_cfg->bank_base_address[0] = pdev->frag_descs.pool_paddr;
|
||||
bank_cfg->bank_base_address[0] =
|
||||
pdev->frag_descs.desc_pages.dma_pages->page_p_addr;
|
||||
#endif /* HTT_PADDR64 */
|
||||
/* Logical Min index */
|
||||
HTT_H2T_FRAG_DESC_BANK_MIN_IDX_SET(bank_cfg->bank_info[0], 0);
|
||||
|
|
|
|||
|
|
@ -149,20 +149,6 @@ void htt_rx_hash_deinit(struct htt_pdev_t *pdev)
|
|||
pdev->rx_ring.hash_table = NULL;
|
||||
}
|
||||
|
||||
static int ceil_pwr2(int value)
|
||||
{
|
||||
int log2;
|
||||
if (IS_PWR2(value))
|
||||
return value;
|
||||
|
||||
log2 = 0;
|
||||
while (value) {
|
||||
value >>= 1;
|
||||
log2++;
|
||||
}
|
||||
return 1 << log2;
|
||||
}
|
||||
|
||||
static bool
|
||||
htt_rx_msdu_first_msdu_flag_ll(htt_pdev_handle pdev, void *msdu_desc)
|
||||
{
|
||||
|
|
@ -206,7 +192,7 @@ static int htt_rx_ring_size(struct htt_pdev_t *pdev)
|
|||
else if (size > HTT_RX_RING_SIZE_MAX)
|
||||
size = HTT_RX_RING_SIZE_MAX;
|
||||
|
||||
size = ceil_pwr2(size);
|
||||
size = cdf_get_pwr2(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
@ -2064,7 +2050,7 @@ int htt_rx_hash_init(struct htt_pdev_t *pdev)
|
|||
{
|
||||
int i, j;
|
||||
|
||||
HTT_ASSERT2(IS_PWR2(RX_NUM_HASH_BUCKETS));
|
||||
HTT_ASSERT2(CDF_IS_PWR2(RX_NUM_HASH_BUCKETS));
|
||||
|
||||
pdev->rx_ring.hash_table =
|
||||
cdf_mem_malloc(RX_NUM_HASH_BUCKETS *
|
||||
|
|
@ -2150,7 +2136,7 @@ int htt_rx_attach(struct htt_pdev_t *pdev)
|
|||
uint32_t ring_elem_size = sizeof(uint32_t);
|
||||
#endif /* HTT_PADDR64 */
|
||||
pdev->rx_ring.size = htt_rx_ring_size(pdev);
|
||||
HTT_ASSERT2(IS_PWR2(pdev->rx_ring.size));
|
||||
HTT_ASSERT2(CDF_IS_PWR2(pdev->rx_ring.size));
|
||||
pdev->rx_ring.size_mask = pdev->rx_ring.size - 1;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include <ol_cfg.h> /* ol_cfg_netbuf_frags_max, etc. */
|
||||
#include <ol_htt_tx_api.h> /* HTT_TX_DESC_VADDR_OFFSET */
|
||||
#include <ol_txrx_htt_api.h> /* ol_tx_msdu_id_storage */
|
||||
#include <ol_txrx_internal.h>
|
||||
#include <htt_internal.h>
|
||||
|
||||
/* IPA Micro controler TX data packet HTT Header Preset */
|
||||
|
|
@ -65,25 +66,42 @@
|
|||
*/
|
||||
#define HTT_IPA_UC_OFFLOAD_TX_HEADER_DEFAULT 0x07C04001
|
||||
|
||||
#if HTT_PADDR64
|
||||
#define HTT_TX_DESC_FRAG_FIELD_HI_UPDATE(frag_filed_ptr) \
|
||||
do { \
|
||||
frag_filed_ptr++; \
|
||||
/* frags_desc_ptr.hi */ \
|
||||
*frag_filed_ptr = 0; \
|
||||
} while (0)
|
||||
#else
|
||||
#define HTT_TX_DESC_FRAG_FIELD_HI_UPDATE(frag_filed_ptr) {}
|
||||
#endif
|
||||
|
||||
/*--- setup / tear-down functions -------------------------------------------*/
|
||||
|
||||
#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS
|
||||
uint32_t *g_dbg_htt_desc_end_addr, *g_dbg_htt_desc_start_addr;
|
||||
#endif
|
||||
|
||||
int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems)
|
||||
static cdf_dma_addr_t htt_tx_get_paddr(htt_pdev_handle pdev,
|
||||
char *target_vaddr);
|
||||
|
||||
#ifdef HELIUMPLUS
|
||||
/**
|
||||
* htt_tx_desc_get_size() - get tx descripotrs size
|
||||
* @pdev: htt device instance pointer
|
||||
*
|
||||
* This function will get HTT TX descriptor size and fragment descriptor size
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void htt_tx_desc_get_size(struct htt_pdev_t *pdev)
|
||||
{
|
||||
int i, pool_size;
|
||||
uint32_t **p;
|
||||
cdf_dma_addr_t pool_paddr;
|
||||
|
||||
#if defined(HELIUMPLUS_PADDR64)
|
||||
pdev->tx_descs.size = sizeof(struct htt_host_tx_desc_t);
|
||||
|
||||
if (HTT_WIFI_IP_VERSION(pdev->wifi_ip_ver.major, 0x2)) {
|
||||
/*
|
||||
* sizeof MSDU_EXT/Fragmentation descriptor.
|
||||
*/
|
||||
* sizeof MSDU_EXT/Fragmentation descriptor.
|
||||
*/
|
||||
pdev->frag_descs.size = sizeof(struct msdu_ext_desc_t);
|
||||
} else {
|
||||
/*
|
||||
|
|
@ -96,7 +114,130 @@ int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems)
|
|||
(ol_cfg_netbuf_frags_max(pdev->ctrl_pdev)+1) * 8
|
||||
+ 4;
|
||||
}
|
||||
#else /* ! defined(HELIUMPLUS_PADDR64) */
|
||||
}
|
||||
|
||||
/**
|
||||
* htt_tx_frag_desc_field_update() - Update fragment descriptor field
|
||||
* @pdev: htt device instance pointer
|
||||
* @fptr: Fragment descriptor field pointer
|
||||
* @index: Descriptor index to find page and offset
|
||||
* @desc_v_ptr: descriptor virtual pointot to find offset
|
||||
*
|
||||
* This function will update fragment descriptor field with actual fragment
|
||||
* descriptor stating physical pointer
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void htt_tx_frag_desc_field_update(struct htt_pdev_t *pdev,
|
||||
uint32_t *fptr, unsigned int index,
|
||||
struct htt_tx_msdu_desc_t *desc_v_ptr)
|
||||
{
|
||||
unsigned int target_page;
|
||||
unsigned int offset;
|
||||
struct cdf_mem_dma_page_t *dma_page;
|
||||
|
||||
target_page = index / pdev->frag_descs.desc_pages.num_element_per_page;
|
||||
offset = index % pdev->frag_descs.desc_pages.num_element_per_page;
|
||||
dma_page = &pdev->frag_descs.desc_pages.dma_pages[target_page];
|
||||
*fptr = (uint32_t)(dma_page->page_p_addr +
|
||||
offset * pdev->frag_descs.size);
|
||||
HTT_TX_DESC_FRAG_FIELD_HI_UPDATE(fptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* htt_tx_frag_desc_attach() - Attach fragment descriptor
|
||||
* @pdev: htt device instance pointer
|
||||
* @desc_pool_elems: Number of fragment descriptor
|
||||
*
|
||||
* This function will allocate fragment descriptor
|
||||
*
|
||||
* Return: 0 success
|
||||
*/
|
||||
static int htt_tx_frag_desc_attach(struct htt_pdev_t *pdev,
|
||||
uint16_t desc_pool_elems)
|
||||
{
|
||||
pdev->frag_descs.pool_elems = desc_pool_elems;
|
||||
cdf_mem_multi_pages_alloc(pdev->osdev, &pdev->frag_descs.desc_pages,
|
||||
pdev->frag_descs.size, desc_pool_elems,
|
||||
cdf_get_dma_mem_context((&pdev->frag_descs), memctx), false);
|
||||
if ((0 == pdev->frag_descs.desc_pages.num_pages) ||
|
||||
(NULL == pdev->frag_descs.desc_pages.dma_pages)) {
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
|
||||
"FRAG descriptor alloc fail");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* htt_tx_frag_desc_detach() - Detach fragment descriptor
|
||||
* @pdev: htt device instance pointer
|
||||
*
|
||||
* This function will free fragment descriptor
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void htt_tx_frag_desc_detach(struct htt_pdev_t *pdev)
|
||||
{
|
||||
cdf_mem_multi_pages_free(pdev->osdev, &pdev->frag_descs.desc_pages,
|
||||
cdf_get_dma_mem_context((&pdev->frag_descs), memctx), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* htt_tx_frag_alloc() - Allocate single fragment descriptor from the pool
|
||||
* @pdev: htt device instance pointer
|
||||
* @index: Descriptor index
|
||||
* @frag_paddr_lo: Fragment descriptor physical address
|
||||
* @frag_ptr: Fragment descriptor virtual address
|
||||
*
|
||||
* This function will free fragment descriptor
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
int htt_tx_frag_alloc(htt_pdev_handle pdev,
|
||||
u_int16_t index, u_int32_t *frag_paddr_lo, void **frag_ptr)
|
||||
{
|
||||
uint16_t frag_page_index;
|
||||
uint16_t frag_elem_index;
|
||||
struct cdf_mem_dma_page_t *dma_page;
|
||||
|
||||
/** Index should never be 0, since its used by the hardware
|
||||
to terminate the link. */
|
||||
if (index >= pdev->tx_descs.pool_elems) {
|
||||
*frag_ptr = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
frag_page_index = index /
|
||||
pdev->frag_descs.desc_pages.num_element_per_page;
|
||||
frag_elem_index = index %
|
||||
pdev->frag_descs.desc_pages.num_element_per_page;
|
||||
dma_page = &pdev->frag_descs.desc_pages.dma_pages[frag_page_index];
|
||||
|
||||
*frag_ptr = dma_page->page_v_addr_start +
|
||||
frag_elem_index * pdev->frag_descs.size;
|
||||
if (((char *)(*frag_ptr) < dma_page->page_v_addr_start) ||
|
||||
((char *)(*frag_ptr) > dma_page->page_v_addr_end)) {
|
||||
*frag_ptr = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
*frag_paddr_lo = dma_page->page_p_addr +
|
||||
frag_elem_index * pdev->frag_descs.size;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* htt_tx_desc_get_size() - get tx descripotrs size
|
||||
* @pdev: htt device instance pointer
|
||||
*
|
||||
* This function will get HTT TX descriptor size and fragment descriptor size
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static inline void htt_tx_desc_get_size(struct htt_pdev_t *pdev)
|
||||
{
|
||||
/*
|
||||
* Start with the size of the base struct
|
||||
* that actually gets downloaded.
|
||||
|
|
@ -111,10 +252,74 @@ int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems)
|
|||
+ (ol_cfg_netbuf_frags_max(pdev->ctrl_pdev) + 1) * 8
|
||||
/* 2x uint32_t */
|
||||
+ 4; /* uint32_t fragmentation list terminator */
|
||||
|
||||
if (pdev->tx_descs.size < sizeof(uint32_t *))
|
||||
pdev->tx_descs.size = sizeof(uint32_t *);
|
||||
#endif /* defined(HELIUMPLUS_PADDR64) */
|
||||
}
|
||||
|
||||
/**
|
||||
* htt_tx_frag_desc_field_update() - Update fragment descriptor field
|
||||
* @pdev: htt device instance pointer
|
||||
* @fptr: Fragment descriptor field pointer
|
||||
* @index: Descriptor index to find page and offset
|
||||
* @desc_v_ptr: descriptor virtual pointot to find offset
|
||||
*
|
||||
* This function will update fragment descriptor field with actual fragment
|
||||
* descriptor stating physical pointer
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void htt_tx_frag_desc_field_update(struct htt_pdev_t *pdev,
|
||||
uint32_t *fptr, unsigned int index,
|
||||
struct htt_tx_msdu_desc_t *desc_v_ptr)
|
||||
{
|
||||
*fptr = (uint32_t)htt_tx_get_paddr(pdev, (char *)desc_v_ptr) +
|
||||
HTT_TX_DESC_LEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* htt_tx_frag_desc_attach() - Attach fragment descriptor
|
||||
* @pdev: htt device instance pointer
|
||||
* @desc_pool_elems: Number of fragment descriptor
|
||||
*
|
||||
* This function will allocate fragment descriptor
|
||||
*
|
||||
* Return: 0 success
|
||||
*/
|
||||
static inline int htt_tx_frag_desc_attach(struct htt_pdev_t *pdev,
|
||||
int desc_pool_elems)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* htt_tx_frag_desc_detach() - Detach fragment descriptor
|
||||
* @pdev: htt device instance pointer
|
||||
*
|
||||
* This function will free fragment descriptor
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void htt_tx_frag_desc_detach(struct htt_pdev_t *pdev) {}
|
||||
#endif /* HELIUMPLUS */
|
||||
|
||||
/**
|
||||
* htt_tx_attach() - Attach HTT device instance
|
||||
* @pdev: htt device instance pointer
|
||||
* @desc_pool_elems: Number of TX descriptors
|
||||
*
|
||||
* This function will allocate HTT TX resources
|
||||
*
|
||||
* Return: 0 Success
|
||||
*/
|
||||
int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems)
|
||||
{
|
||||
int i, i_int, pool_size;
|
||||
uint32_t **p;
|
||||
struct cdf_mem_dma_page_t *page_info;
|
||||
uint32_t num_link = 0;
|
||||
uint16_t num_page, num_desc_per_page;
|
||||
|
||||
htt_tx_desc_get_size(pdev);
|
||||
/*
|
||||
* Make sure tx_descs.size is a multiple of 4-bytes.
|
||||
* It should be, but round up just to be sure.
|
||||
|
|
@ -123,94 +328,120 @@ int htt_tx_attach(struct htt_pdev_t *pdev, int desc_pool_elems)
|
|||
|
||||
pdev->tx_descs.pool_elems = desc_pool_elems;
|
||||
pdev->tx_descs.alloc_cnt = 0;
|
||||
|
||||
pool_size = pdev->tx_descs.pool_elems * pdev->tx_descs.size;
|
||||
|
||||
pdev->tx_descs.pool_vaddr =
|
||||
cdf_os_mem_alloc_consistent(
|
||||
pdev->osdev, pool_size,
|
||||
&pool_paddr,
|
||||
cdf_get_dma_mem_context((&pdev->tx_descs), memctx));
|
||||
|
||||
pdev->tx_descs.pool_paddr = pool_paddr;
|
||||
|
||||
if (!pdev->tx_descs.pool_vaddr)
|
||||
return -ENOBUFS; /* failure */
|
||||
|
||||
cdf_print("%s:htt_desc_start:0x%p htt_desc_end:0x%p\n", __func__,
|
||||
pdev->tx_descs.pool_vaddr,
|
||||
(uint32_t *) (pdev->tx_descs.pool_vaddr + pool_size));
|
||||
|
||||
#if defined(HELIUMPLUS_PADDR64)
|
||||
pdev->frag_descs.pool_elems = desc_pool_elems;
|
||||
/*
|
||||
* Allocate space for MSDU extension descriptor
|
||||
* H/W expects this in contiguous memory
|
||||
*/
|
||||
pool_size = pdev->frag_descs.pool_elems * pdev->frag_descs.size;
|
||||
|
||||
pdev->frag_descs.pool_vaddr = cdf_os_mem_alloc_consistent(
|
||||
pdev->osdev, pool_size, &pool_paddr,
|
||||
cdf_get_dma_mem_context((&pdev->frag_descs), memctx));
|
||||
|
||||
if (!pdev->frag_descs.pool_vaddr)
|
||||
return -ENOBUFS; /* failure */
|
||||
|
||||
pdev->frag_descs.pool_paddr = pool_paddr;
|
||||
|
||||
cdf_print("%s:MSDU Ext.Table Start:0x%p MSDU Ext.Table End:0x%p\n",
|
||||
__func__, pdev->frag_descs.pool_vaddr,
|
||||
(u_int32_t *) (pdev->frag_descs.pool_vaddr + pool_size));
|
||||
#endif /* defined(HELIUMPLUS_PADDR64) */
|
||||
|
||||
#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS
|
||||
g_dbg_htt_desc_end_addr = (uint32_t *)
|
||||
(pdev->tx_descs.pool_vaddr + pool_size);
|
||||
g_dbg_htt_desc_start_addr = (uint32_t *) pdev->tx_descs.pool_vaddr;
|
||||
#endif
|
||||
cdf_mem_multi_pages_alloc(pdev->osdev, &pdev->tx_descs.desc_pages,
|
||||
pdev->tx_descs.size, pdev->tx_descs.pool_elems,
|
||||
cdf_get_dma_mem_context((&pdev->tx_descs), memctx), false);
|
||||
if ((0 == pdev->tx_descs.desc_pages.num_pages) ||
|
||||
(NULL == pdev->tx_descs.desc_pages.dma_pages)) {
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
|
||||
"HTT desc alloc fail");
|
||||
goto out_fail;
|
||||
}
|
||||
num_page = pdev->tx_descs.desc_pages.num_pages;
|
||||
num_desc_per_page = pdev->tx_descs.desc_pages.num_element_per_page;
|
||||
|
||||
/* link tx descriptors into a freelist */
|
||||
pdev->tx_descs.freelist = (uint32_t *) pdev->tx_descs.pool_vaddr;
|
||||
page_info = pdev->tx_descs.desc_pages.dma_pages;
|
||||
pdev->tx_descs.freelist = (uint32_t *)page_info->page_v_addr_start;
|
||||
p = (uint32_t **) pdev->tx_descs.freelist;
|
||||
for (i = 0; i < desc_pool_elems - 1; i++) {
|
||||
*p = (uint32_t *) (((char *)p) + pdev->tx_descs.size);
|
||||
p = (uint32_t **) *p;
|
||||
for (i = 0; i < num_page; i++) {
|
||||
for (i_int = 0; i_int < num_desc_per_page; i_int++) {
|
||||
if (i_int == (num_desc_per_page - 1)) {
|
||||
/*
|
||||
* Last element on this page,
|
||||
* should pint next page */
|
||||
if (!page_info->page_v_addr_start) {
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
|
||||
"over flow num link %d\n",
|
||||
num_link);
|
||||
goto free_htt_desc;
|
||||
}
|
||||
page_info++;
|
||||
*p = (uint32_t *)page_info->page_v_addr_start;
|
||||
} else {
|
||||
*p = (uint32_t *)
|
||||
(((char *) p) + pdev->tx_descs.size);
|
||||
}
|
||||
num_link++;
|
||||
p = (uint32_t **) *p;
|
||||
/* Last link established exit */
|
||||
if (num_link == (pdev->tx_descs.pool_elems - 1))
|
||||
break;
|
||||
}
|
||||
}
|
||||
*p = NULL;
|
||||
|
||||
return 0; /* success */
|
||||
if (htt_tx_frag_desc_attach(pdev, desc_pool_elems)) {
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
|
||||
"HTT Frag descriptor alloc fail");
|
||||
goto free_htt_desc;
|
||||
}
|
||||
|
||||
/* success */
|
||||
return 0;
|
||||
|
||||
free_htt_desc:
|
||||
cdf_mem_multi_pages_free(pdev->osdev, &pdev->tx_descs.desc_pages,
|
||||
cdf_get_dma_mem_context((&pdev->tx_descs), memctx), false);
|
||||
out_fail:
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
void htt_tx_detach(struct htt_pdev_t *pdev)
|
||||
{
|
||||
if (pdev) {
|
||||
cdf_os_mem_free_consistent(
|
||||
pdev->osdev,
|
||||
/* pool_size */
|
||||
pdev->tx_descs.pool_elems * pdev->tx_descs.size,
|
||||
pdev->tx_descs.pool_vaddr,
|
||||
pdev->tx_descs.pool_paddr,
|
||||
cdf_get_dma_mem_context((&pdev->tx_descs), memctx));
|
||||
#if defined(HELIUMPLUS_PADDR64)
|
||||
cdf_os_mem_free_consistent(
|
||||
pdev->osdev,
|
||||
/* pool_size */
|
||||
pdev->frag_descs.pool_elems *
|
||||
pdev->frag_descs.size,
|
||||
pdev->frag_descs.pool_vaddr,
|
||||
pdev->frag_descs.pool_paddr,
|
||||
cdf_get_dma_mem_context((&pdev->frag_descs), memctx));
|
||||
#endif /* defined(HELIUMPLUS_PADDR64) */
|
||||
if (!pdev) {
|
||||
cdf_print("htt tx detach invalid instance");
|
||||
return;
|
||||
}
|
||||
|
||||
htt_tx_frag_desc_detach(pdev);
|
||||
cdf_mem_multi_pages_free(pdev->osdev, &pdev->tx_descs.desc_pages,
|
||||
cdf_get_dma_mem_context((&pdev->tx_descs), memctx), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* htt_tx_get_paddr() - get physical address for htt desc
|
||||
*
|
||||
* Get HTT descriptor physical address from virtaul address
|
||||
* Find page first and find offset
|
||||
*
|
||||
* Return: Physical address of descriptor
|
||||
*/
|
||||
static cdf_dma_addr_t htt_tx_get_paddr(htt_pdev_handle pdev,
|
||||
char *target_vaddr)
|
||||
{
|
||||
uint16_t i;
|
||||
struct cdf_mem_dma_page_t *page_info = NULL;
|
||||
uint64_t offset;
|
||||
|
||||
for (i = 0; i < pdev->tx_descs.desc_pages.num_pages; i++) {
|
||||
page_info = pdev->tx_descs.desc_pages.dma_pages + i;
|
||||
if (!page_info->page_v_addr_start) {
|
||||
cdf_assert(0);
|
||||
return 0;
|
||||
}
|
||||
if ((target_vaddr >= page_info->page_v_addr_start) &&
|
||||
(target_vaddr <= page_info->page_v_addr_end))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!page_info) {
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "invalid page_info");
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset = (uint64_t)(target_vaddr - page_info->page_v_addr_start);
|
||||
return page_info->page_p_addr + offset;
|
||||
}
|
||||
|
||||
/*--- descriptor allocation functions ---------------------------------------*/
|
||||
|
||||
void *htt_tx_desc_alloc(htt_pdev_handle pdev, uint32_t *paddr_lo)
|
||||
void *htt_tx_desc_alloc(htt_pdev_handle pdev, uint32_t *paddr_lo,
|
||||
uint16_t index)
|
||||
{
|
||||
struct htt_host_tx_desc_t *htt_host_tx_desc; /* includes HTC hdr */
|
||||
struct htt_tx_msdu_desc_t *htt_tx_desc; /* doesn't include HTC hdr */
|
||||
uint16_t index;
|
||||
uint32_t *fragmentation_descr_field_ptr;
|
||||
|
||||
htt_host_tx_desc = (struct htt_host_tx_desc_t *)pdev->tx_descs.freelist;
|
||||
|
|
@ -234,44 +465,20 @@ void *htt_tx_desc_alloc(htt_pdev_handle pdev, uint32_t *paddr_lo)
|
|||
fragmentation_descr_field_ptr = (uint32_t *)
|
||||
((uint32_t *) htt_tx_desc) +
|
||||
HTT_TX_DESC_FRAGS_DESC_PADDR_OFFSET_DWORD;
|
||||
|
||||
index = ((char *)htt_host_tx_desc -
|
||||
(char *)(((struct htt_host_tx_desc_t *)
|
||||
pdev->tx_descs.pool_vaddr))) /
|
||||
pdev->tx_descs.size;
|
||||
/*
|
||||
* The fragmentation descriptor is allocated from consistent
|
||||
* memory. Therefore, we can use the address directly rather
|
||||
* than having to map it from a virtual/CPU address to a
|
||||
* physical/bus address.
|
||||
*/
|
||||
#if defined(HELIUMPLUS_PADDR64)
|
||||
#if HTT_PADDR64
|
||||
/* this is: frags_desc_ptr.lo */
|
||||
*fragmentation_descr_field_ptr = (uint32_t)
|
||||
(pdev->frag_descs.pool_paddr +
|
||||
(pdev->frag_descs.size * index));
|
||||
fragmentation_descr_field_ptr++;
|
||||
/* frags_desc_ptr.hi */
|
||||
*fragmentation_descr_field_ptr = 0;
|
||||
#else /* ! HTT_PADDR64 */
|
||||
*fragmentation_descr_field_ptr = (uint32_t)
|
||||
(pdev->frag_descs.pool_paddr +
|
||||
(pdev->frag_descs.size * index));
|
||||
cdf_print("%s %d: i %d frag_paddr 0x%x\n",
|
||||
__func__, __LINE__, index,
|
||||
(*fragmentation_descr_field_ptr));
|
||||
#endif /* HTT_PADDR64 */
|
||||
#else /* !HELIUMPLUS_PADDR64 */
|
||||
*fragmentation_descr_field_ptr =
|
||||
HTT_TX_DESC_PADDR(pdev, htt_tx_desc) + HTT_TX_DESC_LEN;
|
||||
#endif /* HELIUMPLUS_PADDR64 */
|
||||
htt_tx_frag_desc_field_update(pdev, fragmentation_descr_field_ptr,
|
||||
index, htt_tx_desc);
|
||||
|
||||
/*
|
||||
* Include the headroom for the HTC frame header when specifying the
|
||||
* physical address for the HTT tx descriptor.
|
||||
*/
|
||||
*paddr_lo = (uint32_t) HTT_TX_DESC_PADDR(pdev, htt_host_tx_desc);
|
||||
*paddr_lo = (uint32_t)htt_tx_get_paddr(pdev, (char *)htt_host_tx_desc);
|
||||
/*
|
||||
* The allocated tx descriptor space includes headroom for a
|
||||
* HTC frame header. Hide this headroom, so that we don't have
|
||||
|
|
@ -312,32 +519,13 @@ void htt_tx_desc_frags_table_set(htt_pdev_handle pdev,
|
|||
*fragmentation_descr_field_ptr = frag_desc_paddr_lo;
|
||||
#else
|
||||
*fragmentation_descr_field_ptr =
|
||||
HTT_TX_DESC_PADDR(pdev, htt_tx_desc) + HTT_TX_DESC_LEN;
|
||||
htt_tx_get_paddr(pdev, htt_tx_desc) + HTT_TX_DESC_LEN;
|
||||
#endif
|
||||
} else {
|
||||
*fragmentation_descr_field_ptr = paddr;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HELIUMPLUS_PADDR64)
|
||||
void *
|
||||
htt_tx_frag_alloc(htt_pdev_handle pdev,
|
||||
u_int16_t index,
|
||||
u_int32_t *frag_paddr_lo)
|
||||
{
|
||||
/** Index should never be 0, since its used by the hardware
|
||||
to terminate the link. */
|
||||
if (index >= pdev->tx_descs.pool_elems)
|
||||
return NULL;
|
||||
|
||||
*frag_paddr_lo = (uint32_t)
|
||||
(pdev->frag_descs.pool_paddr + (pdev->frag_descs.size * index));
|
||||
|
||||
return ((char *) pdev->frag_descs.pool_vaddr) +
|
||||
(pdev->frag_descs.size * index);
|
||||
}
|
||||
#endif /* defined(HELIUMPLUS_PADDR64) */
|
||||
|
||||
/* PUT THESE AS INLINE IN ol_htt_tx_api.h */
|
||||
|
||||
void htt_tx_desc_flag_postponed(htt_pdev_handle pdev, void *desc)
|
||||
|
|
|
|||
|
|
@ -324,10 +324,9 @@ struct htt_pdev_t {
|
|||
|
||||
struct {
|
||||
int size; /* of each HTT tx desc */
|
||||
int pool_elems;
|
||||
int alloc_cnt;
|
||||
char *pool_vaddr;
|
||||
uint32_t pool_paddr;
|
||||
uint16_t pool_elems;
|
||||
uint16_t alloc_cnt;
|
||||
struct cdf_mem_multi_page_t desc_pages;
|
||||
uint32_t *freelist;
|
||||
cdf_dma_mem_context(memctx);
|
||||
} tx_descs;
|
||||
|
|
@ -335,8 +334,7 @@ struct htt_pdev_t {
|
|||
struct {
|
||||
int size; /* of each Fragment/MSDU-Ext descriptor */
|
||||
int pool_elems;
|
||||
char *pool_vaddr;
|
||||
uint32_t pool_paddr;
|
||||
struct cdf_mem_multi_page_t desc_pages;
|
||||
cdf_dma_mem_context(memctx);
|
||||
} frag_descs;
|
||||
#endif /* defined(HELIUMPLUS_PADDR64) */
|
||||
|
|
|
|||
|
|
@ -357,7 +357,8 @@ uint16_t htt_tx_compl_desc_id(void *iterator, int num);
|
|||
* @param[OUT] paddr_lo - physical address of the HTT descriptor
|
||||
* @return success -> descriptor handle, -OR- failure -> NULL
|
||||
*/
|
||||
void *htt_tx_desc_alloc(htt_pdev_handle htt_pdev, uint32_t *paddr_lo);
|
||||
void *htt_tx_desc_alloc(htt_pdev_handle pdev, uint32_t *paddr_lo,
|
||||
uint16_t index);
|
||||
|
||||
/**
|
||||
* @brief Free a HTT abstract tx descriptor.
|
||||
|
|
@ -368,17 +369,26 @@ void *htt_tx_desc_alloc(htt_pdev_handle htt_pdev, uint32_t *paddr_lo);
|
|||
void htt_tx_desc_free(htt_pdev_handle htt_pdev, void *htt_tx_desc);
|
||||
|
||||
#if defined(HELIUMPLUS_PADDR64)
|
||||
/* TODO: oka: use kernel-doc format */
|
||||
/**
|
||||
* @brief Free a HTT abstract tx descriptor.
|
||||
* @brief Allocate TX frag descriptor
|
||||
* @details
|
||||
* Allocate TX frag descriptor
|
||||
*
|
||||
* @param htt_pdev - handle to the HTT instance that made the allocation
|
||||
* @param htt_tx_desc - the descriptor to free
|
||||
* @param pdev - handle to the HTT instance that made the allocation
|
||||
* @param index - tx descriptor index
|
||||
* @param frag_paddr_lo - fragment descriptor physical address lower 32bits
|
||||
* @param frag_ptr - fragment descriptor hlos pointe
|
||||
* @return success 0
|
||||
*/
|
||||
void *
|
||||
htt_tx_frag_alloc(htt_pdev_handle pdev,
|
||||
u_int16_t index,
|
||||
u_int32_t *frag_paddr_lo);
|
||||
int htt_tx_frag_alloc(htt_pdev_handle pdev,
|
||||
u_int16_t index, u_int32_t *frag_paddr_lo, void **frag_ptr);
|
||||
#else
|
||||
static inline int htt_tx_frag_alloc(htt_pdev_handle pdev,
|
||||
u_int16_t index, u_int32_t *frag_paddr_lo, void **frag_ptr)
|
||||
{
|
||||
*frag_ptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(HELIUMPLUS_PADDR64) */
|
||||
/**
|
||||
* @brief Discard all tx frames in the process of being downloaded.
|
||||
|
|
|
|||
|
|
@ -1159,7 +1159,7 @@ void dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc)
|
|||
int i;
|
||||
|
||||
cdf_print("OL TX Descriptor 0x%p msdu_id %d\n",
|
||||
tx_desc, tx_desc->index);
|
||||
tx_desc, tx_desc->id);
|
||||
cdf_print("HTT TX Descriptor vaddr: 0x%p paddr: 0x%x\n",
|
||||
tx_desc->htt_tx_desc, tx_desc->htt_tx_desc_paddr);
|
||||
cdf_print("%s %d: Fragment Descriptor 0x%p\n",
|
||||
|
|
@ -1329,35 +1329,34 @@ cdf_nbuf_t ol_tx_reinject(struct ol_txrx_vdev_t *vdev,
|
|||
void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg)
|
||||
{
|
||||
int i;
|
||||
pdev->tso_seg_pool.pool_size = num_seg;
|
||||
pdev->tso_seg_pool.num_free = num_seg;
|
||||
struct cdf_tso_seg_elem_t *c_element;
|
||||
|
||||
pdev->tso_seg_pool.array = NULL;
|
||||
pdev->tso_seg_pool.array = cdf_mem_malloc(num_seg *
|
||||
sizeof(struct cdf_tso_seg_elem_t));
|
||||
if (!pdev->tso_seg_pool.array) {
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
|
||||
"%s Could not allocate TSO array!\n", __func__);
|
||||
return;
|
||||
c_element = cdf_mem_malloc(sizeof(struct cdf_tso_seg_elem_t));
|
||||
pdev->tso_seg_pool.freelist = c_element;
|
||||
for (i = 0; i < (num_seg - 1); i++) {
|
||||
c_element->next =
|
||||
cdf_mem_malloc(sizeof(struct cdf_tso_seg_elem_t));
|
||||
c_element = c_element->next;
|
||||
c_element->next = NULL;
|
||||
}
|
||||
|
||||
pdev->tso_seg_pool.freelist = &pdev->tso_seg_pool.array[0];
|
||||
|
||||
for (i = 0; i < (num_seg - 1); i++)
|
||||
pdev->tso_seg_pool.array[i].next =
|
||||
&pdev->tso_seg_pool.array[i + 1];
|
||||
|
||||
pdev->tso_seg_pool.array[i].next = NULL;
|
||||
|
||||
pdev->tso_seg_pool.pool_size = num_seg;
|
||||
cdf_spinlock_init(&pdev->tso_seg_pool.tso_mutex);
|
||||
}
|
||||
|
||||
void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev)
|
||||
{
|
||||
int i;
|
||||
struct cdf_tso_seg_elem_t *c_element;
|
||||
struct cdf_tso_seg_elem_t *temp;
|
||||
|
||||
cdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex);
|
||||
if (pdev->tso_seg_pool.array) {
|
||||
cdf_mem_free(pdev->tso_seg_pool.array);
|
||||
pdev->tso_seg_pool.array = NULL;
|
||||
c_element = pdev->tso_seg_pool.freelist;
|
||||
for (i = 0; i < pdev->tso_seg_pool.pool_size; i++) {
|
||||
temp = c_element->next;
|
||||
cdf_mem_free(c_element);
|
||||
c_element = temp;
|
||||
if (!c_element)
|
||||
break;
|
||||
}
|
||||
|
||||
pdev->tso_seg_pool.freelist = NULL;
|
||||
|
|
|
|||
|
|
@ -78,5 +78,15 @@ void ol_txrx_mgmt_tx_complete(void *ctxt, cdf_nbuf_t netbuf, int err);
|
|||
#if defined(FEATURE_TSO)
|
||||
void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg);
|
||||
void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev);
|
||||
#else
|
||||
static inline void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev,
|
||||
uint32_t num_seg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
static inline void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif /* _OL_TX__H_ */
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@ struct ol_tx_desc_t *ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev,
|
|||
pdev->tx_desc.freelist = pdev->tx_desc.freelist->next;
|
||||
ol_tx_desc_sanity_checks(pdev, tx_desc);
|
||||
ol_tx_desc_compute_delay(tx_desc);
|
||||
|
||||
}
|
||||
cdf_spin_unlock_bh(&pdev->tx_mutex);
|
||||
if (!tx_desc)
|
||||
|
|
@ -231,13 +230,6 @@ ol_tx_desc_alloc_wrapper(struct ol_txrx_pdev_t *pdev,
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* TBD: make this inline in the .h file? */
|
||||
struct ol_tx_desc_t *ol_tx_desc_find(struct ol_txrx_pdev_t *pdev,
|
||||
uint16_t tx_desc_id)
|
||||
{
|
||||
return &pdev->tx_desc.array[tx_desc_id].tx_desc;
|
||||
}
|
||||
|
||||
#ifndef QCA_LL_TX_FLOW_CONTROL_V2
|
||||
/**
|
||||
* ol_tx_desc_free() - put descriptor to freelist
|
||||
|
|
@ -537,7 +529,7 @@ void ol_tx_desc_frame_free_nonstd(struct ol_txrx_pdev_t *pdev,
|
|||
*/
|
||||
#if defined(HELIUMPLUS_DEBUG)
|
||||
cdf_print("%s %d: Frag Descriptor Reset [%d] to 0x%x\n",
|
||||
__func__, __LINE__, tx_desc->index,
|
||||
__func__, __LINE__, tx_desc->id,
|
||||
frag_desc_paddr_lo);
|
||||
#endif /* HELIUMPLUS_DEBUG */
|
||||
#endif /* HELIUMPLUS_PADDR64 */
|
||||
|
|
@ -591,8 +583,6 @@ struct cdf_tso_seg_elem_t *ol_tso_alloc_segment(struct ol_txrx_pdev_t *pdev)
|
|||
pdev->tso_seg_pool.freelist = pdev->tso_seg_pool.freelist->next;
|
||||
}
|
||||
cdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
|
||||
if (!tso_seg)
|
||||
return NULL;
|
||||
|
||||
return tso_seg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,8 +73,16 @@ struct ol_tx_desc_t *ol_tx_desc_ll(struct ol_txrx_pdev_t *pdev,
|
|||
* @param tx_desc_id - the ID of the descriptor in question
|
||||
* @return the descriptor object that has the specified ID
|
||||
*/
|
||||
struct ol_tx_desc_t *ol_tx_desc_find(struct ol_txrx_pdev_t *pdev,
|
||||
uint16_t tx_desc_id);
|
||||
static inline struct ol_tx_desc_t *ol_tx_desc_find(
|
||||
struct ol_txrx_pdev_t *pdev, uint16_t tx_desc_id)
|
||||
{
|
||||
void **td_base = (void **)pdev->tx_desc.desc_pages.cacheable_pages;
|
||||
|
||||
return &((union ol_tx_desc_list_elem_t *)
|
||||
(td_base[tx_desc_id >> pdev->tx_desc.page_divider] +
|
||||
(pdev->tx_desc.desc_reserved_size *
|
||||
(tx_desc_id & pdev->tx_desc.offset_filter))))->tx_desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free a list of tx descriptors and the tx frames they refer to.
|
||||
|
|
@ -125,10 +133,8 @@ void ol_tx_desc_frame_free_nonstd(struct ol_txrx_pdev_t *pdev,
|
|||
static inline uint16_t
|
||||
ol_tx_desc_id(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc)
|
||||
{
|
||||
TXRX_ASSERT2(((union ol_tx_desc_list_elem_t *)tx_desc -
|
||||
pdev->tx_desc.array) < pdev->tx_desc.pool_size);
|
||||
return (uint16_t)
|
||||
((union ol_tx_desc_list_elem_t *)tx_desc - pdev->tx_desc.array);
|
||||
TXRX_ASSERT2(tx_desc->id < pdev->tx_desc.pool_size);
|
||||
return tx_desc->id;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -442,8 +442,10 @@ ol_tx_delay_compute(struct ol_txrx_pdev_t *pdev,
|
|||
void ol_tx_discard_target_frms(ol_txrx_pdev_handle pdev)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < pdev->tx_desc.pool_size; i++) {
|
||||
struct ol_tx_desc_t *tx_desc;
|
||||
|
||||
for (i = 0; i < pdev->tx_desc.pool_size; i++) {
|
||||
tx_desc = ol_tx_desc_find(pdev, i);
|
||||
/*
|
||||
* Confirm that each tx descriptor is "empty", i.e. it has
|
||||
* no tx frame attached.
|
||||
|
|
@ -451,12 +453,11 @@ void ol_tx_discard_target_frms(ol_txrx_pdev_handle pdev)
|
|||
* been given to the target to transmit, for which the
|
||||
* target has never provided a response.
|
||||
*/
|
||||
if (cdf_atomic_read(&pdev->tx_desc.array[i].tx_desc.ref_cnt)) {
|
||||
if (cdf_atomic_read(&tx_desc->ref_cnt)) {
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_WARN,
|
||||
"Warning: freeing tx frame "
|
||||
"(no tx completion from the target)\n");
|
||||
ol_tx_desc_frame_free_nonstd(pdev,
|
||||
&pdev->tx_desc.array[i].
|
||||
tx_desc, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -487,7 +488,6 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev,
|
|||
char *trace_str;
|
||||
|
||||
uint32_t byte_cnt = 0;
|
||||
union ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array;
|
||||
cdf_nbuf_t netbuf;
|
||||
|
||||
union ol_tx_desc_list_elem_t *lcl_freelist = NULL;
|
||||
|
|
@ -500,7 +500,7 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev,
|
|||
trace_str = (status) ? "OT:C:F:" : "OT:C:S:";
|
||||
for (i = 0; i < num_msdus; i++) {
|
||||
tx_desc_id = desc_ids[i];
|
||||
tx_desc = &td_array[tx_desc_id].tx_desc;
|
||||
tx_desc = ol_tx_desc_find(pdev, tx_desc_id);
|
||||
tx_desc->status = status;
|
||||
netbuf = tx_desc->netbuf;
|
||||
|
||||
|
|
@ -560,10 +560,9 @@ ol_tx_single_completion_handler(ol_txrx_pdev_handle pdev,
|
|||
enum htt_tx_status status, uint16_t tx_desc_id)
|
||||
{
|
||||
struct ol_tx_desc_t *tx_desc;
|
||||
union ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array;
|
||||
cdf_nbuf_t netbuf;
|
||||
|
||||
tx_desc = &td_array[tx_desc_id].tx_desc;
|
||||
tx_desc = ol_tx_desc_find(pdev, tx_desc_id);
|
||||
tx_desc->status = status;
|
||||
netbuf = tx_desc->netbuf;
|
||||
|
||||
|
|
@ -597,7 +596,6 @@ ol_tx_inspect_handler(ol_txrx_pdev_handle pdev,
|
|||
uint16_t *desc_ids = (uint16_t *) tx_desc_id_iterator;
|
||||
uint16_t tx_desc_id;
|
||||
struct ol_tx_desc_t *tx_desc;
|
||||
union ol_tx_desc_list_elem_t *td_array = pdev->tx_desc.array;
|
||||
union ol_tx_desc_list_elem_t *lcl_freelist = NULL;
|
||||
union ol_tx_desc_list_elem_t *tx_desc_last = NULL;
|
||||
cdf_nbuf_t netbuf;
|
||||
|
|
@ -606,7 +604,7 @@ ol_tx_inspect_handler(ol_txrx_pdev_handle pdev,
|
|||
|
||||
for (i = 0; i < num_msdus; i++) {
|
||||
tx_desc_id = desc_ids[i];
|
||||
tx_desc = &td_array[tx_desc_id].tx_desc;
|
||||
tx_desc = ol_tx_desc_find(pdev, tx_desc_id);
|
||||
netbuf = tx_desc->netbuf;
|
||||
|
||||
/* find the "vdev" this tx_desc belongs to */
|
||||
|
|
@ -848,7 +846,7 @@ ol_tx_delay_tid_from_l3_hdr(struct ol_txrx_pdev_t *pdev,
|
|||
static int ol_tx_delay_category(struct ol_txrx_pdev_t *pdev, uint16_t msdu_id)
|
||||
{
|
||||
#ifdef QCA_COMPUTE_TX_DELAY_PER_TID
|
||||
struct ol_tx_desc_t *tx_desc = &pdev->tx_desc.array[msdu_id].tx_desc;
|
||||
struct ol_tx_desc_t *tx_desc = ol_tx_desc_find(pdev, msdu_id);
|
||||
uint8_t tid;
|
||||
|
||||
cdf_nbuf_t msdu = tx_desc->netbuf;
|
||||
|
|
@ -939,9 +937,9 @@ ol_tx_delay_compute(struct ol_txrx_pdev_t *pdev,
|
|||
pdev->tx_delay.tx_compl_timestamp_ticks = now_ticks;
|
||||
|
||||
for (i = 0; i < num_msdus; i++) {
|
||||
uint16_t id = desc_ids[i];
|
||||
struct ol_tx_desc_t *tx_desc = &pdev->tx_desc.array[id].tx_desc;
|
||||
int bin;
|
||||
uint16_t id = desc_ids[i];
|
||||
struct ol_tx_desc_t *tx_desc = ol_tx_desc_find(pdev, id);
|
||||
|
||||
tx_delay_queue_ticks =
|
||||
now_ticks - tx_desc->entry_timestamp_ticks;
|
||||
|
|
|
|||
|
|
@ -258,29 +258,11 @@ setup_fastpath_ce_handles(struct ol_softc *osc, struct ol_txrx_pdev_t *pdev)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* init_txdesc_id() initialize Tx desc with id
|
||||
*
|
||||
* @pdev: handle OL pdev
|
||||
* @desc_num: Tx descriptor number
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static inline void
|
||||
init_txdesc_id(struct ol_txrx_pdev_t *pdev, int desc_num)
|
||||
{
|
||||
pdev->tx_desc.array[desc_num].tx_desc.id = desc_num;
|
||||
cdf_atomic_init(&pdev->tx_desc.array[desc_num].tx_desc.ref_cnt);
|
||||
}
|
||||
#else /* not WLAN_FEATURE_FASTPATH */
|
||||
static inline void
|
||||
setup_fastpath_ce_handles(struct ol_softc *osc, struct ol_txrx_pdev_t *pdev)
|
||||
{
|
||||
}
|
||||
static inline void
|
||||
init_txdesc_id(struct ol_txrx_pdev_t *pdev, int desc_num)
|
||||
{
|
||||
}
|
||||
#endif /* WLAN_FEATURE_FASTPATH */
|
||||
|
||||
#ifdef QCA_LL_TX_FLOW_CONTROL_V2
|
||||
|
|
@ -391,14 +373,20 @@ fail0:
|
|||
int
|
||||
ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev)
|
||||
{
|
||||
int i;
|
||||
uint16_t i;
|
||||
uint16_t fail_idx = 0;
|
||||
int ret = 0;
|
||||
uint16_t desc_pool_size;
|
||||
struct ol_softc *osc = cds_get_context(CDF_MODULE_ID_HIF);
|
||||
|
||||
uint16_t desc_element_size = sizeof(union ol_tx_desc_list_elem_t);
|
||||
union ol_tx_desc_list_elem_t *c_element;
|
||||
unsigned int sig_bit;
|
||||
uint16_t desc_per_page;
|
||||
|
||||
if (!osc) {
|
||||
ret = -EINVAL;
|
||||
goto fail0;
|
||||
goto ol_attach_fail;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -428,7 +416,7 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev)
|
|||
|
||||
ret = htt_attach(pdev->htt_pdev, desc_pool_size);
|
||||
if (ret)
|
||||
goto fail0;
|
||||
goto ol_attach_fail;
|
||||
|
||||
/* Update CE's pkt download length */
|
||||
ce_pkt_dl_len_set((void *)osc, htt_pkt_dl_len_get(pdev->htt_pdev));
|
||||
|
|
@ -436,15 +424,32 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev)
|
|||
/* Attach micro controller data path offload resource */
|
||||
if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev))
|
||||
if (htt_ipa_uc_attach(pdev->htt_pdev))
|
||||
goto fail1;
|
||||
goto uc_attach_fail;
|
||||
|
||||
pdev->tx_desc.array =
|
||||
cdf_mem_malloc(desc_pool_size *
|
||||
sizeof(union ol_tx_desc_list_elem_t));
|
||||
if (!pdev->tx_desc.array)
|
||||
goto fail2;
|
||||
cdf_mem_set(pdev->tx_desc.array,
|
||||
desc_pool_size * sizeof(union ol_tx_desc_list_elem_t), 0);
|
||||
/* Calculate single element reserved size power of 2 */
|
||||
pdev->tx_desc.desc_reserved_size = cdf_get_pwr2(desc_element_size);
|
||||
cdf_mem_multi_pages_alloc(pdev->osdev, &pdev->tx_desc.desc_pages,
|
||||
pdev->tx_desc.desc_reserved_size, desc_pool_size, 0, true);
|
||||
if ((0 == pdev->tx_desc.desc_pages.num_pages) ||
|
||||
(NULL == pdev->tx_desc.desc_pages.cacheable_pages)) {
|
||||
CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR,
|
||||
"Page alloc fail");
|
||||
goto page_alloc_fail;
|
||||
}
|
||||
desc_per_page = pdev->tx_desc.desc_pages.num_element_per_page;
|
||||
pdev->tx_desc.offset_filter = desc_per_page - 1;
|
||||
/* Calculate page divider to find page number */
|
||||
sig_bit = 0;
|
||||
while (desc_per_page) {
|
||||
sig_bit++;
|
||||
desc_per_page = desc_per_page >> 1;
|
||||
}
|
||||
pdev->tx_desc.page_divider = (sig_bit - 1);
|
||||
CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR,
|
||||
"page_divider 0x%x, offset_filter 0x%x num elem %d, ol desc num page %d, ol desc per page %d",
|
||||
pdev->tx_desc.page_divider, pdev->tx_desc.offset_filter,
|
||||
desc_pool_size, pdev->tx_desc.desc_pages.num_pages,
|
||||
pdev->tx_desc.desc_pages.num_element_per_page);
|
||||
|
||||
/*
|
||||
* Each SW tx desc (used only within the tx datapath SW) has a
|
||||
|
|
@ -453,79 +458,74 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev)
|
|||
* desc now, to avoid doing it during time-critical transmit.
|
||||
*/
|
||||
pdev->tx_desc.pool_size = desc_pool_size;
|
||||
pdev->tx_desc.freelist =
|
||||
(union ol_tx_desc_list_elem_t *)
|
||||
(*pdev->tx_desc.desc_pages.cacheable_pages);
|
||||
c_element = pdev->tx_desc.freelist;
|
||||
for (i = 0; i < desc_pool_size; i++) {
|
||||
void *htt_tx_desc;
|
||||
#if defined(HELIUMPLUS_PADDR64)
|
||||
void *htt_frag_desc;
|
||||
uint32_t frag_paddr_lo;
|
||||
#endif /* defined(HELIUMPLUS_PADDR64) */
|
||||
void *htt_frag_desc = NULL;
|
||||
uint32_t frag_paddr_lo = 0;
|
||||
uint32_t paddr_lo;
|
||||
|
||||
htt_tx_desc = htt_tx_desc_alloc(pdev->htt_pdev, &paddr_lo);
|
||||
if (i == (desc_pool_size - 1))
|
||||
c_element->next = NULL;
|
||||
else
|
||||
c_element->next = (union ol_tx_desc_list_elem_t *)
|
||||
ol_tx_desc_find(pdev, i + 1);
|
||||
|
||||
htt_tx_desc = htt_tx_desc_alloc(pdev->htt_pdev, &paddr_lo, i);
|
||||
if (!htt_tx_desc) {
|
||||
CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_FATAL,
|
||||
"%s: failed to alloc HTT tx desc (%d of %d)",
|
||||
__func__, i, desc_pool_size);
|
||||
while (--i >= 0) {
|
||||
htt_tx_desc_free(pdev->htt_pdev,
|
||||
pdev->tx_desc.array[i].
|
||||
tx_desc.htt_tx_desc);
|
||||
}
|
||||
goto fail3;
|
||||
fail_idx = i;
|
||||
goto desc_alloc_fail;
|
||||
}
|
||||
pdev->tx_desc.array[i].tx_desc.htt_tx_desc = htt_tx_desc;
|
||||
pdev->tx_desc.array[i].tx_desc.htt_tx_desc_paddr = paddr_lo;
|
||||
|
||||
#if defined(HELIUMPLUS_PADDR64)
|
||||
htt_frag_desc = htt_tx_frag_alloc(pdev->htt_pdev, i,
|
||||
&frag_paddr_lo);
|
||||
if (!htt_frag_desc) {
|
||||
cdf_print("%s: failed to alloc HTT frag dsc (%d/%d)\n",
|
||||
__func__, i, desc_pool_size);
|
||||
c_element->tx_desc.htt_tx_desc = htt_tx_desc;
|
||||
c_element->tx_desc.htt_tx_desc_paddr = paddr_lo;
|
||||
ret = htt_tx_frag_alloc(pdev->htt_pdev,
|
||||
i, &frag_paddr_lo, &htt_frag_desc);
|
||||
if (ret) {
|
||||
CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR,
|
||||
"%s: failed to alloc HTT frag dsc (%d/%d)",
|
||||
__func__, i, desc_pool_size);
|
||||
/* Is there a leak here, is this handling correct? */
|
||||
goto fail3;
|
||||
fail_idx = i;
|
||||
goto desc_alloc_fail;
|
||||
}
|
||||
/* Initialize the first 6 words (TSO flags)
|
||||
of the frag descriptor */
|
||||
memset(htt_frag_desc, 0, 6*sizeof(uint32_t));
|
||||
|
||||
pdev->tx_desc.array[i].tx_desc.htt_frag_desc = htt_frag_desc;
|
||||
#if defined(HELIUMPLUS_DEBUG)
|
||||
cdf_print("%s:%d %d %p\n", __func__, __LINE__,
|
||||
i, pdev->tx_desc.array[i].tx_desc.htt_frag_desc);
|
||||
#endif /* HELIUMPLUS_DEBUG */
|
||||
pdev->tx_desc.array[i].tx_desc.htt_frag_desc_paddr =
|
||||
frag_paddr_lo;
|
||||
#if defined(HELIUMPLUS_DEBUG)
|
||||
cdf_print("%s:%d - %d FRAG VA 0x%p FRAG PA 0x%x\n",
|
||||
if (!ret && htt_frag_desc) {
|
||||
/* Initialize the first 6 words (TSO flags)
|
||||
of the frag descriptor */
|
||||
memset(htt_frag_desc, 0, 6 * sizeof(uint32_t));
|
||||
c_element->tx_desc.htt_frag_desc = htt_frag_desc;
|
||||
c_element->tx_desc.htt_frag_desc_paddr = frag_paddr_lo;
|
||||
}
|
||||
CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_INFO_LOW,
|
||||
"%s:%d - %d FRAG VA 0x%p FRAG PA 0x%x",
|
||||
__func__, __LINE__, i,
|
||||
pdev->tx_desc.array[i].tx_desc.htt_frag_desc,
|
||||
pdev->tx_desc.array[i].tx_desc.htt_frag_desc_paddr);
|
||||
#endif /* HELIUMPLUS_DEBUG */
|
||||
#endif /* defined(HELIUMPLUS_PADDR64) */
|
||||
|
||||
pdev->tx_desc.array[i].tx_desc.index = i;
|
||||
c_element->tx_desc.htt_frag_desc,
|
||||
c_element->tx_desc.htt_frag_desc_paddr);
|
||||
#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS
|
||||
pdev->tx_desc.array[i].tx_desc.pkt_type = 0xff;
|
||||
c_element->tx_desc.pkt_type = 0xff;
|
||||
#ifdef QCA_COMPUTE_TX_DELAY
|
||||
pdev->tx_desc.array[i].tx_desc.entry_timestamp_ticks =
|
||||
c_element->tx_desc.entry_timestamp_ticks =
|
||||
0xffffffff;
|
||||
#endif
|
||||
#endif
|
||||
init_txdesc_id(pdev, i);
|
||||
c_element->tx_desc.id = i;
|
||||
cdf_atomic_init(&c_element->tx_desc.ref_cnt);
|
||||
c_element = c_element->next;
|
||||
fail_idx = i;
|
||||
}
|
||||
|
||||
/* link SW tx descs into a freelist */
|
||||
pdev->tx_desc.num_free = desc_pool_size;
|
||||
pdev->tx_desc.freelist = &pdev->tx_desc.array[0];
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1,
|
||||
"%s first tx_desc:0x%p Last tx desc:0x%p\n", __func__,
|
||||
(uint32_t *) pdev->tx_desc.freelist,
|
||||
(uint32_t *) (pdev->tx_desc.freelist + desc_pool_size));
|
||||
for (i = 0; i < desc_pool_size - 1; i++)
|
||||
pdev->tx_desc.array[i].next = &pdev->tx_desc.array[i + 1];
|
||||
|
||||
pdev->tx_desc.array[i].next = NULL;
|
||||
|
||||
/* check what format of frames are expected to be delivered by the OS */
|
||||
pdev->frame_format = ol_cfg_frame_type(pdev->ctrl_pdev);
|
||||
|
|
@ -540,7 +540,7 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev)
|
|||
CDF_TRACE(CDF_MODULE_ID_TXRX, CDF_TRACE_LEVEL_ERROR,
|
||||
"%s Invalid standard frame type: %d",
|
||||
__func__, pdev->frame_format);
|
||||
goto fail4;
|
||||
goto control_init_fail;
|
||||
}
|
||||
|
||||
/* setup the global rx defrag waitlist */
|
||||
|
|
@ -608,7 +608,7 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev)
|
|||
"Invalid std frame type; [en/de]cap: f:%x t:%x r:%x",
|
||||
pdev->frame_format,
|
||||
pdev->target_tx_tran_caps, pdev->target_rx_tran_caps);
|
||||
goto fail4;
|
||||
goto control_init_fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -658,7 +658,7 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev)
|
|||
CDF_TRACE_LEVEL_ERROR,
|
||||
"%s: %s", __func__, TRACESTR01);
|
||||
#undef TRACESTR01
|
||||
goto fail4;
|
||||
goto control_init_fail;
|
||||
}
|
||||
} else {
|
||||
/* PN check done on target */
|
||||
|
|
@ -686,10 +686,10 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev)
|
|||
OL_TXRX_PEER_STATS_MUTEX_INIT(pdev);
|
||||
|
||||
if (OL_RX_REORDER_TRACE_ATTACH(pdev) != A_OK)
|
||||
goto fail5;
|
||||
goto reorder_trace_attach_fail;
|
||||
|
||||
if (OL_RX_PN_TRACE_ATTACH(pdev) != A_OK)
|
||||
goto fail6;
|
||||
goto pn_trace_attach_fail;
|
||||
|
||||
#ifdef PERE_IP_HDR_ALIGNMENT_WAR
|
||||
pdev->host_80211_enable = ol_scn_host_80211_enable_get(pdev->ctrl_pdev);
|
||||
|
|
@ -791,45 +791,39 @@ ol_txrx_pdev_attach(ol_txrx_pdev_handle pdev)
|
|||
}
|
||||
#endif /* QCA_COMPUTE_TX_DELAY */
|
||||
|
||||
#ifdef QCA_SUPPORT_TX_THROTTLE
|
||||
/* Thermal Mitigation */
|
||||
ol_tx_throttle_init(pdev);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(FEATURE_TSO)
|
||||
ol_tso_seg_list_init(pdev, desc_pool_size);
|
||||
#endif
|
||||
|
||||
ol_tx_register_flow_control(pdev);
|
||||
|
||||
return 0; /* success */
|
||||
|
||||
fail6:
|
||||
pn_trace_attach_fail:
|
||||
OL_RX_REORDER_TRACE_DETACH(pdev);
|
||||
|
||||
fail5:
|
||||
reorder_trace_attach_fail:
|
||||
cdf_spinlock_destroy(&pdev->tx_mutex);
|
||||
cdf_spinlock_destroy(&pdev->peer_ref_mutex);
|
||||
cdf_spinlock_destroy(&pdev->rx.mutex);
|
||||
cdf_spinlock_destroy(&pdev->last_real_peer_mutex);
|
||||
OL_TXRX_PEER_STATS_MUTEX_DESTROY(pdev);
|
||||
|
||||
fail4:
|
||||
for (i = 0; i < desc_pool_size; i++)
|
||||
control_init_fail:
|
||||
desc_alloc_fail:
|
||||
for (i = 0; i < fail_idx; i++)
|
||||
htt_tx_desc_free(pdev->htt_pdev,
|
||||
pdev->tx_desc.array[i].tx_desc.htt_tx_desc);
|
||||
(ol_tx_desc_find(pdev, i))->htt_tx_desc);
|
||||
|
||||
fail3:
|
||||
cdf_mem_free(pdev->tx_desc.array);
|
||||
cdf_mem_multi_pages_free(pdev->osdev,
|
||||
&pdev->tx_desc.desc_pages, 0, true);
|
||||
|
||||
fail2:
|
||||
page_alloc_fail:
|
||||
if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev))
|
||||
htt_ipa_uc_detach(pdev->htt_pdev);
|
||||
fail1:
|
||||
uc_attach_fail:
|
||||
htt_detach(pdev->htt_pdev);
|
||||
|
||||
fail0:
|
||||
ol_attach_fail:
|
||||
return ret; /* fail */
|
||||
}
|
||||
|
||||
|
|
@ -841,6 +835,7 @@ A_STATUS ol_txrx_pdev_attach_target(ol_txrx_pdev_handle pdev)
|
|||
void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev, int force)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*checking to ensure txrx pdev structure is not NULL */
|
||||
if (!pdev) {
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "NULL pdev passed to %s\n", __func__);
|
||||
|
|
@ -863,7 +858,7 @@ void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev, int force)
|
|||
cdf_softirq_timer_free(&pdev->tx_throttle.tx_timer);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ol_tso_seg_list_deinit(pdev);
|
||||
ol_tx_deregister_flow_control(pdev);
|
||||
|
||||
if (force) {
|
||||
|
|
@ -889,7 +884,9 @@ void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev, int force)
|
|||
|
||||
for (i = 0; i < pdev->tx_desc.pool_size; i++) {
|
||||
void *htt_tx_desc;
|
||||
struct ol_tx_desc_t *tx_desc;
|
||||
|
||||
tx_desc = ol_tx_desc_find(pdev, i);
|
||||
/*
|
||||
* Confirm that each tx descriptor is "empty", i.e. it has
|
||||
* no tx frame attached.
|
||||
|
|
@ -897,18 +894,19 @@ void ol_txrx_pdev_detach(ol_txrx_pdev_handle pdev, int force)
|
|||
* been given to the target to transmit, for which the
|
||||
* target has never provided a response.
|
||||
*/
|
||||
if (cdf_atomic_read(&pdev->tx_desc.array[i].tx_desc.ref_cnt)) {
|
||||
if (cdf_atomic_read(&tx_desc->ref_cnt)) {
|
||||
TXRX_PRINT(TXRX_PRINT_LEVEL_WARN,
|
||||
"Warning: freeing tx frame (no compltn)\n");
|
||||
ol_tx_desc_frame_free_nonstd(pdev,
|
||||
&pdev->tx_desc.array[i].
|
||||
tx_desc, 1);
|
||||
}
|
||||
htt_tx_desc = pdev->tx_desc.array[i].tx_desc.htt_tx_desc;
|
||||
htt_tx_desc = tx_desc->htt_tx_desc;
|
||||
htt_tx_desc_free(pdev->htt_pdev, htt_tx_desc);
|
||||
}
|
||||
|
||||
cdf_mem_free(pdev->tx_desc.array);
|
||||
cdf_mem_multi_pages_free(pdev->osdev,
|
||||
&pdev->tx_desc.desc_pages, 0, true);
|
||||
pdev->tx_desc.freelist = NULL;
|
||||
|
||||
/* Detach micro controller data path offload resource */
|
||||
if (ol_cfg_ipa_uc_offload_enabled(pdev->ctrl_pdev))
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#define _OL_TXRX_TYPES__H_
|
||||
|
||||
#include <cdf_nbuf.h> /* cdf_nbuf_t */
|
||||
#include <cdf_memory.h>
|
||||
#include <cds_queue.h> /* TAILQ */
|
||||
#include <a_types.h> /* A_UINT8 */
|
||||
#include <htt.h> /* htt_sec_type, htt_pkt_type, etc. */
|
||||
|
|
@ -131,15 +132,10 @@ enum ol_tx_frm_type {
|
|||
struct ol_tx_desc_t {
|
||||
cdf_nbuf_t netbuf;
|
||||
void *htt_tx_desc;
|
||||
#ifdef WLAN_FEATURE_FASTPATH
|
||||
uint16_t id;
|
||||
#endif /* WLAN_FEATURE_FASTPATH */
|
||||
uint32_t htt_tx_desc_paddr;
|
||||
#if defined(HELIUMPLUS_PADDR64)
|
||||
void *htt_frag_desc; /* struct msdu_ext_desc_t * */
|
||||
uint32_t htt_frag_desc_paddr;
|
||||
#endif /* defined(HELIUMPLUS_PADDR64) */
|
||||
uint32_t index;
|
||||
cdf_atomic_t ref_cnt;
|
||||
enum htt_tx_status status;
|
||||
|
||||
|
|
@ -565,13 +561,17 @@ struct ol_txrx_pdev_t {
|
|||
struct {
|
||||
uint16_t pool_size;
|
||||
uint16_t num_free;
|
||||
union ol_tx_desc_list_elem_t *array;
|
||||
union ol_tx_desc_list_elem_t *freelist;
|
||||
#ifdef QCA_LL_TX_FLOW_CONTROL_V2
|
||||
uint8_t num_invalid_bin;
|
||||
cdf_spinlock_t flow_pool_list_lock;
|
||||
TAILQ_HEAD(flow_pool_list_t, ol_tx_flow_pool_t) flow_pool_list;
|
||||
#endif
|
||||
uint32_t page_size;
|
||||
uint16_t desc_reserved_size;
|
||||
uint8_t page_divider;
|
||||
uint32_t offset_filter;
|
||||
struct cdf_mem_multi_page_t desc_pages;
|
||||
} tx_desc;
|
||||
|
||||
#if defined(QCA_LL_TX_FLOW_CONTROL_V2)
|
||||
|
|
@ -761,7 +761,6 @@ struct ol_txrx_pdev_t {
|
|||
struct {
|
||||
uint16_t pool_size;
|
||||
uint16_t num_free;
|
||||
struct cdf_tso_seg_elem_t *array;
|
||||
struct cdf_tso_seg_elem_t *freelist;
|
||||
/* tso mutex */
|
||||
OL_TX_MUTEX_TYPE tso_mutex;
|
||||
|
|
|
|||
Loading…
Reference in a new issue