[PATCH] fec fix: Use OF 'ethernet' device as a provider of dma ops.

Grant Likely grant.likely at secretlab.ca
Sat Apr 4 01:18:30 EST 2009


This is already fixed in the netdev tree

g.

On Fri, Apr 3, 2009 at 8:16 AM, Grzegorz Bernacki <gjb at semihalf.com> wrote:
> 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 <gjb at 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
>
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.



More information about the Linuxppc-dev mailing list