History

Merge branch 'axienet-fixes'

Andy Chiu says: ==================== net: axienet: fix DMA Tx error We ran into multiple DMA TX errors while writing files over a network block device running on top of a DMA-connected AXI Ethernet device on 64-bit RISC-V machines. The errors indicated that the DMA had fetched a null descriptor and we found that the reason for this is that AXI DMA had unexpectedly processed a partially updated tail descriptor pointer. To fix it, we suggest that the driver should use one 64-bit write instead of two 32-bit writes to perform such update if possible. For those archectures where double-word load/stores are unavailable, e.g. 32-bit archectures, force a driver probe failure if the driver finds 64-bit capability on DMA. ====================

David S. Miller committed 4 years ago

Commit a7ffce92 parents a5b00f5 b690f8d2 files · +55 −24Browse files

Unified · Split

2 files
  1. drivers/net/ethernet/xilinx/xilinx_axienet.h +51 −0
  2. drivers/net/ethernet/xilinx/xilinx_axienet_main.c +4 −24
drivers/net/ethernet/xilinx/xilinx_axienet.h+51−0
@@ -547,6 +547,57 @@ static inline void axienet_iow(struct axienet_local *lp, off_t offset, · 546 unmodified lines
547 iowrite32(value, lp->regs + offset);547 iowrite32(value, lp->regs + offset);
548}548}
549 549
550/**
551 * axienet_dma_out32 - Memory mapped Axi DMA register write.
552 * @lp: Pointer to axienet local structure
553 * @reg: Address offset from the base address of the Axi DMA core
554 * @value: Value to be written into the Axi DMA register
555 *
556 * This function writes the desired value into the corresponding Axi DMA
557 * register.
558 */
559
560static inline void axienet_dma_out32(struct axienet_local *lp,
561 off_t reg, u32 value)
562{
563 iowrite32(value, lp->dma_regs + reg);
564}
565
566#ifdef CONFIG_64BIT
567/**
568 * axienet_dma_out64 - Memory mapped Axi DMA register write.
569 * @lp: Pointer to axienet local structure
570 * @reg: Address offset from the base address of the Axi DMA core
571 * @value: Value to be written into the Axi DMA register
572 *
573 * This function writes the desired value into the corresponding Axi DMA
574 * register.
575 */
576static inline void axienet_dma_out64(struct axienet_local *lp,
577 off_t reg, u64 value)
578{
579 iowrite64(value, lp->dma_regs + reg);
580}
581
582static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
583 dma_addr_t addr)
584{
585 if (lp->features & XAE_FEATURE_DMA_64BIT)
586 axienet_dma_out64(lp, reg, addr);
587 else
588 axienet_dma_out32(lp, reg, lower_32_bits(addr));
589}
590
591#else /* CONFIG_64BIT */
592
593static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
594 dma_addr_t addr)
595{
596 axienet_dma_out32(lp, reg, lower_32_bits(addr));
597}
598
599#endif /* CONFIG_64BIT */
600
550/* Function prototypes visible in xilinx_axienet_mdio.c for other files */601/* Function prototypes visible in xilinx_axienet_mdio.c for other files */
551int axienet_mdio_enable(struct axienet_local *lp);602int axienet_mdio_enable(struct axienet_local *lp);
552void axienet_mdio_disable(struct axienet_local *lp);603void axienet_mdio_disable(struct axienet_local *lp);
drivers/net/ethernet/xilinx/xilinx_axienet_main.c+4−24
@@ -133,30 +133,6 @@ static inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg) · 132 unmodified lines
133 return ioread32(lp->dma_regs + reg);133 return ioread32(lp->dma_regs + reg);
134}134}
135 135
136/**
137 * axienet_dma_out32 - Memory mapped Axi DMA register write.
138 * @lp: Pointer to axienet local structure
139 * @reg: Address offset from the base address of the Axi DMA core
140 * @value: Value to be written into the Axi DMA register
141 *
142 * This function writes the desired value into the corresponding Axi DMA
143 * register.
144 */
145static inline void axienet_dma_out32(struct axienet_local *lp,
146 off_t reg, u32 value)
147{
148 iowrite32(value, lp->dma_regs + reg);
149}
150
151static void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
152 dma_addr_t addr)
153{
154 axienet_dma_out32(lp, reg, lower_32_bits(addr));
155
156 if (lp->features & XAE_FEATURE_DMA_64BIT)
157 axienet_dma_out32(lp, reg + 4, upper_32_bits(addr));
158}
159
160static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr,136static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr,
161 struct axidma_bd *desc)137 struct axidma_bd *desc)
162{138{
@@ -2061,6 +2037,10 @@ static int axienet_probe(struct platform_device *pdev) · 1898 unmodified lines
2061 iowrite32(0x0, desc);2037 iowrite32(0x0, desc);
2062 }2038 }
2063 }2039 }
2040 if (!IS_ENABLED(CONFIG_64BIT) && lp->features & XAE_FEATURE_DMA_64BIT) {
2041 dev_err(&pdev->dev, "64-bit addressable DMA is not compatible with 32-bit archecture\n");
2042 goto cleanup_clk;
2043 }
2064 2044
2065 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width));2045 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width));
2066 if (ret) {2046 if (ret) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t