This is the first round of driver protability fixes and clean-up
with the main purpose to make gianfar portable on ARM, for the ARM
based SoC that integrates the eTSEC ethernet controller - "ls1021a".
The patches primarily address compile time errors, when compiling
gianfar on ARM. They replace PPC specific functions and macros
with architecture independent ones, solve arch specific header
inclusions, guard code that relates to PPC only, and even address
some simple endianess issues (see MAC address setup patch).
The patches addressing the bulk of remaining endianess issues,
like handling DMA fields (BD and FCB), will follow with the sencond
round.
These patches were verified on the ls1021a SoC.
Claudiu Manoil (8):
net/fsl_pq_mdio: Fix asm/ucc.h compile error for ARM
net/fsl_pq_mdio: Use ioread/iowrite32be() portable accessors
net/fsl_pq_mdio: Replace spin_event_timeout() with arch independent
gianfar: Include missing headers for ARM builds
gianfar: Exclude PPC specific errata handling from ARM builds
gianfar: Make MAC addr setup endian safe, cleanup
gianfar: Replace spin_event_timeout() with arch independent
gianfar: Replace eieio with wmb for non-PPC archs
drivers/net/ethernet/freescale/fsl_pq_mdio.c | 56 ++++++++++++++---------
drivers/net/ethernet/freescale/gianfar.c | 68 +++++++++++++++-------------
drivers/net/ethernet/freescale/gianfar.h | 31 +++++++++++++
3 files changed, 102 insertions(+), 53 deletions(-)
--
1.7.11.7
@@ -1762,26 +1762,32 @@ static void gfar_halt_nodisable(struct gfar_private *priv){structgfar__iomem*regs=priv->gfargrp[0].regs;u32tempval;+unsignedinttimeout;+intstopped;gfar_ints_disable(priv);+if(gfar_is_dma_stopped(priv))+return;+/* Stop the DMA, and wait for it to stop */tempval=gfar_read(®s->dmactrl);-if((tempval&(DMACTRL_GRS|DMACTRL_GTS))!=-(DMACTRL_GRS|DMACTRL_GTS)){-intret;--tempval|=(DMACTRL_GRS|DMACTRL_GTS);-gfar_write(®s->dmactrl,tempval);+tempval|=(DMACTRL_GRS|DMACTRL_GTS);+gfar_write(®s->dmactrl,tempval);-do{-ret=spin_event_timeout(((gfar_read(®s->ievent)&-(IEVENT_GRSC|IEVENT_GTSC))==-(IEVENT_GRSC|IEVENT_GTSC)),1000000,0);-if(!ret&&!(gfar_read(®s->ievent)&IEVENT_GRSC))-ret=__gfar_is_rx_idle(priv);-}while(!ret);+retry:+timeout=1000;+while(!(stopped=gfar_is_dma_stopped(priv))&&timeout){+cpu_relax();+timeout--;}++if(!timeout)+stopped=gfar_is_dma_stopped(priv);++if(!stopped&&!gfar_is_rx_dma_stopped(priv)&&+!__gfar_is_rx_idle(priv))+gotoretry;}/* Halt the receive and transmit queues */
@@ -107,14 +107,14 @@ static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum,u32status;/* Set the PHY address and the register address we want to write */-out_be32(®s->miimadd,(mii_id<<8)|regnum);+iowrite32be((mii_id<<8)|regnum,®s->miimadd);/* Write out the value we want */-out_be32(®s->miimcon,value);+iowrite32be(value,®s->miimcon);/* Wait for the transaction to finish */-status=spin_event_timeout(!(in_be32(®s->miimind)&MIIMIND_BUSY),-MII_TIMEOUT,0);+status=spin_event_timeout(!(ioread32be(®s->miimind)&+MIIMIND_BUSY),MII_TIMEOUT,0);returnstatus?0:-ETIMEDOUT;}
@@ -137,21 +137,21 @@ static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)u16value;/* Set the PHY address and the register address we want to read */-out_be32(®s->miimadd,(mii_id<<8)|regnum);+iowrite32be((mii_id<<8)|regnum,®s->miimadd);/* Clear miimcom, and then initiate a read */-out_be32(®s->miimcom,0);-out_be32(®s->miimcom,MII_READ_COMMAND);+iowrite32be(0,®s->miimcom);+iowrite32be(MII_READ_COMMAND,®s->miimcom);/* Wait for the transaction to finish, normally less than 100us */-status=spin_event_timeout(!(in_be32(®s->miimind)&+status=spin_event_timeout(!(ioread32be(®s->miimind)&(MIIMIND_NOTVALID|MIIMIND_BUSY)),MII_TIMEOUT,0);if(!status)return-ETIMEDOUT;/* Grab the value of the register from miimstat */-value=in_be32(®s->miimstat);+value=ioread32be(®s->miimstat);dev_dbg(&bus->dev,"read %04x from address %x/%x\n",value,mii_id,regnum);returnvalue;
@@ -167,14 +167,14 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)mutex_lock(&bus->mdio_lock);/* Reset the management interface */-out_be32(®s->miimcfg,MIIMCFG_RESET);+iowrite32be(MIIMCFG_RESET,®s->miimcfg);/* Setup the MII Mgmt clock speed */-out_be32(®s->miimcfg,MIIMCFG_INIT_VALUE);+iowrite32be(MIIMCFG_INIT_VALUE,®s->miimcfg);/* Wait until the bus is free */-status=spin_event_timeout(!(in_be32(®s->miimind)&MIIMIND_BUSY),-MII_TIMEOUT,0);+status=spin_event_timeout(!(ioread32be(®s->miimind)&+MIIMIND_BUSY),MII_TIMEOUT,0);mutex_unlock(&bus->mdio_lock);
@@ -435,7 +435,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)tbipa=data->get_tbipa(priv->map);-out_be32(tbipa,be32_to_cpup(prop));+iowrite32be(be32_to_cpup(prop),tbipa);}}
Include linux/of_address.h for of_iomap() and linux/of_irq.h
for irq_of_parse_and_map().
This wasn't an issue for PPC, because these were implicitly
included from asm/prom.h (via linux/of.h) for PPC builds only.
ARM builds need these includes explicitly.
Signed-off-by: Claudiu Manoil <redacted>
---
drivers/net/ethernet/freescale/gianfar.c | 2 ++
1 file changed, 2 insertions(+)
@@ -104,7 +104,7 @@ static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum,{structfsl_pq_mdio_priv*priv=bus->priv;structfsl_pq_mii__iomem*regs=priv->regs;-u32status;+unsignedinttimeout;/* Set the PHY address and the register address we want to write */iowrite32be((mii_id<<8)|regnum,®s->miimadd);
@@ -113,10 +113,13 @@ static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum,iowrite32be(value,®s->miimcon);/* Wait for the transaction to finish */-status=spin_event_timeout(!(ioread32be(®s->miimind)&-MIIMIND_BUSY),MII_TIMEOUT,0);+timeout=MII_TIMEOUT;+while((ioread32be(®s->miimind)&MIIMIND_BUSY)&&timeout){+cpu_relax();+timeout--;+}-returnstatus?0:-ETIMEDOUT;+returntimeout?0:-ETIMEDOUT;}/*
@@ -133,7 +136,7 @@ static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum){structfsl_pq_mdio_priv*priv=bus->priv;structfsl_pq_mii__iomem*regs=priv->regs;-u32status;+unsignedinttimeout;u16value;/* Set the PHY address and the register address we want to read */
@@ -144,10 +147,14 @@ static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)iowrite32be(MII_READ_COMMAND,®s->miimcom);/* Wait for the transaction to finish, normally less than 100us */-status=spin_event_timeout(!(ioread32be(®s->miimind)&-(MIIMIND_NOTVALID|MIIMIND_BUSY)),-MII_TIMEOUT,0);-if(!status)+timeout=MII_TIMEOUT;+while((ioread32be(®s->miimind)&+(MIIMIND_NOTVALID|MIIMIND_BUSY))&&timeout){+cpu_relax();+timeout--;+}++if(!timeout)return-ETIMEDOUT;/* Grab the value of the register from miimstat */
@@ -162,7 +169,7 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus){structfsl_pq_mdio_priv*priv=bus->priv;structfsl_pq_mii__iomem*regs=priv->regs;-u32status;+unsignedinttimeout;mutex_lock(&bus->mdio_lock);
@@ -173,12 +180,15 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)iowrite32be(MIIMCFG_INIT_VALUE,®s->miimcfg);/* Wait until the bus is free */-status=spin_event_timeout(!(ioread32be(®s->miimind)&-MIIMIND_BUSY),MII_TIMEOUT,0);+timeout=MII_TIMEOUT;+while((ioread32be(®s->miimind)&MIIMIND_BUSY)&&timeout){+cpu_relax();+timeout--;+}mutex_unlock(&bus->mdio_lock);-if(!status){+if(!timeout){dev_err(&bus->dev,"timeout waiting for MII bus\n");return-EBUSY;}
This excludes the PPC specific instructions for PPC based SoC
(MPC85xx family) version identification from ARM builds.
The PPC specific macro mfspr() from asm/reg.h is not defined
by the ARM architecture.
Signed-off-by: Claudiu Manoil <redacted>
---
drivers/net/ethernet/freescale/gianfar.c | 6 ++++++
1 file changed, 6 insertions(+)
Replace PPC specific eieio() with arch independent wmb()
for other architectures, i.e. ARM.
The eieio() macro is not defined on ARM and generates
build error.
Signed-off-by: Claudiu Manoil <redacted>
---
drivers/net/ethernet/freescale/gianfar.c | 13 +++----------
drivers/net/ethernet/freescale/gianfar.h | 16 ++++++++++++++++
2 files changed, 19 insertions(+), 10 deletions(-)
@@ -2371,18 +2371,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)*/spin_lock_irqsave(&tx_queue->txlock,flags);-/* The powerpc-specific eieio() is used, as wmb() has too strong-*semantics(itrequiressynchronizationbetweencacheableand-*uncacheablemappings,whicheieiodoesn'tprovideandwhichwe-*don'tneed),thusrequiringamoreexpensivesyncinstruction.At-*somepoint,thesetofarchitecture-independentbarrierfunctions-*shouldbeexpandedtoincludeweakerbarriers.-*/-eieio();+gfar_wmb();txbdp_start->lstatus=lstatus;-eieio();/* force lstatus write before tx_skbuff */+gfar_wmb();/* force lstatus write before tx_skbuff */tx_queue->tx_skbuff[tx_queue->skb_curtx]=skb;
@@ -1241,6 +1241,22 @@ static inline int gfar_is_rx_dma_stopped(struct gfar_private *priv)returngfar_read(®s->ievent)&IEVENT_GRSC;}+staticinlinevoidgfar_wmb(void)+{+#if defined(CONFIG_PPC)+/* The powerpc-specific eieio() is used, as wmb() has too strong+*semantics(itrequiressynchronizationbetweencacheableand+*uncacheablemappings,whicheieio()doesn'tprovideandwhichwe+*don'tneed),thusrequiringamoreexpensivesyncinstruction.At+*somepoint,thesetofarchitecture-independentbarrierfunctions+*shouldbeexpandedtoincludeweakerbarriers.+*/+eieio();+#else+wmb();/* order write acesses for BD (or FCB) fields */+#endif+}+irqreturn_tgfar_receive(intirq,void*dev_id);intstartup_gfar(structnet_device*dev);voidstop_gfar(structnet_device*dev);
Fix the 32-bit memory access that is not endian safe,
i.e. not giving the desired byte layout for a LE CPU:
tempval = *((u32 *) (tmpbuf + 4)), where 'char tmpbuf[]'.
Get rid of rendundant local vars (tmpbuf[] and idx) and
forced casts. Cleanup comments.
Signed-off-by: Claudiu Manoil <redacted>
---
drivers/net/ethernet/freescale/gianfar.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
@@ -3248,22 +3248,21 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num,{structgfar_private*priv=netdev_priv(dev);structgfar__iomem*regs=priv->gfargrp[0].regs;-intidx;-chartmpbuf[ETH_ALEN];u32tempval;u32__iomem*macptr=®s->macstnaddr1;macptr+=num*2;-/* Now copy it into the mac registers backwards, cuz-*littleendianissilly+/* For a station address of 0x12345678ABCD in transmission+*order(BE),MACnADDR1issetto0xCDAB7856and+*MACnADDR2issetto0x34120000.*/-for(idx=0;idx<ETH_ALEN;idx++)-tmpbuf[ETH_ALEN-1-idx]=addr[idx];+tempval=(addr[5]<<24)|(addr[4]<<16)|+(addr[3]<<8)|addr[2];-gfar_write(macptr,*((u32*)(tmpbuf)));+gfar_write(macptr,tempval);-tempval=*((u32*)(tmpbuf+4));+tempval=(addr[1]<<24)|(addr[0]<<16);gfar_write(macptr+1,tempval);}
The UCC specific code included in fsl_pq_mdio.c (with
function calls from asm/ucc.h) is already guarded
by these config options, so this ARM build fix provides
consistency with the rest UCC specific code.
Signed-off-by: Claudiu Manoil <redacted>
---
drivers/net/ethernet/freescale/fsl_pq_mdio.c | 2 ++
1 file changed, 2 insertions(+)
From: Sergei Shtylyov <hidden> Date: 2014-10-03 18:39:17
Hello.
On 10/03/2014 08:02 PM, Claudiu Manoil wrote:
The UCC specific code included in fsl_pq_mdio.c (with
function calls from asm/ucc.h) is already guarded
by these config options, so this ARM build fix provides
consistency with the rest UCC specific code.
This is the first round of driver protability fixes and clean-up
with the main purpose to make gianfar portable on ARM, for the ARM
based SoC that integrates the eTSEC ethernet controller - "ls1021a".
The patches primarily address compile time errors, when compiling
gianfar on ARM. They replace PPC specific functions and macros
with architecture independent ones, solve arch specific header
inclusions, guard code that relates to PPC only, and even address
some simple endianess issues (see MAC address setup patch).
The patches addressing the bulk of remaining endianess issues,
like handling DMA fields (BD and FCB), will follow with the sencond
round.
These patches were verified on the ls1021a SoC.
If more endianness fixes are necessary and "will follow with the
second round", I do not see how you could have verified specifically
these changes on the ls1021a.
This is the first round of driver protability fixes and clean-up
with the main purpose to make gianfar portable on ARM, for the ARM
based SoC that integrates the eTSEC ethernet controller - "ls1021a".
The patches primarily address compile time errors, when compiling
gianfar on ARM. They replace PPC specific functions and macros
with architecture independent ones, solve arch specific header
inclusions, guard code that relates to PPC only, and even address
some simple endianess issues (see MAC address setup patch).
The patches addressing the bulk of remaining endianess issues,
like handling DMA fields (BD and FCB), will follow with the sencond
round.
These patches were verified on the ls1021a SoC.
If more endianness fixes are necessary and "will follow with the
second round", I do not see how you could have verified specifically
these changes on the ls1021a.
Hi David,
What I did is to split the initial patchset in 2, to ease up the review
process.
This first part is fairly straightforward, these patches make localized
code changes and can be more easily ported among different kernel
versions. The second part has fewer patches but touches more code,
because it handles endianess conversions for all the reads/writes to
the buffer descriptors. Please let me now if you have objections to
this approach.
As for testing, we have our internal kernel tree for ARM supporting
ls1021a, and these gianfar patches have been there for a while and
tested. Now it's time to upstream (a cleaned-up version of) them.
(see git.freescale.com/git/cgit.cgi/layerscape/ls1021a/linux.git/)
Please note that the current (upstream) net tree does not include the
support for ls1021a (which is to be propagated via the arm tree).
Thanks and regards,
Claudiu
This is the first round of driver protability fixes and clean-up
with the main purpose to make gianfar portable on ARM, for the ARM
based SoC that integrates the eTSEC ethernet controller - "ls1021a".
The patches primarily address compile time errors, when compiling
gianfar on ARM. They replace PPC specific functions and macros
with architecture independent ones, solve arch specific header
inclusions, guard code that relates to PPC only, and even address
some simple endianess issues (see MAC address setup patch).
The patches addressing the bulk of remaining endianess issues,
like handling DMA fields (BD and FCB), will follow with the sencond
round.
These patches were verified on the ls1021a SoC.
If more endianness fixes are necessary and "will follow with the
second round", I do not see how you could have verified specifically
these changes on the ls1021a.
Hi David,
What I did is to split the initial patchset in 2, to ease up the
review
process.
This first part is fairly straightforward, these patches make
localized
code changes and can be more easily ported among different kernel
versions. The second part has fewer patches but touches more code,
because it handles endianess conversions for all the reads/writes to
the buffer descriptors. Please let me now if you have objections to
this approach.
As for testing, we have our internal kernel tree for ARM supporting
ls1021a, and these gianfar patches have been there for a while and
tested. Now it's time to upstream (a cleaned-up version of) them.
(see git.freescale.com/git/cgit.cgi/layerscape/ls1021a/linux.git/)
Please note that the current (upstream) net tree does not include the
support for ls1021a (which is to be propagated via the arm tree).
I'm merely saying that it's inaccurate to say that you "verified" this
specific patch series on that chip, when in fact the second upcoming
series is necessary as well for the driver to work on that chip properly.