mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 21:02:19 +00:00
net: axienet: make the 64b addresable DMA depends on 64b archectures
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> Reviewed-by: Greentime Hu <greentime.hu@sifive.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a5b00f5b78
commit
00be43a74c
@ -547,6 +547,42 @@ static inline void axienet_iow(struct axienet_local *lp, off_t offset,
|
|||||||
iowrite32(value, lp->regs + 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 */
|
/* Function prototypes visible in xilinx_axienet_mdio.c for other files */
|
||||||
int axienet_mdio_enable(struct axienet_local *lp);
|
int axienet_mdio_enable(struct axienet_local *lp);
|
||||||
void axienet_mdio_disable(struct axienet_local *lp);
|
void axienet_mdio_disable(struct axienet_local *lp);
|
||||||
|
@ -133,30 +133,6 @@ static inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg)
|
|||||||
return ioread32(lp->dma_regs + 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,
|
static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr,
|
||||||
struct axidma_bd *desc)
|
struct axidma_bd *desc)
|
||||||
{
|
{
|
||||||
@ -2061,6 +2037,10 @@ static int axienet_probe(struct platform_device *pdev)
|
|||||||
iowrite32(0x0, desc);
|
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));
|
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(addr_width));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
Loading…
Reference in New Issue
Block a user