Message ID | 20220613034202.3777248-2-andy.chiu@sifive.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | net: axienet: fix DMA Tx error | expand |
Reviewed-by: Greentime Hu <greentime.hu@sifive.com> On Mon, Jun 13, 2022 at 11:45 AM Andy Chiu <andy.chiu@sifive.com> wrote: > > Currently it is not safe to config the IP as 64-bit addressable on 32-bit > archectures, which cannot perform a double-word store on its descriptor > pointers. The pointer is 64-bit wide if the IP is configured as 64-bit, > and the device would process the partially updated pointer on some > states if the pointer was updated via two store-words. To prevent such > condition, we force a probe fail if we discover that the IP has 64-bit > capability but it is not running on a 64-Bit kernel. > > This is a series of patch (1/2). The next patch must be applied in order > to make 64b DMA safe on 64b archectures. > > Signed-off-by: Andy Chiu <andy.chiu@sifive.com> > Reported-by: Max Hsu <max.hsu@sifive.com> > --- > drivers/net/ethernet/xilinx/xilinx_axienet.h | 36 +++++++++++++++++++ > .../net/ethernet/xilinx/xilinx_axienet_main.c | 28 +++------------ > 2 files changed, 40 insertions(+), 24 deletions(-) > > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h > index 4225efbeda3d..6c95676ba172 100644 > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h > @@ -547,6 +547,42 @@ static inline void axienet_iow(struct axienet_local *lp, off_t offset, > iowrite32(value, lp->regs + offset); > } > > +/** > + * axienet_dma_out32 - Memory mapped Axi DMA register write. > + * @lp: Pointer to axienet local structure > + * @reg: Address offset from the base address of the Axi DMA core > + * @value: Value to be written into the Axi DMA register > + * > + * This function writes the desired value into the corresponding Axi DMA > + * register. > + */ > + > +static inline void axienet_dma_out32(struct axienet_local *lp, > + off_t reg, u32 value) > +{ > + iowrite32(value, lp->dma_regs + reg); > +} > + > +#ifdef CONFIG_64BIT > +static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg, > + dma_addr_t addr) > +{ > + axienet_dma_out32(lp, reg, lower_32_bits(addr)); > + > + if (lp->features & XAE_FEATURE_DMA_64BIT) > + axienet_dma_out32(lp, reg + 4, upper_32_bits(addr)); > +} > + > +#else /* CONFIG_64BIT */ > + > +static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg, > + dma_addr_t addr) > +{ > + axienet_dma_out32(lp, reg, lower_32_bits(addr)); > +} > + > +#endif /* CONFIG_64BIT */ > + > /* Function prototypes visible in xilinx_axienet_mdio.c for other files */ > int axienet_mdio_enable(struct axienet_local *lp); > void axienet_mdio_disable(struct axienet_local *lp); > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > index 93c9f305bba4..fa7bcd2c1892 100644 > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c > @@ -133,30 +133,6 @@ static inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg) > return ioread32(lp->dma_regs + reg); > } > > -/** > - * axienet_dma_out32 - Memory mapped Axi DMA register write. > - * @lp: Pointer to axienet local structure > - * @reg: Address offset from the base address of the Axi DMA core > - * @value: Value to be written into the Axi DMA register > - * > - * This function writes the desired value into the corresponding Axi DMA > - * register. > - */ > -static inline void axienet_dma_out32(struct axienet_local *lp, > - off_t reg, u32 value) > -{ > - iowrite32(value, lp->dma_regs + reg); > -} > - > -static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg, > - dma_addr_t addr) > -{ > - axienet_dma_out32(lp, reg, lower_32_bits(addr)); > - > - if (lp->features & XAE_FEATURE_DMA_64BIT) > - axienet_dma_out32(lp, reg + 4, upper_32_bits(addr)); > -} > - > static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr, > struct axidma_bd *desc) > { > @@ -2061,6 +2037,10 @@ static int axienet_probe(struct platform_device *pdev) > iowrite32(0x0, desc); > } > } > + if (!IS_ENABLED(CONFIG_64BIT) && lp->features & XAE_FEATURE_DMA_64BIT) { > + dev_err(&pdev->dev, "64-bit addressable DMA is not compatible with 32-bit archecture\n"); > + goto cleanup_clk; > + } > > ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width)); > if (ret) { > -- > 2.36.0 >
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index 4225efbeda3d..6c95676ba172 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -547,6 +547,42 @@ static inline void axienet_iow(struct axienet_local *lp, off_t offset, iowrite32(value, lp->regs + offset); } +/** + * axienet_dma_out32 - Memory mapped Axi DMA register write. + * @lp: Pointer to axienet local structure + * @reg: Address offset from the base address of the Axi DMA core + * @value: Value to be written into the Axi DMA register + * + * This function writes the desired value into the corresponding Axi DMA + * register. + */ + +static inline void axienet_dma_out32(struct axienet_local *lp, + off_t reg, u32 value) +{ + iowrite32(value, lp->dma_regs + reg); +} + +#ifdef CONFIG_64BIT +static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg, + dma_addr_t addr) +{ + axienet_dma_out32(lp, reg, lower_32_bits(addr)); + + if (lp->features & XAE_FEATURE_DMA_64BIT) + axienet_dma_out32(lp, reg + 4, upper_32_bits(addr)); +} + +#else /* CONFIG_64BIT */ + +static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg, + dma_addr_t addr) +{ + axienet_dma_out32(lp, reg, lower_32_bits(addr)); +} + +#endif /* CONFIG_64BIT */ + /* Function prototypes visible in xilinx_axienet_mdio.c for other files */ int axienet_mdio_enable(struct axienet_local *lp); void axienet_mdio_disable(struct axienet_local *lp); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 93c9f305bba4..fa7bcd2c1892 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -133,30 +133,6 @@ static inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg) return ioread32(lp->dma_regs + reg); } -/** - * axienet_dma_out32 - Memory mapped Axi DMA register write. - * @lp: Pointer to axienet local structure - * @reg: Address offset from the base address of the Axi DMA core - * @value: Value to be written into the Axi DMA register - * - * This function writes the desired value into the corresponding Axi DMA - * register. - */ -static inline void axienet_dma_out32(struct axienet_local *lp, - off_t reg, u32 value) -{ - iowrite32(value, lp->dma_regs + reg); -} - -static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg, - dma_addr_t addr) -{ - axienet_dma_out32(lp, reg, lower_32_bits(addr)); - - if (lp->features & XAE_FEATURE_DMA_64BIT) - axienet_dma_out32(lp, reg + 4, upper_32_bits(addr)); -} - static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr, struct axidma_bd *desc) { @@ -2061,6 +2037,10 @@ static int axienet_probe(struct platform_device *pdev) iowrite32(0x0, desc); } } + if (!IS_ENABLED(CONFIG_64BIT) && lp->features & XAE_FEATURE_DMA_64BIT) { + dev_err(&pdev->dev, "64-bit addressable DMA is not compatible with 32-bit archecture\n"); + goto cleanup_clk; + } ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width)); if (ret) {
Currently it is not safe to config the IP as 64-bit addressable on 32-bit archectures, which cannot perform a double-word store on its descriptor pointers. The pointer is 64-bit wide if the IP is configured as 64-bit, and the device would process the partially updated pointer on some states if the pointer was updated via two store-words. To prevent such condition, we force a probe fail if we discover that the IP has 64-bit capability but it is not running on a 64-Bit kernel. This is a series of patch (1/2). The next patch must be applied in order to make 64b DMA safe on 64b archectures. Signed-off-by: Andy Chiu <andy.chiu@sifive.com> Reported-by: Max Hsu <max.hsu@sifive.com> --- drivers/net/ethernet/xilinx/xilinx_axienet.h | 36 +++++++++++++++++++ .../net/ethernet/xilinx/xilinx_axienet_main.c | 28 +++------------ 2 files changed, 40 insertions(+), 24 deletions(-)