Skip to content

Commit

Permalink
net: axienet: make the 64b addresable DMA depends on 64b archectures
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reported-by: Max Hsu <[email protected]>
Reviewed-by: Greentime Hu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
AndybnACT authored and davem330 committed Jun 13, 2022
1 parent a5b00f5 commit 00be43a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 24 deletions.
36 changes: 36 additions & 0 deletions drivers/net/ethernet/xilinx/xilinx_axienet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 4 additions & 24 deletions drivers/net/ethernet/xilinx/xilinx_axienet_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 00be43a

Please sign in to comment.