[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