| From 46a15c7cc0095ee249d9e3ea30590721826168e3 Mon Sep 17 00:00:00 2001 |
| From: Igor Russkikh <Igor.Russkikh@aquantia.com> |
| Date: Fri, 11 Oct 2019 13:45:20 +0000 |
| Subject: [PATCH] net: aquantia: when cleaning hw cache it should be toggled |
| |
| commit ed4d81c4b3f28ccf624f11fd66f67aec5b58859c upstream. |
| |
| >From HW specification to correctly reset HW caches (this is a required |
| workaround when stopping the device), register bit should actually |
| be toggled. |
| |
| It was previosly always just set. Due to the way driver stops HW this |
| never actually caused any issues, but it still may, so cleaning this up. |
| |
| Fixes: 7a1bb49461b1 ("net: aquantia: fix potential IOMMU fault after driver unbind") |
| Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c |
| index 13ac2661a473..23e113fa2986 100644 |
| --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c |
| +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c |
| @@ -938,14 +938,26 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) |
| |
| static int hw_atl_b0_hw_stop(struct aq_hw_s *self) |
| { |
| + int err; |
| + u32 val; |
| + |
| hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); |
| |
| /* Invalidate Descriptor Cache to prevent writing to the cached |
| * descriptors and to the data pointer of those descriptors |
| */ |
| - hw_atl_rdm_rx_dma_desc_cache_init_set(self, 1); |
| + hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); |
| |
| - return aq_hw_err_from_flags(self); |
| + err = aq_hw_err_from_flags(self); |
| + |
| + if (err) |
| + goto err_exit; |
| + |
| + readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, |
| + self, val, val == 1, 1000U, 10000U); |
| + |
| +err_exit: |
| + return err; |
| } |
| |
| static int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, |
| diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c |
| index 451529069f28..bf6673aab7a4 100644 |
| --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c |
| +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c |
| @@ -606,12 +606,25 @@ void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, u32 rx_flow_ctl_mode |
| HW_ATL_RPB_RX_FC_MODE_SHIFT, rx_flow_ctl_mode); |
| } |
| |
| -void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init) |
| +void hw_atl_rdm_rx_dma_desc_cache_init_tgl(struct aq_hw_s *aq_hw) |
| { |
| + u32 val; |
| + |
| + val = aq_hw_read_reg_bit(aq_hw, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR, |
| + HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK, |
| + HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT); |
| + |
| aq_hw_write_reg_bit(aq_hw, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR, |
| HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK, |
| HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT, |
| - init); |
| + val ^ 1); |
| +} |
| + |
| +u32 hw_atl_rdm_rx_dma_desc_cache_init_done_get(struct aq_hw_s *aq_hw) |
| +{ |
| + return aq_hw_read_reg_bit(aq_hw, RDM_RX_DMA_DESC_CACHE_INIT_DONE_ADR, |
| + RDM_RX_DMA_DESC_CACHE_INIT_DONE_MSK, |
| + RDM_RX_DMA_DESC_CACHE_INIT_DONE_SHIFT); |
| } |
| |
| void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, |
| diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h |
| index 34b42ce43512..91cbe32ec28d 100644 |
| --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h |
| +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h |
| @@ -313,8 +313,11 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, |
| u32 rx_pkt_buff_size_per_tc, |
| u32 buffer); |
| |
| -/* set rdm rx dma descriptor cache init */ |
| -void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init); |
| +/* toggle rdm rx dma descriptor cache init */ |
| +void hw_atl_rdm_rx_dma_desc_cache_init_tgl(struct aq_hw_s *aq_hw); |
| + |
| +/* get rdm rx dma descriptor cache init done */ |
| +u32 hw_atl_rdm_rx_dma_desc_cache_init_done_get(struct aq_hw_s *aq_hw); |
| |
| /* set rx xoff enable (per tc) */ |
| void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc, |
| diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h |
| index fc1446f737bb..436e98980012 100644 |
| --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h |
| +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h |
| @@ -318,6 +318,25 @@ |
| /* default value of bitfield rdm_desc_init_i */ |
| #define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_DEFAULT 0x0 |
| |
| +/* rdm_desc_init_done_i bitfield definitions |
| + * preprocessor definitions for the bitfield rdm_desc_init_done_i. |
| + * port="pif_rdm_desc_init_done_i" |
| + */ |
| + |
| +/* register address for bitfield rdm_desc_init_done_i */ |
| +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_ADR 0x00005a10 |
| +/* bitmask for bitfield rdm_desc_init_done_i */ |
| +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_MSK 0x00000001U |
| +/* inverted bitmask for bitfield rdm_desc_init_done_i */ |
| +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_MSKN 0xfffffffe |
| +/* lower bit position of bitfield rdm_desc_init_done_i */ |
| +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_SHIFT 0U |
| +/* width of bitfield rdm_desc_init_done_i */ |
| +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_WIDTH 1 |
| +/* default value of bitfield rdm_desc_init_done_i */ |
| +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_DEFAULT 0x0 |
| + |
| + |
| /* rx int_desc_wrb_en bitfield definitions |
| * preprocessor definitions for the bitfield "int_desc_wrb_en". |
| * port="pif_rdm_int_desc_wrb_en_i" |
| -- |
| 2.7.4 |
| |