linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] fec fix: Use OF 'ethernet' device as a provider of dma ops.
@ 2009-04-03 14:16 Grzegorz Bernacki
  2009-04-03 14:18 ` Grant Likely
  0 siblings, 1 reply; 2+ messages in thread
From: Grzegorz Bernacki @ 2009-04-03 14:16 UTC (permalink / raw)
  To: linuxppc-dev

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@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

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] fec fix: Use OF 'ethernet' device as a provider of dma ops.
  2009-04-03 14:16 [PATCH] fec fix: Use OF 'ethernet' device as a provider of dma ops Grzegorz Bernacki
@ 2009-04-03 14:18 ` Grant Likely
  0 siblings, 0 replies; 2+ messages in thread
From: Grant Likely @ 2009-04-03 14:18 UTC (permalink / raw)
  To: Grzegorz Bernacki; +Cc: linuxppc-dev

This is already fixed in the netdev tree

g.

On Fri, Apr 3, 2009 at 8:16 AM, Grzegorz Bernacki <gjb@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@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 =A0 Not tainted =A0(2.6.29-07103-gd0b70e8)
> MSR: 00029032 <EE,ME,CE,IR,DR> =A0CR: 42008048 =A0XER: 20000000
> TASK =3D c3820000[1] 'swapper' THREAD: c3824000
> [...]
>
> =A0drivers/net/fec_mpc52xx.c | =A0 31 +++++++++++++++++++++----------
> =A01 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 {
> =A0 =A0 =A0 =A0spinlock_t lock;
> =A0 =A0 =A0 =A0int msg_enable;
>
> + =A0 =A0 =A0 struct of_device *ofdev;
> +
> =A0 =A0 =A0 =A0/* MDIO link details */
> =A0 =A0 =A0 =A0int phy_addr;
> =A0 =A0 =A0 =A0unsigned int phy_speed;
> @@ -124,18 +126,23 @@ static int mpc52xx_fec_set_mac_address(struct net_d=
evice *dev, void *addr)
>
> =A0static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct=
 bcom_task *s)
> =A0{
> + =A0 =A0 =A0 struct mpc52xx_fec_priv *priv =3D netdev_priv(dev);
> +
> =A0 =A0 =A0 =A0while (!bcom_queue_empty(s)) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct bcom_fec_bd *bd;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct sk_buff *skb;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0skb =3D bcom_retrieve_buffer(s, NULL, (str=
uct bcom_bd **)&bd);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(&dev->dev, bd->skb_pa, skb=
->len, DMA_FROM_DEVICE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(&priv->ofdev->dev, bd->skb=
_pa, skb->len,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 DMA_FROM_DEVICE);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0kfree_skb(skb);
> =A0 =A0 =A0 =A0}
> =A0}
>
> =A0static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct=
 bcom_task *rxtsk)
> =A0{
> + =A0 =A0 =A0 struct mpc52xx_fec_priv *priv =3D netdev_priv(dev);
> +
> =A0 =A0 =A0 =A0while (!bcom_queue_full(rxtsk)) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct sk_buff *skb;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct bcom_fec_bd *bd;
> @@ -150,8 +157,8 @@ static int mpc52xx_fec_alloc_rx_buffers(struct net_de=
vice *dev, struct bcom_task
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bd =3D (struct bcom_fec_bd *)bcom_prepare_=
next_buffer(rxtsk);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bd->status =3D FEC_RX_BUFFER_SIZE;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 bd->skb_pa =3D dma_map_single(&dev->dev, sk=
b->data,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 FEC_RX_BUFF=
ER_SIZE, DMA_FROM_DEVICE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 bd->skb_pa =3D dma_map_single(&priv->ofdev-=
>dev, skb->data,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bcom_submit_next_buffer(rxtsk, skb);
> =A0 =A0 =A0 =A0}
> @@ -388,7 +395,8 @@ static int mpc52xx_fec_hard_start_xmit(struct sk_buff=
 *skb, struct net_device *d
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bcom_prepare_next_buffer(priv->tx_dmatsk);
>
> =A0 =A0 =A0 =A0bd->status =3D skb->len | BCOM_FEC_TX_BD_TFD | BCOM_FEC_TX=
_BD_TC;
> - =A0 =A0 =A0 bd->skb_pa =3D dma_map_single(&dev->dev, skb->data, skb->le=
n, DMA_TO_DEVICE);
> + =A0 =A0 =A0 bd->skb_pa =3D dma_map_single(&priv->ofdev->dev, skb->data,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 skb->len, DMA_TO_DEVICE);
>
> =A0 =A0 =A0 =A0bcom_submit_next_buffer(priv->tx_dmatsk, skb);
>
> @@ -430,7 +438,8 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, =
void *dev_id)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct bcom_fec_bd *bd;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0skb =3D bcom_retrieve_buffer(priv->tx_dmat=
sk, NULL,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(struct bc=
om_bd **)&bd);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(&dev->dev, bd->skb_pa, skb=
->len, DMA_TO_DEVICE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(&priv->ofdev->dev, bd->skb=
_pa, skb->len,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 DMA_TO_DEVICE);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dev_kfree_skb_irq(skb);
> =A0 =A0 =A0 =A0}
> @@ -455,7 +464,8 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, =
void *dev_id)
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0rskb =3D bcom_retrieve_buffer(priv->rx_dma=
tsk, &status,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(struct bc=
om_bd **)&bd);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(&dev->dev, bd->skb_pa, rsk=
b->len, DMA_FROM_DEVICE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dma_unmap_single(&priv->ofdev->dev, bd->skb=
_pa, rskb->len,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 DMA_FROM_DEVICE);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Test for errors in received frame */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (status & BCOM_FEC_RX_BD_ERRORS) {
> @@ -464,8 +474,9 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, =
void *dev_id)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bcom_prepa=
re_next_buffer(priv->rx_dmatsk);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bd->status =3D FEC_RX_BUFF=
ER_SIZE;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bd->skb_pa =3D dma_map_sing=
le(&dev->dev, rskb->data,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bd->skb_pa =3D dma_map_sing=
le(&priv->ofdev->dev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 rskb->data, FEC_RX_BUFFER_SIZE,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 DMA_FROM_DEVICE);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bcom_submit_next_buffer(pr=
iv->rx_dmatsk, rskb);
>
> @@ -499,7 +510,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, =
void *dev_id)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bcom_prepare_next_buffer(p=
riv->rx_dmatsk);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bd->status =3D FEC_RX_BUFFER_SIZE;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 bd->skb_pa =3D dma_map_single(&dev->dev, sk=
b->data,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 bd->skb_pa =3D dma_map_single(&priv->ofdev-=
>dev, skb->data,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0FEC_RX_BUF=
FER_SIZE, DMA_FROM_DEVICE);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bcom_submit_next_buffer(priv->rx_dmatsk, s=
kb);
> @@ -910,7 +921,7 @@ mpc52xx_fec_probe(struct of_device *op, const struct =
of_device_id *match)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -ENOMEM;
>
> =A0 =A0 =A0 =A0priv =3D netdev_priv(ndev);
> -
> + =A0 =A0 =A0 priv->ofdev =3D op;
> =A0 =A0 =A0 =A0/* Reserve FEC control zone */
> =A0 =A0 =A0 =A0rv =3D of_address_to_resource(op->node, 0, &mem);
> =A0 =A0 =A0 =A0if (rv) {
> --
> 1.5.2.2
>
>



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

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-04-03 14:30 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-03 14:16 [PATCH] fec fix: Use OF 'ethernet' device as a provider of dma ops Grzegorz Bernacki
2009-04-03 14:18 ` Grant Likely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).