Commit 2d533a92 authored by Denis Bolotin's avatar Denis Bolotin Committed by David S. Miller

qed: Fix qed_chain_set_prod() for PBL chains with non power of 2 page count

In PBL chains with non power of 2 page count, the producer is not at the
beginning of the chain when index is 0 after a wrap. Therefore, after the
producer index wrap around, page index should be calculated more carefully.
Signed-off-by: 's avatarDenis Bolotin <dbolotin@marvell.com>
Signed-off-by: 's avatarAriel Elior <aelior@marvell.com>
Signed-off-by: 's avatarDavid S. Miller <davem@davemloft.net>
parent f8c468e8
......@@ -663,6 +663,37 @@ static inline void *qed_chain_get_last_elem(struct qed_chain *p_chain)
static inline void qed_chain_set_prod(struct qed_chain *p_chain,
u32 prod_idx, void *p_prod_elem)
{
if (p_chain->mode == QED_CHAIN_MODE_PBL) {
u32 cur_prod, page_mask, page_cnt, page_diff;
cur_prod = is_chain_u16(p_chain) ? p_chain->u.chain16.prod_idx :
p_chain->u.chain32.prod_idx;
/* Assume that number of elements in a page is power of 2 */
page_mask = ~p_chain->elem_per_page_mask;
/* Use "cur_prod - 1" and "prod_idx - 1" since producer index
* reaches the first element of next page before the page index
* is incremented. See qed_chain_produce().
* Index wrap around is not a problem because the difference
* between current and given producer indices is always
* positive and lower than the chain's capacity.
*/
page_diff = (((cur_prod - 1) & page_mask) -
((prod_idx - 1) & page_mask)) /
p_chain->elem_per_page;
page_cnt = qed_chain_get_page_cnt(p_chain);
if (is_chain_u16(p_chain))
p_chain->pbl.c.u16.prod_page_idx =
(p_chain->pbl.c.u16.prod_page_idx -
page_diff + page_cnt) % page_cnt;
else
p_chain->pbl.c.u32.prod_page_idx =
(p_chain->pbl.c.u32.prod_page_idx -
page_diff + page_cnt) % page_cnt;
}
if (is_chain_u16(p_chain))
p_chain->u.chain16.prod_idx = (u16) prod_idx;
else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment