Commit 4ae0ff6 "powerpc: expect all devices calling dma ops to have archdata set" assumes that all devices use correct dma ops. However FEC uses dma ops from 'eth' device which doesn't have proper archdata. This patch makes FEC use dma operation from OF 'ethernet' device, similarly to what other drivers (like gianfar) do.
Signed-off-by: Grzegorz Bernacki <g...@semihalf.com> --- This is fix for not working FEC. Mounting root filesystem via NFS ends up with: Kernel BUG at c021b788 [verbose debug info unavailable] Oops: Exception in kernel mode, sig: 5 [#1] mpc5200-simple-platform Modules linked in: NIP: c021b788 LR: c021b758 CTR: 00000000 REGS: c3825d40 TRAP: 0700 Not tainted (2.6.29-07103-gd0b70e8) MSR: 00029032 <EE,ME,CE,IR,DR> CR: 42008048 XER: 20000000 TASK = c3820000[1] 'swapper' THREAD: c3824000 [...] drivers/net/fec_mpc52xx.c | 31 +++++++++++++++++++++---------- 1 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index cd8e98b..960b239 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -58,6 +58,8 @@ struct mpc52xx_fec_priv { spinlock_t lock; int msg_enable; + struct of_device *ofdev; + /* MDIO link details */ int phy_addr; unsigned int phy_speed; @@ -124,18 +126,23 @@ static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr) static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct bcom_task *s) { + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + while (!bcom_queue_empty(s)) { struct bcom_fec_bd *bd; struct sk_buff *skb; skb = bcom_retrieve_buffer(s, NULL, (struct bcom_bd **)&bd); - dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_FROM_DEVICE); + dma_unmap_single(&priv->ofdev->dev, bd->skb_pa, skb->len, + DMA_FROM_DEVICE); kfree_skb(skb); } } static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task *rxtsk) { + struct mpc52xx_fec_priv *priv = netdev_priv(dev); + while (!bcom_queue_full(rxtsk)) { struct sk_buff *skb; struct bcom_fec_bd *bd; @@ -150,8 +157,8 @@ static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task bd = (struct bcom_fec_bd *)bcom_prepare_next_buffer(rxtsk); bd->status = FEC_RX_BUFFER_SIZE; - bd->skb_pa = dma_map_single(&dev->dev, skb->data, - FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + bd->skb_pa = dma_map_single(&priv->ofdev->dev, skb->data, + FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); bcom_submit_next_buffer(rxtsk, skb); } @@ -388,7 +395,8 @@ static int mpc52xx_fec_hard_start_xmit(struct sk_buff *skb, struct net_device *d bcom_prepare_next_buffer(priv->tx_dmatsk); bd->status = skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX_BD_TC; - bd->skb_pa = dma_map_single(&dev->dev, skb->data, skb->len, DMA_TO_DEVICE); + bd->skb_pa = dma_map_single(&priv->ofdev->dev, skb->data, + skb->len, DMA_TO_DEVICE); bcom_submit_next_buffer(priv->tx_dmatsk, skb); @@ -430,7 +438,8 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id) struct bcom_fec_bd *bd; skb = bcom_retrieve_buffer(priv->tx_dmatsk, NULL, (struct bcom_bd **)&bd); - dma_unmap_single(&dev->dev, bd->skb_pa, skb->len, DMA_TO_DEVICE); + dma_unmap_single(&priv->ofdev->dev, bd->skb_pa, skb->len, + DMA_TO_DEVICE); dev_kfree_skb_irq(skb); } @@ -455,7 +464,8 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status, (struct bcom_bd **)&bd); - dma_unmap_single(&dev->dev, bd->skb_pa, rskb->len, DMA_FROM_DEVICE); + dma_unmap_single(&priv->ofdev->dev, bd->skb_pa, rskb->len, + DMA_FROM_DEVICE); /* Test for errors in received frame */ if (status & BCOM_FEC_RX_BD_ERRORS) { @@ -464,8 +474,9 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) bcom_prepare_next_buffer(priv->rx_dmatsk); bd->status = FEC_RX_BUFFER_SIZE; - bd->skb_pa = dma_map_single(&dev->dev, rskb->data, - FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); + bd->skb_pa = dma_map_single(&priv->ofdev->dev, + rskb->data, FEC_RX_BUFFER_SIZE, + DMA_FROM_DEVICE); bcom_submit_next_buffer(priv->rx_dmatsk, rskb); @@ -499,7 +510,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) bcom_prepare_next_buffer(priv->rx_dmatsk); bd->status = FEC_RX_BUFFER_SIZE; - bd->skb_pa = dma_map_single(&dev->dev, skb->data, + bd->skb_pa = dma_map_single(&priv->ofdev->dev, skb->data, FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE); bcom_submit_next_buffer(priv->rx_dmatsk, skb); @@ -910,7 +921,7 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) return -ENOMEM; priv = netdev_priv(ndev); - + priv->ofdev = op; /* Reserve FEC control zone */ rv = of_address_to_resource(op->node, 0, &mem); if (rv) { -- 1.5.2.2 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev