From 9a4cbd53b80862c1e57ed20d30468770699b776e Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 7 Oct 2014 10:44:28 +0300 Subject: net/fsl_pq_mdio: Fix asm/ucc.h compile error for ARM 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 only provides consistency with the rest UCC specific code. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 583e71ab7f51..32136f08515e 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -28,7 +28,9 @@ #include #include +#if IS_ENABLED(CONFIG_UCC_GETH) #include /* for ucc_set_qe_mux_mii_mng() */ +#endif #include "gianfar.h" -- cgit 1.4.1 From f5bbd262e70ff2355ce4284b0ad9eaf93fb5e374 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 7 Oct 2014 10:44:29 +0300 Subject: net/fsl_pq_mdio: Use ioread/iowrite32be() portable accessors in_be32()/out_be32() are not defined by ARM. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 32136f08515e..a422838b4f1d 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -107,14 +107,14 @@ static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u32 status; /* 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); return status ? 0 : -ETIMEDOUT; } @@ -137,21 +137,21 @@ static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) u16 value; /* 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); return value; @@ -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); } } -- cgit 1.4.1 From e4b081f543030fc0b23d2cd7d1f6e3ac69d7f47f Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 7 Oct 2014 10:44:30 +0300 Subject: net/fsl_pq_mdio: Replace spin_event_timeout() with arch independent spin_event_timeout() is PPC dependent, use an arch independent equivalent instead. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 36 ++++++++++++++++++---------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index a422838b4f1d..964c6bf37710 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -104,7 +104,7 @@ static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, { struct fsl_pq_mdio_priv *priv = bus->priv; struct fsl_pq_mii __iomem *regs = priv->regs; - u32 status; + unsigned int timeout; /* 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--; + } - return status ? 0 : -ETIMEDOUT; + return timeout ? 0 : -ETIMEDOUT; } /* @@ -133,7 +136,7 @@ static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct fsl_pq_mdio_priv *priv = bus->priv; struct fsl_pq_mii __iomem *regs = priv->regs; - u32 status; + unsigned int timeout; u16 value; /* 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) { struct fsl_pq_mdio_priv *priv = bus->priv; struct fsl_pq_mii __iomem *regs = priv->regs; - u32 status; + unsigned int timeout; 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; } -- cgit 1.4.1 From fd31a9528800b52c7a56a9cfa0af30b44dcfb0c9 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 7 Oct 2014 10:44:31 +0300 Subject: gianfar: Include missing headers for ARM builds 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 Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index fb29d049f4e1..a488105ec51d 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -100,6 +100,8 @@ #include #include #include +#include +#include #include "gianfar.h" -- cgit 1.4.1 From d6ef0bcce386531f250a8abee3c3595214ea1629 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 7 Oct 2014 10:44:32 +0300 Subject: gianfar: Exclude PPC specific errata handling from ARM builds 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 Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index a488105ec51d..37e060478630 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -88,8 +88,10 @@ #include #include +#ifdef CONFIG_PPC #include #include +#endif #include #include #include @@ -1063,6 +1065,7 @@ static void gfar_init_filer_table(struct gfar_private *priv) } } +#ifdef CONFIG_PPC static void __gfar_detect_errata_83xx(struct gfar_private *priv) { unsigned int pvr = mfspr(SPRN_PVR); @@ -1095,6 +1098,7 @@ static void __gfar_detect_errata_85xx(struct gfar_private *priv) ((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20))) priv->errata |= GFAR_ERRATA_76; /* aka eTSEC 20 */ } +#endif static void gfar_detect_errata(struct gfar_private *priv) { @@ -1103,10 +1107,12 @@ static void gfar_detect_errata(struct gfar_private *priv) /* no plans to fix */ priv->errata |= GFAR_ERRATA_A002; +#ifdef CONFIG_PPC if (pvr_version_is(PVR_VER_E500V1) || pvr_version_is(PVR_VER_E500V2)) __gfar_detect_errata_85xx(priv); else /* non-mpc85xx parts, i.e. e300 core based */ __gfar_detect_errata_83xx(priv); +#endif if (priv->errata) dev_info(dev, "enabled errata workarounds, flags: 0x%x\n", -- cgit 1.4.1 From 83bfc3c4765c35ef0dfff8a3d6dedab88f3f50ea Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 7 Oct 2014 10:44:33 +0300 Subject: gianfar: Make MAC addr setup endian safe, cleanup 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 Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 37e060478630..961198a2bfa8 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -3248,22 +3248,21 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num, { struct gfar_private *priv = netdev_priv(dev); struct gfar __iomem *regs = priv->gfargrp[0].regs; - int idx; - char tmpbuf[ETH_ALEN]; u32 tempval; u32 __iomem *macptr = ®s->macstnaddr1; macptr += num*2; - /* Now copy it into the mac registers backwards, cuz - * little endian is silly + /* For a station address of 0x12345678ABCD in transmission + * order (BE), MACnADDR1 is set to 0xCDAB7856 and + * MACnADDR2 is set to 0x34120000. */ - 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); } -- cgit 1.4.1 From a4feee89ce4590c7a4aead49ca5a4853dc6ea5dc Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 7 Oct 2014 10:44:34 +0300 Subject: gianfar: Replace spin_event_timeout() with arch independent Use arch independent code to replace the powerpc dependent spin_event_timeout() from gfar_halt_nodisable(). Added GRS/GTS read accessors to clean-up the implementation of gfar_halt_nodisable(). Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 32 +++++++++++++++++++------------- drivers/net/ethernet/freescale/gianfar.h | 15 +++++++++++++++ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 961198a2bfa8..356a9982d014 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1762,26 +1762,32 @@ static void gfar_halt_nodisable(struct gfar_private *priv) { struct gfar __iomem *regs = priv->gfargrp[0].regs; u32 tempval; + unsigned int timeout; + int stopped; 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)) { - int ret; - - 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)) + goto retry; } /* Halt the receive and transmit queues */ diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 84632c569f2c..0b3772217a9a 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -1226,6 +1226,21 @@ static inline void gfar_write_isrg(struct gfar_private *priv) } } +static inline int gfar_is_dma_stopped(struct gfar_private *priv) +{ + struct gfar __iomem *regs = priv->gfargrp[0].regs; + + return ((gfar_read(®s->ievent) & (IEVENT_GRSC | IEVENT_GTSC)) == + (IEVENT_GRSC | IEVENT_GTSC)); +} + +static inline int gfar_is_rx_dma_stopped(struct gfar_private *priv) +{ + struct gfar __iomem *regs = priv->gfargrp[0].regs; + + return gfar_read(®s->ievent) & IEVENT_GRSC; +} + irqreturn_t gfar_receive(int irq, void *dev_id); int startup_gfar(struct net_device *dev); void stop_gfar(struct net_device *dev); -- cgit 1.4.1 From d55398ba81139bc826a8c2417a01280e99f08cf3 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 7 Oct 2014 10:44:35 +0300 Subject: gianfar: Replace eieio with wmb for non-PPC archs 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 Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 13 +++---------- drivers/net/ethernet/freescale/gianfar.h | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 356a9982d014..379b1a578d3d 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -165,7 +165,7 @@ static void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, if (bdp == rx_queue->rx_bd_base + rx_queue->rx_ring_size - 1) lstatus |= BD_LFLAG(RXBD_WRAP); - eieio(); + gfar_wmb(); bdp->lstatus = lstatus; } @@ -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 (it requires synchronization between cacheable and - * uncacheable mappings, which eieio doesn't provide and which we - * don't need), thus requiring a more expensive sync instruction. At - * some point, the set of architecture-independent barrier functions - * should be expanded to include weaker barriers. - */ - 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; diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 0b3772217a9a..2805cfbf1765 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -1241,6 +1241,22 @@ static inline int gfar_is_rx_dma_stopped(struct gfar_private *priv) return gfar_read(®s->ievent) & IEVENT_GRSC; } +static inline void gfar_wmb(void) +{ +#if defined(CONFIG_PPC) + /* The powerpc-specific eieio() is used, as wmb() has too strong + * semantics (it requires synchronization between cacheable and + * uncacheable mappings, which eieio() doesn't provide and which we + * don't need), thus requiring a more expensive sync instruction. At + * some point, the set of architecture-independent barrier functions + * should be expanded to include weaker barriers. + */ + eieio(); +#else + wmb(); /* order write acesses for BD (or FCB) fields */ +#endif +} + irqreturn_t gfar_receive(int irq, void *dev_id); int startup_gfar(struct net_device *dev); void stop_gfar(struct net_device *dev); -- cgit 1.4.1