| From 68b92e1333c98d90a8b9144708c1784c6a337188 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 23 Jun 2020 16:51:29 +0300 |
| Subject: net: qed: fix left elements count calculation |
| |
| From: Alexander Lobakin <alobakin@marvell.com> |
| |
| [ Upstream commit 97dd1abd026ae4e6a82fa68645928404ad483409 ] |
| |
| qed_chain_get_element_left{,_u32} returned 0 when the difference |
| between producer and consumer page count was equal to the total |
| page count. |
| Fix this by conditional expanding of producer value (vs |
| unconditional). This allowed to eliminate normalizaton against |
| total page count, which was the cause of this bug. |
| |
| Misc: replace open-coded constants with common defines. |
| |
| Fixes: a91eb52abb50 ("qed: Revisit chain implementation") |
| Signed-off-by: Alexander Lobakin <alobakin@marvell.com> |
| Signed-off-by: Igor Russkikh <irusskikh@marvell.com> |
| Signed-off-by: Michal Kalderon <michal.kalderon@marvell.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| include/linux/qed/qed_chain.h | 26 ++++++++++++++++---------- |
| 1 file changed, 16 insertions(+), 10 deletions(-) |
| |
| diff --git a/include/linux/qed/qed_chain.h b/include/linux/qed/qed_chain.h |
| index 72d88cf3ca25b..5a215da57b55a 100644 |
| --- a/include/linux/qed/qed_chain.h |
| +++ b/include/linux/qed/qed_chain.h |
| @@ -155,28 +155,34 @@ static inline u32 qed_chain_get_cons_idx_u32(struct qed_chain *p_chain) |
| |
| static inline u16 qed_chain_get_elem_left(struct qed_chain *p_chain) |
| { |
| + u16 elem_per_page = p_chain->elem_per_page; |
| + u32 prod = p_chain->u.chain16.prod_idx; |
| + u32 cons = p_chain->u.chain16.cons_idx; |
| u16 used; |
| |
| - used = (u16) (((u32)0x10000 + |
| - (u32)p_chain->u.chain16.prod_idx) - |
| - (u32)p_chain->u.chain16.cons_idx); |
| + if (prod < cons) |
| + prod += (u32)U16_MAX + 1; |
| + |
| + used = (u16)(prod - cons); |
| if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR) |
| - used -= p_chain->u.chain16.prod_idx / p_chain->elem_per_page - |
| - p_chain->u.chain16.cons_idx / p_chain->elem_per_page; |
| + used -= prod / elem_per_page - cons / elem_per_page; |
| |
| return (u16)(p_chain->capacity - used); |
| } |
| |
| static inline u32 qed_chain_get_elem_left_u32(struct qed_chain *p_chain) |
| { |
| + u16 elem_per_page = p_chain->elem_per_page; |
| + u64 prod = p_chain->u.chain32.prod_idx; |
| + u64 cons = p_chain->u.chain32.cons_idx; |
| u32 used; |
| |
| - used = (u32) (((u64)0x100000000ULL + |
| - (u64)p_chain->u.chain32.prod_idx) - |
| - (u64)p_chain->u.chain32.cons_idx); |
| + if (prod < cons) |
| + prod += (u64)U32_MAX + 1; |
| + |
| + used = (u32)(prod - cons); |
| if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR) |
| - used -= p_chain->u.chain32.prod_idx / p_chain->elem_per_page - |
| - p_chain->u.chain32.cons_idx / p_chain->elem_per_page; |
| + used -= (u32)(prod / elem_per_page - cons / elem_per_page); |
| |
| return p_chain->capacity - used; |
| } |
| -- |
| 2.25.1 |
| |