aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDmitry Bogdanov <dmitry.bogdanov@aquantia.com>2018-11-09 06:53:57 -0500
committerDavid S. Miller <davem@davemloft.net>2018-11-09 18:38:10 -0500
commit7a1bb49461b12b2e6332a4d054256835f45203f3 (patch)
tree36f64e4609d757c18250932bde201f1c1ebcbb97 /drivers/net
parent35e8e8b45d31bec34379dd36e7b71448e003efb2 (diff)
net: aquantia: fix potential IOMMU fault after driver unbind
IOMMU fault may occurr on unbind/bind or if_down/if_up sequence. Although driver disables the rings on down, this is not enough. Due to internal HW design, during subsequent initialization NIC sometimes may reuse RX descriptors cache and write to the host memory from the descriptor cache. That's get catched by IOMMU on host. This patch invalidates the descriptor cache in NIC on interface down to prevent writing to the cached descriptors and to the memory pointed in those descriptors. Signed-off-by: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c6
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c8
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h3
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h18
4 files changed, 35 insertions, 0 deletions
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 119265762b0c..3aec56623bf5 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
@@ -920,6 +920,12 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self)
920static int hw_atl_b0_hw_stop(struct aq_hw_s *self) 920static int hw_atl_b0_hw_stop(struct aq_hw_s *self)
921{ 921{
922 hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); 922 hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK);
923
924 /* Invalidate Descriptor Cache to prevent writing to the cached
925 * descriptors and to the data pointer of those descriptors
926 */
927 hw_atl_rdm_rx_dma_desc_cache_init_set(self, 1);
928
923 return aq_hw_err_from_flags(self); 929 return aq_hw_err_from_flags(self);
924} 930}
925 931
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 be0a3a90dfad..5502ec5f0f69 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
@@ -619,6 +619,14 @@ void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, u32 rx_flow_ctl_mode
619 HW_ATL_RPB_RX_FC_MODE_SHIFT, rx_flow_ctl_mode); 619 HW_ATL_RPB_RX_FC_MODE_SHIFT, rx_flow_ctl_mode);
620} 620}
621 621
622void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init)
623{
624 aq_hw_write_reg_bit(aq_hw, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR,
625 HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK,
626 HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT,
627 init);
628}
629
622void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, 630void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw,
623 u32 rx_pkt_buff_size_per_tc, u32 buffer) 631 u32 rx_pkt_buff_size_per_tc, u32 buffer)
624{ 632{
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 7056c7342afc..41f239928c15 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
@@ -325,6 +325,9 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw,
325 u32 rx_pkt_buff_size_per_tc, 325 u32 rx_pkt_buff_size_per_tc,
326 u32 buffer); 326 u32 buffer);
327 327
328/* set rdm rx dma descriptor cache init */
329void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init);
330
328/* set rx xoff enable (per tc) */ 331/* set rx xoff enable (per tc) */
329void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc, 332void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc,
330 u32 buffer); 333 u32 buffer);
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 716674a9b729..a715fa317b1c 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
@@ -293,6 +293,24 @@
293/* default value of bitfield desc{d}_reset */ 293/* default value of bitfield desc{d}_reset */
294#define HW_ATL_RDM_DESCDRESET_DEFAULT 0x0 294#define HW_ATL_RDM_DESCDRESET_DEFAULT 0x0
295 295
296/* rdm_desc_init_i bitfield definitions
297 * preprocessor definitions for the bitfield rdm_desc_init_i.
298 * port="pif_rdm_desc_init_i"
299 */
300
301/* register address for bitfield rdm_desc_init_i */
302#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR 0x00005a00
303/* bitmask for bitfield rdm_desc_init_i */
304#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK 0xffffffff
305/* inverted bitmask for bitfield rdm_desc_init_i */
306#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSKN 0x00000000
307/* lower bit position of bitfield rdm_desc_init_i */
308#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT 0
309/* width of bitfield rdm_desc_init_i */
310#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_WIDTH 32
311/* default value of bitfield rdm_desc_init_i */
312#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_DEFAULT 0x0
313
296/* rx int_desc_wrb_en bitfield definitions 314/* rx int_desc_wrb_en bitfield definitions
297 * preprocessor definitions for the bitfield "int_desc_wrb_en". 315 * preprocessor definitions for the bitfield "int_desc_wrb_en".
298 * port="pif_rdm_int_desc_wrb_en_i" 316 * port="pif_rdm_int_desc_wrb_en_i"