X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=drivers%2Fnet%2Fqede%2Fbase%2Fecore_chain.h;h=6d0382d3a77a7bddb52092356454d348126bc5d8;hb=b63264c8342e6a1b6971c79550d2af2024b6a4de;hp=9ad1874f3fd03d99c272beb9f57ebb234566276f;hpb=6b3e017e5d25f15da73f7700f7f2ac553ef1a2e9;p=deb_dpdk.git diff --git a/drivers/net/qede/base/ecore_chain.h b/drivers/net/qede/base/ecore_chain.h index 9ad1874f..6d0382d3 100644 --- a/drivers/net/qede/base/ecore_chain.h +++ b/drivers/net/qede/base/ecore_chain.h @@ -1,9 +1,7 @@ -/* - * Copyright (c) 2016 QLogic Corporation. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2016 - 2018 Cavium Inc. * All rights reserved. - * www.qlogic.com - * - * See LICENSE.qede_pmd for copyright and licensing details. + * www.cavium.com */ #ifndef __ECORE_CHAIN_H__ @@ -54,21 +52,9 @@ struct ecore_chain_pbl_u32 { u32 cons_page_idx; }; -struct ecore_chain_pbl { - /* Base address of a pre-allocated buffer for pbl */ - dma_addr_t p_phys_table; - void *p_virt_table; - - /* Table for keeping the virtual addresses of the chain pages, - * respectively to the physical addresses in the pbl table. - */ - void **pp_virt_addr_tbl; - - /* Index to current used page by producer/consumer */ - union { - struct ecore_chain_pbl_u16 pbl16; - struct ecore_chain_pbl_u32 pbl32; - } u; +struct ecore_chain_ext_pbl { + dma_addr_t p_pbl_phys; + void *p_pbl_virt; }; struct ecore_chain_u16 { @@ -84,40 +70,75 @@ struct ecore_chain_u32 { }; struct ecore_chain { - /* Address of first page of the chain */ - void *p_virt_addr; - dma_addr_t p_phys_addr; - + /* fastpath portion of the chain - required for commands such + * as produce / consume. + */ /* Point to next element to produce/consume */ void *p_prod_elem; void *p_cons_elem; - enum ecore_chain_mode mode; - enum ecore_chain_use_mode intended_use; + /* Fastpath portions of the PBL [if exists] */ + + struct { + /* Table for keeping the virtual addresses of the chain pages, + * respectively to the physical addresses in the pbl table. + */ + void **pp_virt_addr_tbl; + + union { + struct ecore_chain_pbl_u16 u16; + struct ecore_chain_pbl_u32 u32; + } c; + } pbl; - enum ecore_chain_cnt_type cnt_type; union { struct ecore_chain_u16 chain16; struct ecore_chain_u32 chain32; } u; - u32 page_cnt; + /* Capacity counts only usable elements */ + u32 capacity; + u32 page_cnt; - /* Number of elements - capacity is for usable elements only, - * while size will contain total number of elements [for entire chain]. + /* A u8 would suffice for mode, but it would save as a lot of headaches + * on castings & defaults. */ - u32 capacity; - u32 size; + enum ecore_chain_mode mode; /* Elements information for fast calculations */ u16 elem_per_page; u16 elem_per_page_mask; - u16 elem_unusable; - u16 usable_per_page; u16 elem_size; u16 next_page_mask; + u16 usable_per_page; + u8 elem_unusable; + + u8 cnt_type; + + /* Slowpath of the chain - required for initialization and destruction, + * but isn't involved in regular functionality. + */ + + /* Base address of a pre-allocated buffer for pbl */ + struct { + dma_addr_t p_phys_table; + void *p_virt_table; + } pbl_sp; + + /* Address of first page of the chain - the address is required + * for fastpath operation [consume/produce] but only for the SINGLE + * flavour which isn't considered fastpath [== SPQ]. + */ + void *p_virt_addr; + dma_addr_t p_phys_addr; - struct ecore_chain_pbl pbl; + /* Total number of elements [for entire chain] */ + u32 size; + + u8 intended_use; + + /* TBD - do we really need this? Couldn't find usage for it */ + bool b_external_pbl; void *dp_ctx; }; @@ -128,8 +149,8 @@ struct ecore_chain { #define UNUSABLE_ELEMS_PER_PAGE(elem_size, mode) \ ((mode == ECORE_CHAIN_MODE_NEXT_PTR) ? \ - (1 + ((sizeof(struct ecore_chain_next) - 1) / \ - (elem_size))) : 0) + (u8)(1 + ((sizeof(struct ecore_chain_next) - 1) / \ + (elem_size))) : 0) #define USABLE_ELEMS_PER_PAGE(elem_size, mode) \ ((u32)(ELEMS_PER_PAGE(elem_size) - \ @@ -238,7 +259,7 @@ u16 ecore_chain_get_usable_per_page(struct ecore_chain *p_chain) } static OSAL_INLINE -u16 ecore_chain_get_unusable_per_page(struct ecore_chain *p_chain) +u8 ecore_chain_get_unusable_per_page(struct ecore_chain *p_chain) { return p_chain->elem_unusable; } @@ -256,7 +277,7 @@ static OSAL_INLINE u32 ecore_chain_get_page_cnt(struct ecore_chain *p_chain) static OSAL_INLINE dma_addr_t ecore_chain_get_pbl_phys(struct ecore_chain *p_chain) { - return p_chain->pbl.p_phys_table; + return p_chain->pbl_sp.p_phys_table; } /** @@ -281,9 +302,9 @@ ecore_chain_advance_page(struct ecore_chain *p_chain, void **p_next_elem, p_next = (struct ecore_chain_next *)(*p_next_elem); *p_next_elem = p_next->next_virt; if (is_chain_u16(p_chain)) - *(u16 *)idx_to_inc += p_chain->elem_unusable; + *(u16 *)idx_to_inc += (u16)p_chain->elem_unusable; else - *(u32 *)idx_to_inc += p_chain->elem_unusable; + *(u32 *)idx_to_inc += (u16)p_chain->elem_unusable; break; case ECORE_CHAIN_MODE_SINGLE: *p_next_elem = p_chain->p_virt_addr; @@ -384,7 +405,7 @@ static OSAL_INLINE void *ecore_chain_produce(struct ecore_chain *p_chain) if ((p_chain->u.chain16.prod_idx & p_chain->elem_per_page_mask) == p_chain->next_page_mask) { p_prod_idx = &p_chain->u.chain16.prod_idx; - p_prod_page_idx = &p_chain->pbl.u.pbl16.prod_page_idx; + p_prod_page_idx = &p_chain->pbl.c.u16.prod_page_idx; ecore_chain_advance_page(p_chain, &p_chain->p_prod_elem, p_prod_idx, p_prod_page_idx); } @@ -393,7 +414,7 @@ static OSAL_INLINE void *ecore_chain_produce(struct ecore_chain *p_chain) if ((p_chain->u.chain32.prod_idx & p_chain->elem_per_page_mask) == p_chain->next_page_mask) { p_prod_idx = &p_chain->u.chain32.prod_idx; - p_prod_page_idx = &p_chain->pbl.u.pbl32.prod_page_idx; + p_prod_page_idx = &p_chain->pbl.c.u32.prod_page_idx; ecore_chain_advance_page(p_chain, &p_chain->p_prod_elem, p_prod_idx, p_prod_page_idx); } @@ -458,7 +479,7 @@ static OSAL_INLINE void *ecore_chain_consume(struct ecore_chain *p_chain) if ((p_chain->u.chain16.cons_idx & p_chain->elem_per_page_mask) == p_chain->next_page_mask) { p_cons_idx = &p_chain->u.chain16.cons_idx; - p_cons_page_idx = &p_chain->pbl.u.pbl16.cons_page_idx; + p_cons_page_idx = &p_chain->pbl.c.u16.cons_page_idx; ecore_chain_advance_page(p_chain, &p_chain->p_cons_elem, p_cons_idx, p_cons_page_idx); } @@ -467,7 +488,7 @@ static OSAL_INLINE void *ecore_chain_consume(struct ecore_chain *p_chain) if ((p_chain->u.chain32.cons_idx & p_chain->elem_per_page_mask) == p_chain->next_page_mask) { p_cons_idx = &p_chain->u.chain32.cons_idx; - p_cons_page_idx = &p_chain->pbl.u.pbl32.cons_page_idx; + p_cons_page_idx = &p_chain->pbl.c.u32.cons_page_idx; ecore_chain_advance_page(p_chain, &p_chain->p_cons_elem, p_cons_idx, p_cons_page_idx); } @@ -503,7 +524,7 @@ static OSAL_INLINE void ecore_chain_reset(struct ecore_chain *p_chain) p_chain->p_prod_elem = p_chain->p_virt_addr; if (p_chain->mode == ECORE_CHAIN_MODE_PBL) { - /* Use (page_cnt - 1) as a reset value for the prod/cons page's + /* Use "page_cnt-1" as a reset value for the prod/cons page's * indices, to avoid unnecessary page advancing on the first * call to ecore_chain_produce/consume. Instead, the indices * will be advanced to page_cnt and then will be wrapped to 0. @@ -511,25 +532,26 @@ static OSAL_INLINE void ecore_chain_reset(struct ecore_chain *p_chain) u32 reset_val = p_chain->page_cnt - 1; if (is_chain_u16(p_chain)) { - p_chain->pbl.u.pbl16.prod_page_idx = (u16)reset_val; - p_chain->pbl.u.pbl16.cons_page_idx = (u16)reset_val; + p_chain->pbl.c.u16.prod_page_idx = (u16)reset_val; + p_chain->pbl.c.u16.cons_page_idx = (u16)reset_val; } else { - p_chain->pbl.u.pbl32.prod_page_idx = reset_val; - p_chain->pbl.u.pbl32.cons_page_idx = reset_val; + p_chain->pbl.c.u32.prod_page_idx = reset_val; + p_chain->pbl.c.u32.cons_page_idx = reset_val; } } switch (p_chain->intended_use) { - case ECORE_CHAIN_USE_TO_CONSUME_PRODUCE: - case ECORE_CHAIN_USE_TO_PRODUCE: - /* Do nothing */ - break; - case ECORE_CHAIN_USE_TO_CONSUME: - /* produce empty elements */ - for (i = 0; i < p_chain->capacity; i++) + /* produce empty elements */ + for (i = 0; i < p_chain->capacity; i++) ecore_chain_recycle_consumed(p_chain); - break; + break; + + case ECORE_CHAIN_USE_TO_CONSUME_PRODUCE: + case ECORE_CHAIN_USE_TO_PRODUCE: + default: + /* Do nothing */ + break; } } @@ -556,9 +578,9 @@ ecore_chain_init_params(struct ecore_chain *p_chain, u32 page_cnt, u8 elem_size, p_chain->p_virt_addr = OSAL_NULL; p_chain->p_phys_addr = 0; p_chain->elem_size = elem_size; - p_chain->intended_use = intended_use; + p_chain->intended_use = (u8)intended_use; p_chain->mode = mode; - p_chain->cnt_type = cnt_type; + p_chain->cnt_type = (u8)cnt_type; p_chain->elem_per_page = ELEMS_PER_PAGE(elem_size); p_chain->usable_per_page = USABLE_ELEMS_PER_PAGE(elem_size, mode); @@ -570,9 +592,9 @@ ecore_chain_init_params(struct ecore_chain *p_chain, u32 page_cnt, u8 elem_size, p_chain->page_cnt = page_cnt; p_chain->capacity = p_chain->usable_per_page * page_cnt; p_chain->size = p_chain->elem_per_page * page_cnt; - - p_chain->pbl.p_phys_table = 0; - p_chain->pbl.p_virt_table = OSAL_NULL; + p_chain->b_external_pbl = false; + p_chain->pbl_sp.p_phys_table = 0; + p_chain->pbl_sp.p_virt_table = OSAL_NULL; p_chain->pbl.pp_virt_addr_tbl = OSAL_NULL; p_chain->dp_ctx = dp_ctx; @@ -616,8 +638,8 @@ static OSAL_INLINE void ecore_chain_init_pbl_mem(struct ecore_chain *p_chain, dma_addr_t p_phys_pbl, void **pp_virt_addr_tbl) { - p_chain->pbl.p_phys_table = p_phys_pbl; - p_chain->pbl.p_virt_table = p_virt_pbl; + p_chain->pbl_sp.p_phys_table = p_phys_pbl; + p_chain->pbl_sp.p_virt_table = p_virt_pbl; p_chain->pbl.pp_virt_addr_tbl = pp_virt_addr_tbl; } @@ -702,6 +724,21 @@ out: static OSAL_INLINE void ecore_chain_set_prod(struct ecore_chain *p_chain, u32 prod_idx, void *p_prod_elem) { + if (p_chain->mode == ECORE_CHAIN_MODE_PBL) { + /* Use "prod_idx-1" since ecore_chain_produce() advances the + * page index before the producer index when getting to + * "next_page_mask". + */ + u32 elem_idx = + (prod_idx - 1 + p_chain->capacity) % p_chain->capacity; + u32 page_idx = elem_idx / p_chain->elem_per_page; + + if (is_chain_u16(p_chain)) + p_chain->pbl.c.u16.prod_page_idx = (u16)page_idx; + else + p_chain->pbl.c.u32.prod_page_idx = page_idx; + } + if (is_chain_u16(p_chain)) p_chain->u.chain16.prod_idx = (u16)prod_idx; else @@ -709,6 +746,38 @@ static OSAL_INLINE void ecore_chain_set_prod(struct ecore_chain *p_chain, p_chain->p_prod_elem = p_prod_elem; } +/** + * @brief ecore_chain_set_cons - sets the cons to the given value + * + * @param cons_idx + * @param p_cons_elem + */ +static OSAL_INLINE void ecore_chain_set_cons(struct ecore_chain *p_chain, + u32 cons_idx, void *p_cons_elem) +{ + if (p_chain->mode == ECORE_CHAIN_MODE_PBL) { + /* Use "cons_idx-1" since ecore_chain_consume() advances the + * page index before the consumer index when getting to + * "next_page_mask". + */ + u32 elem_idx = + (cons_idx - 1 + p_chain->capacity) % p_chain->capacity; + u32 page_idx = elem_idx / p_chain->elem_per_page; + + if (is_chain_u16(p_chain)) + p_chain->pbl.c.u16.cons_page_idx = (u16)page_idx; + else + p_chain->pbl.c.u32.cons_page_idx = page_idx; + } + + if (is_chain_u16(p_chain)) + p_chain->u.chain16.cons_idx = (u16)cons_idx; + else + p_chain->u.chain32.cons_idx = cons_idx; + + p_chain->p_cons_elem = p_cons_elem; +} + /** * @brief ecore_chain_pbl_zero_mem - set chain memory to 0 *