All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/40] net: fec: cleanup/fixes
@ 2016-01-28 21:25 ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky


The testing for this series was done on a nitrogen6x.
The base commit was
commit 7a26019fdecdb45ff784ae4e3b7e0cc9045100ca
    Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Testing used imx_v6_v7_defconfig + CONFIG_MICREL_PHY.
The processor was running at 996Mhz. The last 2 patches
are independent from this series, but I included here
to have the bench marks in one place. The following
commands were used to get the transfer rates.

On an x86 ubunto system,
iperf -s -i.5 -u


On a nitrogen6x board, running via NFS/Sd card.
I first stopped some background processes

stop cron
stop upstart-file-bridge
stop upstart-socket-bridge
stop upstart-udev-bridge
stop rsyslog
stop dbus
killall dhclient
echo performance >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

taskset 0x2 iperf -c 192.168.0.201 -u -t60 -b500M -r

There is a branch available on github with this series
https://github.com:boundarydevices/linux-imx6.git branch net-next_master


Troy Kisky (40):
NFS      SDCARD
 TX/RX   TX/RX  Mbits/sec
377/406 379/407 before any patches
377/409 379/406 net: fec: stop the "rcv is not +last, " error messages
374/406 374/407 net: fec: fix rx error counts
373/410 377/407 net: fec: fix fec_enet_get_free_txdesc_num
374/408 379/413 net: fec: add struct bufdesc_prop
375/410 379/412 net: fec: add variable reg_desc_active to speed things up
380/413 383/416 net: fec: don't disable FEC_ENET_TS_TIMER interrupt
375/406 379/413 net: fec: don't transfer ownership until descriptor write is complete
373/411 378/414 net: fec: move cbd_bufaddr assignment closer to the mapping function
372/411 377/414 net: fec: only check queue 0 if RXF_0/TXF_0 interrupt is set
375/410 375/412 net: fec: pass rxq to fec_enet_rx_queue instead of queue_id
373/414 377/413 net: fec: pass txq to fec_enet_tx_queue instead of queue_id
380/426 382/425 net: fec: reduce interrupts
378/418 379/417 net: fec: split off napi routine with 3 queues
379/417 379/418 net: fec: don't clear all rx queue bits when just one is being checked
379/420 379/420 net: fec: set cbd_sc without relying on previous value
379/422 379/422 net: fec: eliminate calls to fec_enet_get_prevdesc
379/425 379/424 net: fec: move restart test for efficiency
379/415 379/419 net: fec: clear cbd_sc after transmission to help with debugging
373/420 379/421 net: fec: dump all tx queues in fec_dump
378/425 379/427 net: fec: detect tx int lost
379/416 379/418 net: fec: print more debug info in fec_timeout
379/415 380/415 net: fec: call dma_unmap_single on mapped tx buffers at restart
382/419 384/418 net: fec: don't set cbd_bufaddr unless no mapping error
379/417 380/415 net: fec: return NETDEV_TX_BUSY, when not enough space in ring
379/417 379/417 net: fec: don't free skb until it has been unmapped
378/421 379/425 net: fec: set cbd_esc only once
379/413 380/411 net: fec: enable interrupt on very last descriptor only
381/411 381/411 net: fec: unmap initial buffer on error
379/419 387/417 net: fec: don't free skb when returning busy
384/419 386/418 net: fec: move last_bdp assignment for symmetry
383/420 387/419 net: fec: don't transfer ownership until entire tso is queued
381/424 384/424 net: fec: fix err_release in fec_enet_txq_submit_tso
382/423 383/422 net: fec: shrink the window for 'tx int lost'
387/418 388/420 net: fec: update dirty_tx even if no skb
387/423 390/423 net: fec: rename dirty_tx to pending_tx
388/426 389/423 net: fec: use mac set by bootloader before fuses
379/425 380/432 net: fec: add events device file
379/432 381/429 net: fec: recover from lost rxf_0 interrupt
381/432 381/432 ARM: dts: imx6qdl-nitrogen6x: add phy interrupt to eliminate polling
380/432 380/432 ARM: dts: imx6qdl-nitrogen6_max: add phy interrupt to eliminate
    polling


The same patch set on Freescale's 3.14 release gives
458/619 Mbits/sec with the command modified to

taskset 0x2 iperf -c 192.168.0.201 -u -t60 -b600M -r

The huge difference may be related to the cpuidle driver which isn't
enabled in imx_v6_v7_defconfig and doesn't seem to work if it is enabled.




 arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi |   9 +
 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi    |  11 +
 drivers/net/ethernet/freescale/fec.h         |  59 +-
 drivers/net/ethernet/freescale/fec_main.c    | 921 ++++++++++++++-------------
 4 files changed, 525 insertions(+), 475 deletions(-)

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

* [PATCH net-next 00/40] net: fec: cleanup/fixes
@ 2016-01-28 21:25 ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel


The testing for this series was done on a nitrogen6x.
The base commit was
commit 7a26019fdecdb45ff784ae4e3b7e0cc9045100ca
    Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Testing used imx_v6_v7_defconfig + CONFIG_MICREL_PHY.
The processor was running at 996Mhz. The last 2 patches
are independent from this series, but I included here
to have the bench marks in one place. The following
commands were used to get the transfer rates.

On an x86 ubunto system,
iperf -s -i.5 -u


On a nitrogen6x board, running via NFS/Sd card.
I first stopped some background processes

stop cron
stop upstart-file-bridge
stop upstart-socket-bridge
stop upstart-udev-bridge
stop rsyslog
stop dbus
killall dhclient
echo performance >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

taskset 0x2 iperf -c 192.168.0.201 -u -t60 -b500M -r

There is a branch available on github with this series
https://github.com:boundarydevices/linux-imx6.git branch net-next_master


Troy Kisky (40):
NFS      SDCARD
 TX/RX   TX/RX  Mbits/sec
377/406 379/407 before any patches
377/409 379/406 net: fec: stop the "rcv is not +last, " error messages
374/406 374/407 net: fec: fix rx error counts
373/410 377/407 net: fec: fix fec_enet_get_free_txdesc_num
374/408 379/413 net: fec: add struct bufdesc_prop
375/410 379/412 net: fec: add variable reg_desc_active to speed things up
380/413 383/416 net: fec: don't disable FEC_ENET_TS_TIMER interrupt
375/406 379/413 net: fec: don't transfer ownership until descriptor write is complete
373/411 378/414 net: fec: move cbd_bufaddr assignment closer to the mapping function
372/411 377/414 net: fec: only check queue 0 if RXF_0/TXF_0 interrupt is set
375/410 375/412 net: fec: pass rxq to fec_enet_rx_queue instead of queue_id
373/414 377/413 net: fec: pass txq to fec_enet_tx_queue instead of queue_id
380/426 382/425 net: fec: reduce interrupts
378/418 379/417 net: fec: split off napi routine with 3 queues
379/417 379/418 net: fec: don't clear all rx queue bits when just one is being checked
379/420 379/420 net: fec: set cbd_sc without relying on previous value
379/422 379/422 net: fec: eliminate calls to fec_enet_get_prevdesc
379/425 379/424 net: fec: move restart test for efficiency
379/415 379/419 net: fec: clear cbd_sc after transmission to help with debugging
373/420 379/421 net: fec: dump all tx queues in fec_dump
378/425 379/427 net: fec: detect tx int lost
379/416 379/418 net: fec: print more debug info in fec_timeout
379/415 380/415 net: fec: call dma_unmap_single on mapped tx buffers at restart
382/419 384/418 net: fec: don't set cbd_bufaddr unless no mapping error
379/417 380/415 net: fec: return NETDEV_TX_BUSY, when not enough space in ring
379/417 379/417 net: fec: don't free skb until it has been unmapped
378/421 379/425 net: fec: set cbd_esc only once
379/413 380/411 net: fec: enable interrupt on very last descriptor only
381/411 381/411 net: fec: unmap initial buffer on error
379/419 387/417 net: fec: don't free skb when returning busy
384/419 386/418 net: fec: move last_bdp assignment for symmetry
383/420 387/419 net: fec: don't transfer ownership until entire tso is queued
381/424 384/424 net: fec: fix err_release in fec_enet_txq_submit_tso
382/423 383/422 net: fec: shrink the window for 'tx int lost'
387/418 388/420 net: fec: update dirty_tx even if no skb
387/423 390/423 net: fec: rename dirty_tx to pending_tx
388/426 389/423 net: fec: use mac set by bootloader before fuses
379/425 380/432 net: fec: add events device file
379/432 381/429 net: fec: recover from lost rxf_0 interrupt
381/432 381/432 ARM: dts: imx6qdl-nitrogen6x: add phy interrupt to eliminate polling
380/432 380/432 ARM: dts: imx6qdl-nitrogen6_max: add phy interrupt to eliminate
    polling


The same patch set on Freescale's 3.14 release gives
458/619 Mbits/sec with the command modified to

taskset 0x2 iperf -c 192.168.0.201 -u -t60 -b600M -r

The huge difference may be related to the cpuidle driver which isn't
enabled in imx_v6_v7_defconfig and doesn't seem to work if it is enabled.




 arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi |   9 +
 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi    |  11 +
 drivers/net/ethernet/freescale/fec.h         |  59 +-
 drivers/net/ethernet/freescale/fec_main.c    | 921 ++++++++++++++-------------
 4 files changed, 525 insertions(+), 475 deletions(-)

--
2.5.0

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

* [PATCH net-next 01/40] net: fec: stop the "rcv is not +last, " error messages
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Setting the FTRL register will stop the fec from
trying to use multiple receive buffers.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      | 1 +
 drivers/net/ethernet/freescale/fec_main.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 99d33e2..5144e73 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -65,6 +65,7 @@
 #define FEC_R_FIFO_RSEM		0x194 /* Receive FIFO section empty threshold */
 #define FEC_R_FIFO_RAEM		0x198 /* Receive FIFO almost empty threshold */
 #define FEC_R_FIFO_RAFL		0x19c /* Receive FIFO almost full threshold */
+#define FEC_FTRL		0x1b0 /* Frame truncation receive length*/
 #define FEC_RACC		0x1c4 /* Receive Accelerator function */
 #define FEC_RCMR_1		0x1c8 /* Receive classification match ring 1 */
 #define FEC_RCMR_2		0x1cc /* Receive classification match ring 2 */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 502da6f..2c7c845 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -984,6 +984,7 @@ fec_restart(struct net_device *ndev)
 			val &= ~FEC_RACC_OPTIONS;
 		writel(val, fep->hwp + FEC_RACC);
 	}
+	writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL);
 #endif
 
 	/*
-- 
2.5.0

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

* [PATCH net-next 01/40] net: fec: stop the "rcv is not +last, " error messages
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Setting the FTRL register will stop the fec from
trying to use multiple receive buffers.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      | 1 +
 drivers/net/ethernet/freescale/fec_main.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 99d33e2..5144e73 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -65,6 +65,7 @@
 #define FEC_R_FIFO_RSEM		0x194 /* Receive FIFO section empty threshold */
 #define FEC_R_FIFO_RAEM		0x198 /* Receive FIFO almost empty threshold */
 #define FEC_R_FIFO_RAFL		0x19c /* Receive FIFO almost full threshold */
+#define FEC_FTRL		0x1b0 /* Frame truncation receive length*/
 #define FEC_RACC		0x1c4 /* Receive Accelerator function */
 #define FEC_RCMR_1		0x1c8 /* Receive classification match ring 1 */
 #define FEC_RCMR_2		0x1cc /* Receive classification match ring 2 */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 502da6f..2c7c845 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -984,6 +984,7 @@ fec_restart(struct net_device *ndev)
 			val &= ~FEC_RACC_OPTIONS;
 		writel(val, fep->hwp + FEC_RACC);
 	}
+	writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL);
 #endif
 
 	/*
-- 
2.5.0

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

* [PATCH net-next 02/40] net: fec: fix rx error counts
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

On an overrun, the other flags are not
valid, so don't check them.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 36 +++++++++++++------------------
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 2c7c845..620834f 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1403,37 +1403,31 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 			break;
 		pkt_received++;
 
-		/* Since we have allocated space to hold a complete frame,
-		 * the last indicator should be set.
-		 */
-		if ((status & BD_ENET_RX_LAST) == 0)
-			netdev_err(ndev, "rcv is not +last\n");
-
 		writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT);
 
 		/* Check for errors. */
+		status ^= BD_ENET_RX_LAST;
 		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
-			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+			   BD_ENET_RX_CR | BD_ENET_RX_OV | BD_ENET_RX_LAST |
+			   BD_ENET_RX_CL)) {
 			ndev->stats.rx_errors++;
-			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
+			if (status & BD_ENET_RX_OV) {
+				/* FIFO overrun */
+				ndev->stats.rx_fifo_errors++;
+				goto rx_processing_done;
+			}
+			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH
+						| BD_ENET_RX_LAST)) {
 				/* Frame too long or too short. */
 				ndev->stats.rx_length_errors++;
+				if (status & BD_ENET_RX_LAST)
+					netdev_err(ndev, "rcv is not +last\n");
 			}
-			if (status & BD_ENET_RX_NO)	/* Frame alignment */
-				ndev->stats.rx_frame_errors++;
 			if (status & BD_ENET_RX_CR)	/* CRC Error */
 				ndev->stats.rx_crc_errors++;
-			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
-				ndev->stats.rx_fifo_errors++;
-		}
-
-		/* Report late collisions as a frame error.
-		 * On this error, the BD is closed, but we don't know what we
-		 * have in the buffer.  So, just drop this frame on the floor.
-		 */
-		if (status & BD_ENET_RX_CL) {
-			ndev->stats.rx_errors++;
-			ndev->stats.rx_frame_errors++;
+			/* Report late collisions as a frame error. */
+			if (status & (BD_ENET_RX_NO | BD_ENET_RX_CL))
+				ndev->stats.rx_frame_errors++;
 			goto rx_processing_done;
 		}
 
-- 
2.5.0

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

* [PATCH net-next 02/40] net: fec: fix rx error counts
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

On an overrun, the other flags are not
valid, so don't check them.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 36 +++++++++++++------------------
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 2c7c845..620834f 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1403,37 +1403,31 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 			break;
 		pkt_received++;
 
-		/* Since we have allocated space to hold a complete frame,
-		 * the last indicator should be set.
-		 */
-		if ((status & BD_ENET_RX_LAST) == 0)
-			netdev_err(ndev, "rcv is not +last\n");
-
 		writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT);
 
 		/* Check for errors. */
+		status ^= BD_ENET_RX_LAST;
 		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
-			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+			   BD_ENET_RX_CR | BD_ENET_RX_OV | BD_ENET_RX_LAST |
+			   BD_ENET_RX_CL)) {
 			ndev->stats.rx_errors++;
-			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
+			if (status & BD_ENET_RX_OV) {
+				/* FIFO overrun */
+				ndev->stats.rx_fifo_errors++;
+				goto rx_processing_done;
+			}
+			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH
+						| BD_ENET_RX_LAST)) {
 				/* Frame too long or too short. */
 				ndev->stats.rx_length_errors++;
+				if (status & BD_ENET_RX_LAST)
+					netdev_err(ndev, "rcv is not +last\n");
 			}
-			if (status & BD_ENET_RX_NO)	/* Frame alignment */
-				ndev->stats.rx_frame_errors++;
 			if (status & BD_ENET_RX_CR)	/* CRC Error */
 				ndev->stats.rx_crc_errors++;
-			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
-				ndev->stats.rx_fifo_errors++;
-		}
-
-		/* Report late collisions as a frame error.
-		 * On this error, the BD is closed, but we don't know what we
-		 * have in the buffer.  So, just drop this frame on the floor.
-		 */
-		if (status & BD_ENET_RX_CL) {
-			ndev->stats.rx_errors++;
-			ndev->stats.rx_frame_errors++;
+			/* Report late collisions as a frame error. */
+			if (status & (BD_ENET_RX_NO | BD_ENET_RX_CL))
+				ndev->stats.rx_frame_errors++;
 			goto rx_processing_done;
 		}
 
-- 
2.5.0

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

* [PATCH net-next 03/40] net: fec: fix fec_enet_get_free_txdesc_num
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, andrew, linux, Troy Kisky, laci, l.stach,
	shawnguo, linux-arm-kernel, tremyfr

When first initialized, cur_tx points to the 1st
entry in the queue, and dirty_tx points to the last.
At this point, fec_enet_get_free_txdesc_num will
return tx_ring_size -2. If tx_ring_size -2 entries
are now queued, then fec_enet_get_free_txdesc_num
should return 0, but it returns tx_ring_size instead.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 620834f..8e1f2a6 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -296,7 +296,7 @@ static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep,
 	entries = ((const char *)txq->dirty_tx -
 			(const char *)txq->cur_tx) / fep->bufdesc_size - 1;
 
-	return entries > 0 ? entries : entries + txq->tx_ring_size;
+	return entries >= 0 ? entries : entries + txq->tx_ring_size;
 }
 
 static void swap_buffer(void *bufaddr, int len)
-- 
2.5.0

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

* [PATCH net-next 03/40] net: fec: fix fec_enet_get_free_txdesc_num
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

When first initialized, cur_tx points to the 1st
entry in the queue, and dirty_tx points to the last.
At this point, fec_enet_get_free_txdesc_num will
return tx_ring_size -2. If tx_ring_size -2 entries
are now queued, then fec_enet_get_free_txdesc_num
should return 0, but it returns tx_ring_size instead.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 620834f..8e1f2a6 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -296,7 +296,7 @@ static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep,
 	entries = ((const char *)txq->dirty_tx -
 			(const char *)txq->cur_tx) / fep->bufdesc_size - 1;
 
-	return entries > 0 ? entries : entries + txq->tx_ring_size;
+	return entries >= 0 ? entries : entries + txq->tx_ring_size;
 }
 
 static void swap_buffer(void *bufaddr, int len)
-- 
2.5.0

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

* [PATCH net-next 04/40] net: fec: add struct bufdesc_prop
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

This reduces code and gains speed.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      |  29 ++-
 drivers/net/ethernet/freescale/fec_main.c | 288 ++++++++++++------------------
 2 files changed, 132 insertions(+), 185 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 5144e73..6018d0e4 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -432,33 +432,34 @@ struct bufdesc_ex {
 /* Controller supports RACC register */
 #define FEC_QUIRK_HAS_RACC		(1 << 12)
 
+struct bufdesc_prop {
+	int qid;
+	/* Address of Rx and Tx buffers */
+	struct bufdesc	*base;
+	struct bufdesc	*last;
+	struct bufdesc	*cur;
+	dma_addr_t	dma;
+	unsigned short ring_size;
+	unsigned char dsize;
+	unsigned char dsize_log2;
+};
+
 struct fec_enet_priv_tx_q {
-	int index;
+	struct bufdesc_prop bd;
 	unsigned char *tx_bounce[TX_RING_SIZE];
 	struct  sk_buff *tx_skbuff[TX_RING_SIZE];
 
-	dma_addr_t	bd_dma;
-	struct bufdesc	*tx_bd_base;
-	uint tx_ring_size;
-
 	unsigned short tx_stop_threshold;
 	unsigned short tx_wake_threshold;
 
-	struct bufdesc	*cur_tx;
 	struct bufdesc	*dirty_tx;
 	char *tso_hdrs;
 	dma_addr_t tso_hdrs_dma;
 };
 
 struct fec_enet_priv_rx_q {
-	int index;
+	struct bufdesc_prop bd;
 	struct  sk_buff *rx_skbuff[RX_RING_SIZE];
-
-	dma_addr_t	bd_dma;
-	struct bufdesc	*rx_bd_base;
-	uint rx_ring_size;
-
-	struct bufdesc	*cur_rx;
 };
 
 /* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
@@ -498,8 +499,6 @@ struct fec_enet_private {
 	unsigned long work_ts;
 	unsigned long work_mdio;
 
-	unsigned short bufdesc_size;
-
 	struct	platform_device *pdev;
 
 	int	dev_id;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 8e1f2a6..feff466 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -217,86 +217,38 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 
 #define IS_TSO_HEADER(txq, addr) \
 	((addr >= txq->tso_hdrs_dma) && \
-	(addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE))
+	(addr < txq->tso_hdrs_dma + txq->bd.ring_size * TSO_HEADER_SIZE))
 
 static int mii_cnt;
 
-static inline
-struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp,
-				      struct fec_enet_private *fep,
-				      int queue_id)
-{
-	struct bufdesc *new_bd = bdp + 1;
-	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1;
-	struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id];
-	struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id];
-	struct bufdesc_ex *ex_base;
-	struct bufdesc *base;
-	int ring_size;
-
-	if (bdp >= txq->tx_bd_base) {
-		base = txq->tx_bd_base;
-		ring_size = txq->tx_ring_size;
-		ex_base = (struct bufdesc_ex *)txq->tx_bd_base;
-	} else {
-		base = rxq->rx_bd_base;
-		ring_size = rxq->rx_ring_size;
-		ex_base = (struct bufdesc_ex *)rxq->rx_bd_base;
-	}
-
-	if (fep->bufdesc_ex)
-		return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ?
-			ex_base : ex_new_bd);
-	else
-		return (new_bd >= (base + ring_size)) ?
-			base : new_bd;
-}
-
-static inline
-struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp,
-				      struct fec_enet_private *fep,
-				      int queue_id)
-{
-	struct bufdesc *new_bd = bdp - 1;
-	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1;
-	struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id];
-	struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id];
-	struct bufdesc_ex *ex_base;
-	struct bufdesc *base;
-	int ring_size;
-
-	if (bdp >= txq->tx_bd_base) {
-		base = txq->tx_bd_base;
-		ring_size = txq->tx_ring_size;
-		ex_base = (struct bufdesc_ex *)txq->tx_bd_base;
-	} else {
-		base = rxq->rx_bd_base;
-		ring_size = rxq->rx_ring_size;
-		ex_base = (struct bufdesc_ex *)rxq->rx_bd_base;
-	}
+static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp,
+					     struct bufdesc_prop *bd)
+{
+	return (bdp >= bd->last) ? bd->base
+			: (struct bufdesc *)(((unsigned)bdp) + bd->dsize);
+}
 
-	if (fep->bufdesc_ex)
-		return (struct bufdesc *)((ex_new_bd < ex_base) ?
-			(ex_new_bd + ring_size) : ex_new_bd);
-	else
-		return (new_bd < base) ? (new_bd + ring_size) : new_bd;
+static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp,
+					     struct bufdesc_prop *bd)
+{
+	return (bdp <= bd->base) ? bd->last
+			: (struct bufdesc *)(((unsigned)bdp) - bd->dsize);
 }
 
-static int fec_enet_get_bd_index(struct bufdesc *base, struct bufdesc *bdp,
-				struct fec_enet_private *fep)
+static int fec_enet_get_bd_index(struct bufdesc *bdp,
+				 struct bufdesc_prop *bd)
 {
-	return ((const char *)bdp - (const char *)base) / fep->bufdesc_size;
+	return ((const char *)bdp - (const char *)bd->base) >> bd->dsize_log2;
 }
 
-static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep,
-					struct fec_enet_priv_tx_q *txq)
+static int fec_enet_get_free_txdesc_num(struct fec_enet_priv_tx_q *txq)
 {
 	int entries;
 
-	entries = ((const char *)txq->dirty_tx -
-			(const char *)txq->cur_tx) / fep->bufdesc_size - 1;
+	entries = (((const char *)txq->dirty_tx -
+			(const char *)txq->bd.cur) >> txq->bd.dsize_log2) - 1;
 
-	return entries >= 0 ? entries : entries + txq->tx_ring_size;
+	return entries >= 0 ? entries : entries + txq->bd.ring_size;
 }
 
 static void swap_buffer(void *bufaddr, int len)
@@ -329,18 +281,18 @@ static void fec_dump(struct net_device *ndev)
 	pr_info("Nr     SC     addr       len  SKB\n");
 
 	txq = fep->tx_queue[0];
-	bdp = txq->tx_bd_base;
+	bdp = txq->bd.base;
 
 	do {
 		pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
 			index,
-			bdp == txq->cur_tx ? 'S' : ' ',
+			bdp == txq->bd.cur ? 'S' : ' ',
 			bdp == txq->dirty_tx ? 'H' : ' ',
 			bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
 			txq->tx_skbuff[index]);
-		bdp = fec_enet_get_nextdesc(bdp, fep, 0);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		index++;
-	} while (bdp != txq->tx_bd_base);
+	} while (bdp != txq->bd.base);
 }
 
 static inline bool is_ipv4_pkt(struct sk_buff *skb)
@@ -371,7 +323,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 			     struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct bufdesc *bdp = txq->cur_tx;
+	struct bufdesc *bdp = txq->bd.cur;
 	struct bufdesc_ex *ebdp;
 	int nr_frags = skb_shinfo(skb)->nr_frags;
 	unsigned short queue = skb_get_queue_mapping(skb);
@@ -386,7 +338,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 	for (frag = 0; frag < nr_frags; frag++) {
 		this_frag = &skb_shinfo(skb)->frags[frag];
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		ebdp = (struct bufdesc_ex *)bdp;
 
 		status = bdp->cbd_sc;
@@ -416,7 +368,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 		bufaddr = page_address(this_frag->page.p) + this_frag->page_offset;
 
-		index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
+		index = fec_enet_get_bd_index(bdp, &txq->bd);
 		if (((unsigned long) bufaddr) & fep->tx_align ||
 			fep->quirks & FEC_QUIRK_SWAP_FRAME) {
 			memcpy(txq->tx_bounce[index], bufaddr, frag_len);
@@ -442,9 +394,9 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 	return bdp;
 dma_mapping_error:
-	bdp = txq->cur_tx;
+	bdp = txq->bd.cur;
 	for (i = 0; i < frag; i++) {
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
 				bdp->cbd_datlen, DMA_TO_DEVICE);
 	}
@@ -466,7 +418,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	unsigned int index;
 	int entries_free;
 
-	entries_free = fec_enet_get_free_txdesc_num(fep, txq);
+	entries_free = fec_enet_get_free_txdesc_num(txq);
 	if (entries_free < MAX_SKB_FRAGS + 1) {
 		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
@@ -481,7 +433,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	}
 
 	/* Fill in a Tx ring entry */
-	bdp = txq->cur_tx;
+	bdp = txq->bd.cur;
 	last_bdp = bdp;
 	status = bdp->cbd_sc;
 	status &= ~BD_ENET_TX_STATS;
@@ -491,7 +443,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	buflen = skb_headlen(skb);
 
 	queue = skb_get_queue_mapping(skb);
-	index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
+	index = fec_enet_get_bd_index(bdp, &txq->bd);
 	if (((unsigned long) bufaddr) & fep->tx_align ||
 		fep->quirks & FEC_QUIRK_SWAP_FRAME) {
 		memcpy(txq->tx_bounce[index], skb->data, buflen);
@@ -542,7 +494,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 		ebdp->cbd_esc = estatus;
 	}
 
-	index = fec_enet_get_bd_index(txq->tx_bd_base, last_bdp, fep);
+	index = fec_enet_get_bd_index(last_bdp, &txq->bd);
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
 
@@ -556,15 +508,15 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	bdp->cbd_sc = status;
 
 	/* If this was the last BD in the ring, start at the beginning again. */
-	bdp = fec_enet_get_nextdesc(last_bdp, fep, queue);
+	bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
 
 	skb_tx_timestamp(skb);
 
 	/* Make sure the update to bdp and tx_skbuff are performed before
-	 * cur_tx.
+	 * txq->bd.cur.
 	 */
 	wmb();
-	txq->cur_tx = bdp;
+	txq->bd.cur = bdp;
 
 	/* Trigger transmission start */
 	writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue));
@@ -695,13 +647,13 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	int total_len, data_left;
-	struct bufdesc *bdp = txq->cur_tx;
+	struct bufdesc *bdp = txq->bd.cur;
 	unsigned short queue = skb_get_queue_mapping(skb);
 	struct tso_t tso;
 	unsigned int index = 0;
 	int ret;
 
-	if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(fep, txq)) {
+	if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(txq)) {
 		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "NOT enough BD for TSO!\n");
@@ -721,7 +673,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	while (total_len > 0) {
 		char *hdr;
 
-		index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
+		index = fec_enet_get_bd_index(bdp, &txq->bd);
 		data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
 		total_len -= data_left;
 
@@ -736,9 +688,8 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 			int size;
 
 			size = min_t(int, tso.size, data_left);
-			bdp = fec_enet_get_nextdesc(bdp, fep, queue);
-			index = fec_enet_get_bd_index(txq->tx_bd_base,
-						      bdp, fep);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+			index = fec_enet_get_bd_index(bdp, &txq->bd);
 			ret = fec_enet_txq_put_data_tso(txq, skb, ndev,
 							bdp, index,
 							tso.data, size,
@@ -751,14 +702,14 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 			tso_build_data(skb, &tso, size);
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 	}
 
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
 
 	skb_tx_timestamp(skb);
-	txq->cur_tx = bdp;
+	txq->bd.cur = bdp;
 
 	/* Trigger transmission start */
 	if (!(fep->quirks & FEC_QUIRK_ERR007885) ||
@@ -796,7 +747,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	if (ret)
 		return ret;
 
-	entries_free = fec_enet_get_free_txdesc_num(fep, txq);
+	entries_free = fec_enet_get_free_txdesc_num(txq);
 	if (entries_free <= txq->tx_stop_threshold)
 		netif_tx_stop_queue(nq);
 
@@ -817,32 +768,32 @@ static void fec_enet_bd_init(struct net_device *dev)
 	for (q = 0; q < fep->num_rx_queues; q++) {
 		/* Initialize the receive buffer descriptors. */
 		rxq = fep->rx_queue[q];
-		bdp = rxq->rx_bd_base;
+		bdp = rxq->bd.base;
 
-		for (i = 0; i < rxq->rx_ring_size; i++) {
+		for (i = 0; i < rxq->bd.ring_size; i++) {
 
 			/* Initialize the BD for every fragment in the page. */
 			if (bdp->cbd_bufaddr)
 				bdp->cbd_sc = BD_ENET_RX_EMPTY;
 			else
 				bdp->cbd_sc = 0;
-			bdp = fec_enet_get_nextdesc(bdp, fep, q);
+			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 		}
 
 		/* Set the last buffer to wrap */
-		bdp = fec_enet_get_prevdesc(bdp, fep, q);
+		bdp = fec_enet_get_prevdesc(bdp, &rxq->bd);
 		bdp->cbd_sc |= BD_SC_WRAP;
 
-		rxq->cur_rx = rxq->rx_bd_base;
+		rxq->bd.cur = rxq->bd.base;
 	}
 
 	for (q = 0; q < fep->num_tx_queues; q++) {
 		/* ...and the same for transmit */
 		txq = fep->tx_queue[q];
-		bdp = txq->tx_bd_base;
-		txq->cur_tx = bdp;
+		bdp = txq->bd.base;
+		txq->bd.cur = bdp;
 
-		for (i = 0; i < txq->tx_ring_size; i++) {
+		for (i = 0; i < txq->bd.ring_size; i++) {
 			/* Initialize the BD for every fragment in the page. */
 			bdp->cbd_sc = 0;
 			if (txq->tx_skbuff[i]) {
@@ -850,11 +801,11 @@ static void fec_enet_bd_init(struct net_device *dev)
 				txq->tx_skbuff[i] = NULL;
 			}
 			bdp->cbd_bufaddr = 0;
-			bdp = fec_enet_get_nextdesc(bdp, fep, q);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
 
 		/* Set the last buffer to wrap */
-		bdp = fec_enet_get_prevdesc(bdp, fep, q);
+		bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
 		bdp->cbd_sc |= BD_SC_WRAP;
 		txq->dirty_tx = bdp;
 	}
@@ -878,7 +829,7 @@ static void fec_enet_enable_ring(struct net_device *ndev)
 
 	for (i = 0; i < fep->num_rx_queues; i++) {
 		rxq = fep->rx_queue[i];
-		writel(rxq->bd_dma, fep->hwp + FEC_R_DES_START(i));
+		writel(rxq->bd.dma, fep->hwp + FEC_R_DES_START(i));
 		writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE(i));
 
 		/* enable DMA1/2 */
@@ -889,7 +840,7 @@ static void fec_enet_enable_ring(struct net_device *ndev)
 
 	for (i = 0; i < fep->num_tx_queues; i++) {
 		txq = fep->tx_queue[i];
-		writel(txq->bd_dma, fep->hwp + FEC_X_DES_START(i));
+		writel(txq->bd.dma, fep->hwp + FEC_X_DES_START(i));
 
 		/* enable DMA1/2 */
 		if (i)
@@ -907,7 +858,7 @@ static void fec_enet_reset_skb(struct net_device *ndev)
 	for (i = 0; i < fep->num_tx_queues; i++) {
 		txq = fep->tx_queue[i];
 
-		for (j = 0; j < txq->tx_ring_size; j++) {
+		for (j = 0; j < txq->bd.ring_size; j++) {
 			if (txq->tx_skbuff[j]) {
 				dev_kfree_skb_any(txq->tx_skbuff[j]);
 				txq->tx_skbuff[j] = NULL;
@@ -1218,16 +1169,16 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 	bdp = txq->dirty_tx;
 
 	/* get next bdp of dirty_tx */
-	bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+	bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 
-	while (bdp != READ_ONCE(txq->cur_tx)) {
-		/* Order the load of cur_tx and cbd_sc */
+	while (bdp != READ_ONCE(txq->bd.cur)) {
+		/* Order the load of bd.cur and cbd_sc */
 		rmb();
 		status = READ_ONCE(bdp->cbd_sc);
 		if (status & BD_ENET_TX_READY)
 			break;
 
-		index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
+		index = fec_enet_get_bd_index(bdp, &txq->bd);
 
 		skb = txq->tx_skbuff[index];
 		txq->tx_skbuff[index] = NULL;
@@ -1236,7 +1187,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 					bdp->cbd_datlen, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
 		if (!skb) {
-			bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 			continue;
 		}
 
@@ -1285,19 +1236,19 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 		txq->dirty_tx = bdp;
 
 		/* Update pointer to next buffer descriptor to be transmitted */
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 
 		/* Since we have freed up a buffer, the ring is no longer full
 		 */
 		if (netif_queue_stopped(ndev)) {
-			entries_free = fec_enet_get_free_txdesc_num(fep, txq);
+			entries_free = fec_enet_get_free_txdesc_num(txq);
 			if (entries_free >= txq->tx_wake_threshold)
 				netif_tx_wake_queue(nq);
 		}
 	}
 
 	/* ERR006538: Keep the transmitter going */
-	if (bdp != txq->cur_tx &&
+	if (bdp != txq->bd.cur &&
 	    readl(fep->hwp + FEC_X_DES_ACTIVE(queue_id)) == 0)
 		writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue_id));
 }
@@ -1362,7 +1313,7 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb,
 	return true;
 }
 
-/* During a receive, the cur_rx points to the current incoming buffer.
+/* During a receive, the bd_rx.cur points to the current incoming buffer.
  * When we update through the ring, if the next incoming buffer has
  * not been given to the system, we just set the empty indicator,
  * effectively tossing the packet.
@@ -1395,7 +1346,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 	/* First, grab all of the stats for the incoming packet.
 	 * These get messed up if we get called due to a busy condition.
 	 */
-	bdp = rxq->cur_rx;
+	bdp = rxq->bd.cur;
 
 	while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
 
@@ -1436,7 +1387,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 		pkt_len = bdp->cbd_datlen;
 		ndev->stats.rx_bytes += pkt_len;
 
-		index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep);
+		index = fec_enet_get_bd_index(bdp, &rxq->bd);
 		skb = rxq->rx_skbuff[index];
 
 		/* The packet length includes FCS, but we don't want to
@@ -1533,7 +1484,7 @@ rx_processing_done:
 		}
 
 		/* Update BD pointer to next entry */
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 
 		/* Doing this here will keep the FEC running while we process
 		 * incoming frames.  On a heavily loaded network, we should be
@@ -1541,7 +1492,7 @@ rx_processing_done:
 		 */
 		writel(0, fep->hwp + FEC_R_DES_ACTIVE(queue_id));
 	}
-	rxq->cur_rx = bdp;
+	rxq->bd.cur = bdp;
 	return pkt_received;
 }
 
@@ -2651,8 +2602,8 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 
 	for (q = 0; q < fep->num_rx_queues; q++) {
 		rxq = fep->rx_queue[q];
-		bdp = rxq->rx_bd_base;
-		for (i = 0; i < rxq->rx_ring_size; i++) {
+		bdp = rxq->bd.base;
+		for (i = 0; i < rxq->bd.ring_size; i++) {
 			skb = rxq->rx_skbuff[i];
 			rxq->rx_skbuff[i] = NULL;
 			if (skb) {
@@ -2662,14 +2613,14 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 						 DMA_FROM_DEVICE);
 				dev_kfree_skb(skb);
 			}
-			bdp = fec_enet_get_nextdesc(bdp, fep, q);
+			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 		}
 	}
 
 	for (q = 0; q < fep->num_tx_queues; q++) {
 		txq = fep->tx_queue[q];
-		bdp = txq->tx_bd_base;
-		for (i = 0; i < txq->tx_ring_size; i++) {
+		bdp = txq->bd.base;
+		for (i = 0; i < txq->bd.ring_size; i++) {
 			kfree(txq->tx_bounce[i]);
 			txq->tx_bounce[i] = NULL;
 			skb = txq->tx_skbuff[i];
@@ -2689,7 +2640,7 @@ static void fec_enet_free_queue(struct net_device *ndev)
 		if (fep->tx_queue[i] && fep->tx_queue[i]->tso_hdrs) {
 			txq = fep->tx_queue[i];
 			dma_free_coherent(NULL,
-					  txq->tx_ring_size * TSO_HEADER_SIZE,
+					  txq->bd.ring_size * TSO_HEADER_SIZE,
 					  txq->tso_hdrs,
 					  txq->tso_hdrs_dma);
 		}
@@ -2715,15 +2666,15 @@ static int fec_enet_alloc_queue(struct net_device *ndev)
 		}
 
 		fep->tx_queue[i] = txq;
-		txq->tx_ring_size = TX_RING_SIZE;
-		fep->total_tx_ring_size += fep->tx_queue[i]->tx_ring_size;
+		txq->bd.ring_size = TX_RING_SIZE;
+		fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size;
 
 		txq->tx_stop_threshold = FEC_MAX_SKB_DESCS;
 		txq->tx_wake_threshold =
-				(txq->tx_ring_size - txq->tx_stop_threshold) / 2;
+			(txq->bd.ring_size - txq->tx_stop_threshold) / 2;
 
 		txq->tso_hdrs = dma_alloc_coherent(NULL,
-					txq->tx_ring_size * TSO_HEADER_SIZE,
+					txq->bd.ring_size * TSO_HEADER_SIZE,
 					&txq->tso_hdrs_dma,
 					GFP_KERNEL);
 		if (!txq->tso_hdrs) {
@@ -2740,8 +2691,8 @@ static int fec_enet_alloc_queue(struct net_device *ndev)
 			goto alloc_failed;
 		}
 
-		fep->rx_queue[i]->rx_ring_size = RX_RING_SIZE;
-		fep->total_rx_ring_size += fep->rx_queue[i]->rx_ring_size;
+		fep->rx_queue[i]->bd.ring_size = RX_RING_SIZE;
+		fep->total_rx_ring_size += fep->rx_queue[i]->bd.ring_size;
 	}
 	return ret;
 
@@ -2760,8 +2711,8 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
 	struct fec_enet_priv_rx_q *rxq;
 
 	rxq = fep->rx_queue[queue];
-	bdp = rxq->rx_bd_base;
-	for (i = 0; i < rxq->rx_ring_size; i++) {
+	bdp = rxq->bd.base;
+	for (i = 0; i < rxq->bd.ring_size; i++) {
 		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
 		if (!skb)
 			goto err_alloc;
@@ -2779,11 +2730,11 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
 			ebdp->cbd_esc = BD_ENET_RX_INT;
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 	}
 
 	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep, queue);
+	bdp = fec_enet_get_prevdesc(bdp, &rxq->bd);
 	bdp->cbd_sc |= BD_SC_WRAP;
 	return 0;
 
@@ -2801,8 +2752,8 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
 	struct fec_enet_priv_tx_q *txq;
 
 	txq = fep->tx_queue[queue];
-	bdp = txq->tx_bd_base;
-	for (i = 0; i < txq->tx_ring_size; i++) {
+	bdp = txq->bd.base;
+	for (i = 0; i < txq->bd.ring_size; i++) {
 		txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
 		if (!txq->tx_bounce[i])
 			goto err_alloc;
@@ -2815,11 +2766,11 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
 			ebdp->cbd_esc = BD_ENET_TX_INT;
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 	}
 
 	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep, queue);
+	bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	return 0;
@@ -3110,13 +3061,15 @@ static const struct net_device_ops fec_netdev_ops = {
 static int fec_enet_init(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_enet_priv_tx_q *txq;
-	struct fec_enet_priv_rx_q *rxq;
 	struct bufdesc *cbd_base;
 	dma_addr_t bd_dma;
 	int bd_size;
 	unsigned int i;
+	unsigned dsize = fep->bufdesc_ex ? sizeof(struct bufdesc_ex) :
+			sizeof(struct bufdesc);
+	unsigned dsize_log2 = __fls(dsize);
 
+	WARN_ON(dsize != (1 << dsize_log2));
 #if defined(CONFIG_ARM)
 	fep->rx_align = 0xf;
 	fep->tx_align = 0xf;
@@ -3127,12 +3080,7 @@ static int fec_enet_init(struct net_device *ndev)
 
 	fec_enet_alloc_queue(ndev);
 
-	if (fep->bufdesc_ex)
-		fep->bufdesc_size = sizeof(struct bufdesc_ex);
-	else
-		fep->bufdesc_size = sizeof(struct bufdesc);
-	bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) *
-			fep->bufdesc_size;
+	bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * dsize;
 
 	/* Allocate memory for buffer descriptors. */
 	cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma,
@@ -3150,33 +3098,33 @@ static int fec_enet_init(struct net_device *ndev)
 
 	/* Set receive and transmit descriptor base. */
 	for (i = 0; i < fep->num_rx_queues; i++) {
-		rxq = fep->rx_queue[i];
-		rxq->index = i;
-		rxq->rx_bd_base = (struct bufdesc *)cbd_base;
-		rxq->bd_dma = bd_dma;
-		if (fep->bufdesc_ex) {
-			bd_dma += sizeof(struct bufdesc_ex) * rxq->rx_ring_size;
-			cbd_base = (struct bufdesc *)
-				(((struct bufdesc_ex *)cbd_base) + rxq->rx_ring_size);
-		} else {
-			bd_dma += sizeof(struct bufdesc) * rxq->rx_ring_size;
-			cbd_base += rxq->rx_ring_size;
-		}
+		struct fec_enet_priv_rx_q *rxq = fep->rx_queue[i];
+		unsigned size = dsize * rxq->bd.ring_size;
+
+		rxq->bd.qid = i;
+		rxq->bd.base = cbd_base;
+		rxq->bd.cur = cbd_base;
+		rxq->bd.dma = bd_dma;
+		rxq->bd.dsize = dsize;
+		rxq->bd.dsize_log2 = dsize_log2;
+		bd_dma += size;
+		cbd_base = (struct bufdesc *)(((void *)cbd_base) + size);
+		rxq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize);
 	}
 
 	for (i = 0; i < fep->num_tx_queues; i++) {
-		txq = fep->tx_queue[i];
-		txq->index = i;
-		txq->tx_bd_base = (struct bufdesc *)cbd_base;
-		txq->bd_dma = bd_dma;
-		if (fep->bufdesc_ex) {
-			bd_dma += sizeof(struct bufdesc_ex) * txq->tx_ring_size;
-			cbd_base = (struct bufdesc *)
-			 (((struct bufdesc_ex *)cbd_base) + txq->tx_ring_size);
-		} else {
-			bd_dma += sizeof(struct bufdesc) * txq->tx_ring_size;
-			cbd_base += txq->tx_ring_size;
-		}
+		struct fec_enet_priv_tx_q *txq = fep->tx_queue[i];
+		unsigned size = dsize * txq->bd.ring_size;
+
+		txq->bd.qid = i;
+		txq->bd.base = cbd_base;
+		txq->bd.cur = cbd_base;
+		txq->bd.dma = bd_dma;
+		txq->bd.dsize = dsize;
+		txq->bd.dsize_log2 = dsize_log2;
+		bd_dma += size;
+		cbd_base = (struct bufdesc *)(((void *)cbd_base) + size);
+		txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize);
 	}
 
 
-- 
2.5.0

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

* [PATCH net-next 04/40] net: fec: add struct bufdesc_prop
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

This reduces code and gains speed.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      |  29 ++-
 drivers/net/ethernet/freescale/fec_main.c | 288 ++++++++++++------------------
 2 files changed, 132 insertions(+), 185 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 5144e73..6018d0e4 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -432,33 +432,34 @@ struct bufdesc_ex {
 /* Controller supports RACC register */
 #define FEC_QUIRK_HAS_RACC		(1 << 12)
 
+struct bufdesc_prop {
+	int qid;
+	/* Address of Rx and Tx buffers */
+	struct bufdesc	*base;
+	struct bufdesc	*last;
+	struct bufdesc	*cur;
+	dma_addr_t	dma;
+	unsigned short ring_size;
+	unsigned char dsize;
+	unsigned char dsize_log2;
+};
+
 struct fec_enet_priv_tx_q {
-	int index;
+	struct bufdesc_prop bd;
 	unsigned char *tx_bounce[TX_RING_SIZE];
 	struct  sk_buff *tx_skbuff[TX_RING_SIZE];
 
-	dma_addr_t	bd_dma;
-	struct bufdesc	*tx_bd_base;
-	uint tx_ring_size;
-
 	unsigned short tx_stop_threshold;
 	unsigned short tx_wake_threshold;
 
-	struct bufdesc	*cur_tx;
 	struct bufdesc	*dirty_tx;
 	char *tso_hdrs;
 	dma_addr_t tso_hdrs_dma;
 };
 
 struct fec_enet_priv_rx_q {
-	int index;
+	struct bufdesc_prop bd;
 	struct  sk_buff *rx_skbuff[RX_RING_SIZE];
-
-	dma_addr_t	bd_dma;
-	struct bufdesc	*rx_bd_base;
-	uint rx_ring_size;
-
-	struct bufdesc	*cur_rx;
 };
 
 /* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
@@ -498,8 +499,6 @@ struct fec_enet_private {
 	unsigned long work_ts;
 	unsigned long work_mdio;
 
-	unsigned short bufdesc_size;
-
 	struct	platform_device *pdev;
 
 	int	dev_id;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 8e1f2a6..feff466 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -217,86 +217,38 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 
 #define IS_TSO_HEADER(txq, addr) \
 	((addr >= txq->tso_hdrs_dma) && \
-	(addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE))
+	(addr < txq->tso_hdrs_dma + txq->bd.ring_size * TSO_HEADER_SIZE))
 
 static int mii_cnt;
 
-static inline
-struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp,
-				      struct fec_enet_private *fep,
-				      int queue_id)
-{
-	struct bufdesc *new_bd = bdp + 1;
-	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1;
-	struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id];
-	struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id];
-	struct bufdesc_ex *ex_base;
-	struct bufdesc *base;
-	int ring_size;
-
-	if (bdp >= txq->tx_bd_base) {
-		base = txq->tx_bd_base;
-		ring_size = txq->tx_ring_size;
-		ex_base = (struct bufdesc_ex *)txq->tx_bd_base;
-	} else {
-		base = rxq->rx_bd_base;
-		ring_size = rxq->rx_ring_size;
-		ex_base = (struct bufdesc_ex *)rxq->rx_bd_base;
-	}
-
-	if (fep->bufdesc_ex)
-		return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ?
-			ex_base : ex_new_bd);
-	else
-		return (new_bd >= (base + ring_size)) ?
-			base : new_bd;
-}
-
-static inline
-struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp,
-				      struct fec_enet_private *fep,
-				      int queue_id)
-{
-	struct bufdesc *new_bd = bdp - 1;
-	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1;
-	struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id];
-	struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id];
-	struct bufdesc_ex *ex_base;
-	struct bufdesc *base;
-	int ring_size;
-
-	if (bdp >= txq->tx_bd_base) {
-		base = txq->tx_bd_base;
-		ring_size = txq->tx_ring_size;
-		ex_base = (struct bufdesc_ex *)txq->tx_bd_base;
-	} else {
-		base = rxq->rx_bd_base;
-		ring_size = rxq->rx_ring_size;
-		ex_base = (struct bufdesc_ex *)rxq->rx_bd_base;
-	}
+static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp,
+					     struct bufdesc_prop *bd)
+{
+	return (bdp >= bd->last) ? bd->base
+			: (struct bufdesc *)(((unsigned)bdp) + bd->dsize);
+}
 
-	if (fep->bufdesc_ex)
-		return (struct bufdesc *)((ex_new_bd < ex_base) ?
-			(ex_new_bd + ring_size) : ex_new_bd);
-	else
-		return (new_bd < base) ? (new_bd + ring_size) : new_bd;
+static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp,
+					     struct bufdesc_prop *bd)
+{
+	return (bdp <= bd->base) ? bd->last
+			: (struct bufdesc *)(((unsigned)bdp) - bd->dsize);
 }
 
-static int fec_enet_get_bd_index(struct bufdesc *base, struct bufdesc *bdp,
-				struct fec_enet_private *fep)
+static int fec_enet_get_bd_index(struct bufdesc *bdp,
+				 struct bufdesc_prop *bd)
 {
-	return ((const char *)bdp - (const char *)base) / fep->bufdesc_size;
+	return ((const char *)bdp - (const char *)bd->base) >> bd->dsize_log2;
 }
 
-static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep,
-					struct fec_enet_priv_tx_q *txq)
+static int fec_enet_get_free_txdesc_num(struct fec_enet_priv_tx_q *txq)
 {
 	int entries;
 
-	entries = ((const char *)txq->dirty_tx -
-			(const char *)txq->cur_tx) / fep->bufdesc_size - 1;
+	entries = (((const char *)txq->dirty_tx -
+			(const char *)txq->bd.cur) >> txq->bd.dsize_log2) - 1;
 
-	return entries >= 0 ? entries : entries + txq->tx_ring_size;
+	return entries >= 0 ? entries : entries + txq->bd.ring_size;
 }
 
 static void swap_buffer(void *bufaddr, int len)
@@ -329,18 +281,18 @@ static void fec_dump(struct net_device *ndev)
 	pr_info("Nr     SC     addr       len  SKB\n");
 
 	txq = fep->tx_queue[0];
-	bdp = txq->tx_bd_base;
+	bdp = txq->bd.base;
 
 	do {
 		pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
 			index,
-			bdp == txq->cur_tx ? 'S' : ' ',
+			bdp == txq->bd.cur ? 'S' : ' ',
 			bdp == txq->dirty_tx ? 'H' : ' ',
 			bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
 			txq->tx_skbuff[index]);
-		bdp = fec_enet_get_nextdesc(bdp, fep, 0);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		index++;
-	} while (bdp != txq->tx_bd_base);
+	} while (bdp != txq->bd.base);
 }
 
 static inline bool is_ipv4_pkt(struct sk_buff *skb)
@@ -371,7 +323,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 			     struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct bufdesc *bdp = txq->cur_tx;
+	struct bufdesc *bdp = txq->bd.cur;
 	struct bufdesc_ex *ebdp;
 	int nr_frags = skb_shinfo(skb)->nr_frags;
 	unsigned short queue = skb_get_queue_mapping(skb);
@@ -386,7 +338,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 	for (frag = 0; frag < nr_frags; frag++) {
 		this_frag = &skb_shinfo(skb)->frags[frag];
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		ebdp = (struct bufdesc_ex *)bdp;
 
 		status = bdp->cbd_sc;
@@ -416,7 +368,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 		bufaddr = page_address(this_frag->page.p) + this_frag->page_offset;
 
-		index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
+		index = fec_enet_get_bd_index(bdp, &txq->bd);
 		if (((unsigned long) bufaddr) & fep->tx_align ||
 			fep->quirks & FEC_QUIRK_SWAP_FRAME) {
 			memcpy(txq->tx_bounce[index], bufaddr, frag_len);
@@ -442,9 +394,9 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 	return bdp;
 dma_mapping_error:
-	bdp = txq->cur_tx;
+	bdp = txq->bd.cur;
 	for (i = 0; i < frag; i++) {
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
 				bdp->cbd_datlen, DMA_TO_DEVICE);
 	}
@@ -466,7 +418,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	unsigned int index;
 	int entries_free;
 
-	entries_free = fec_enet_get_free_txdesc_num(fep, txq);
+	entries_free = fec_enet_get_free_txdesc_num(txq);
 	if (entries_free < MAX_SKB_FRAGS + 1) {
 		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
@@ -481,7 +433,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	}
 
 	/* Fill in a Tx ring entry */
-	bdp = txq->cur_tx;
+	bdp = txq->bd.cur;
 	last_bdp = bdp;
 	status = bdp->cbd_sc;
 	status &= ~BD_ENET_TX_STATS;
@@ -491,7 +443,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	buflen = skb_headlen(skb);
 
 	queue = skb_get_queue_mapping(skb);
-	index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
+	index = fec_enet_get_bd_index(bdp, &txq->bd);
 	if (((unsigned long) bufaddr) & fep->tx_align ||
 		fep->quirks & FEC_QUIRK_SWAP_FRAME) {
 		memcpy(txq->tx_bounce[index], skb->data, buflen);
@@ -542,7 +494,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 		ebdp->cbd_esc = estatus;
 	}
 
-	index = fec_enet_get_bd_index(txq->tx_bd_base, last_bdp, fep);
+	index = fec_enet_get_bd_index(last_bdp, &txq->bd);
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
 
@@ -556,15 +508,15 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	bdp->cbd_sc = status;
 
 	/* If this was the last BD in the ring, start at the beginning again. */
-	bdp = fec_enet_get_nextdesc(last_bdp, fep, queue);
+	bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
 
 	skb_tx_timestamp(skb);
 
 	/* Make sure the update to bdp and tx_skbuff are performed before
-	 * cur_tx.
+	 * txq->bd.cur.
 	 */
 	wmb();
-	txq->cur_tx = bdp;
+	txq->bd.cur = bdp;
 
 	/* Trigger transmission start */
 	writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue));
@@ -695,13 +647,13 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	int total_len, data_left;
-	struct bufdesc *bdp = txq->cur_tx;
+	struct bufdesc *bdp = txq->bd.cur;
 	unsigned short queue = skb_get_queue_mapping(skb);
 	struct tso_t tso;
 	unsigned int index = 0;
 	int ret;
 
-	if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(fep, txq)) {
+	if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(txq)) {
 		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "NOT enough BD for TSO!\n");
@@ -721,7 +673,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	while (total_len > 0) {
 		char *hdr;
 
-		index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
+		index = fec_enet_get_bd_index(bdp, &txq->bd);
 		data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
 		total_len -= data_left;
 
@@ -736,9 +688,8 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 			int size;
 
 			size = min_t(int, tso.size, data_left);
-			bdp = fec_enet_get_nextdesc(bdp, fep, queue);
-			index = fec_enet_get_bd_index(txq->tx_bd_base,
-						      bdp, fep);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+			index = fec_enet_get_bd_index(bdp, &txq->bd);
 			ret = fec_enet_txq_put_data_tso(txq, skb, ndev,
 							bdp, index,
 							tso.data, size,
@@ -751,14 +702,14 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 			tso_build_data(skb, &tso, size);
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 	}
 
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
 
 	skb_tx_timestamp(skb);
-	txq->cur_tx = bdp;
+	txq->bd.cur = bdp;
 
 	/* Trigger transmission start */
 	if (!(fep->quirks & FEC_QUIRK_ERR007885) ||
@@ -796,7 +747,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	if (ret)
 		return ret;
 
-	entries_free = fec_enet_get_free_txdesc_num(fep, txq);
+	entries_free = fec_enet_get_free_txdesc_num(txq);
 	if (entries_free <= txq->tx_stop_threshold)
 		netif_tx_stop_queue(nq);
 
@@ -817,32 +768,32 @@ static void fec_enet_bd_init(struct net_device *dev)
 	for (q = 0; q < fep->num_rx_queues; q++) {
 		/* Initialize the receive buffer descriptors. */
 		rxq = fep->rx_queue[q];
-		bdp = rxq->rx_bd_base;
+		bdp = rxq->bd.base;
 
-		for (i = 0; i < rxq->rx_ring_size; i++) {
+		for (i = 0; i < rxq->bd.ring_size; i++) {
 
 			/* Initialize the BD for every fragment in the page. */
 			if (bdp->cbd_bufaddr)
 				bdp->cbd_sc = BD_ENET_RX_EMPTY;
 			else
 				bdp->cbd_sc = 0;
-			bdp = fec_enet_get_nextdesc(bdp, fep, q);
+			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 		}
 
 		/* Set the last buffer to wrap */
-		bdp = fec_enet_get_prevdesc(bdp, fep, q);
+		bdp = fec_enet_get_prevdesc(bdp, &rxq->bd);
 		bdp->cbd_sc |= BD_SC_WRAP;
 
-		rxq->cur_rx = rxq->rx_bd_base;
+		rxq->bd.cur = rxq->bd.base;
 	}
 
 	for (q = 0; q < fep->num_tx_queues; q++) {
 		/* ...and the same for transmit */
 		txq = fep->tx_queue[q];
-		bdp = txq->tx_bd_base;
-		txq->cur_tx = bdp;
+		bdp = txq->bd.base;
+		txq->bd.cur = bdp;
 
-		for (i = 0; i < txq->tx_ring_size; i++) {
+		for (i = 0; i < txq->bd.ring_size; i++) {
 			/* Initialize the BD for every fragment in the page. */
 			bdp->cbd_sc = 0;
 			if (txq->tx_skbuff[i]) {
@@ -850,11 +801,11 @@ static void fec_enet_bd_init(struct net_device *dev)
 				txq->tx_skbuff[i] = NULL;
 			}
 			bdp->cbd_bufaddr = 0;
-			bdp = fec_enet_get_nextdesc(bdp, fep, q);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
 
 		/* Set the last buffer to wrap */
-		bdp = fec_enet_get_prevdesc(bdp, fep, q);
+		bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
 		bdp->cbd_sc |= BD_SC_WRAP;
 		txq->dirty_tx = bdp;
 	}
@@ -878,7 +829,7 @@ static void fec_enet_enable_ring(struct net_device *ndev)
 
 	for (i = 0; i < fep->num_rx_queues; i++) {
 		rxq = fep->rx_queue[i];
-		writel(rxq->bd_dma, fep->hwp + FEC_R_DES_START(i));
+		writel(rxq->bd.dma, fep->hwp + FEC_R_DES_START(i));
 		writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE(i));
 
 		/* enable DMA1/2 */
@@ -889,7 +840,7 @@ static void fec_enet_enable_ring(struct net_device *ndev)
 
 	for (i = 0; i < fep->num_tx_queues; i++) {
 		txq = fep->tx_queue[i];
-		writel(txq->bd_dma, fep->hwp + FEC_X_DES_START(i));
+		writel(txq->bd.dma, fep->hwp + FEC_X_DES_START(i));
 
 		/* enable DMA1/2 */
 		if (i)
@@ -907,7 +858,7 @@ static void fec_enet_reset_skb(struct net_device *ndev)
 	for (i = 0; i < fep->num_tx_queues; i++) {
 		txq = fep->tx_queue[i];
 
-		for (j = 0; j < txq->tx_ring_size; j++) {
+		for (j = 0; j < txq->bd.ring_size; j++) {
 			if (txq->tx_skbuff[j]) {
 				dev_kfree_skb_any(txq->tx_skbuff[j]);
 				txq->tx_skbuff[j] = NULL;
@@ -1218,16 +1169,16 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 	bdp = txq->dirty_tx;
 
 	/* get next bdp of dirty_tx */
-	bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+	bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 
-	while (bdp != READ_ONCE(txq->cur_tx)) {
-		/* Order the load of cur_tx and cbd_sc */
+	while (bdp != READ_ONCE(txq->bd.cur)) {
+		/* Order the load of bd.cur and cbd_sc */
 		rmb();
 		status = READ_ONCE(bdp->cbd_sc);
 		if (status & BD_ENET_TX_READY)
 			break;
 
-		index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
+		index = fec_enet_get_bd_index(bdp, &txq->bd);
 
 		skb = txq->tx_skbuff[index];
 		txq->tx_skbuff[index] = NULL;
@@ -1236,7 +1187,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 					bdp->cbd_datlen, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
 		if (!skb) {
-			bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 			continue;
 		}
 
@@ -1285,19 +1236,19 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 		txq->dirty_tx = bdp;
 
 		/* Update pointer to next buffer descriptor to be transmitted */
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 
 		/* Since we have freed up a buffer, the ring is no longer full
 		 */
 		if (netif_queue_stopped(ndev)) {
-			entries_free = fec_enet_get_free_txdesc_num(fep, txq);
+			entries_free = fec_enet_get_free_txdesc_num(txq);
 			if (entries_free >= txq->tx_wake_threshold)
 				netif_tx_wake_queue(nq);
 		}
 	}
 
 	/* ERR006538: Keep the transmitter going */
-	if (bdp != txq->cur_tx &&
+	if (bdp != txq->bd.cur &&
 	    readl(fep->hwp + FEC_X_DES_ACTIVE(queue_id)) == 0)
 		writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue_id));
 }
@@ -1362,7 +1313,7 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb,
 	return true;
 }
 
-/* During a receive, the cur_rx points to the current incoming buffer.
+/* During a receive, the bd_rx.cur points to the current incoming buffer.
  * When we update through the ring, if the next incoming buffer has
  * not been given to the system, we just set the empty indicator,
  * effectively tossing the packet.
@@ -1395,7 +1346,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 	/* First, grab all of the stats for the incoming packet.
 	 * These get messed up if we get called due to a busy condition.
 	 */
-	bdp = rxq->cur_rx;
+	bdp = rxq->bd.cur;
 
 	while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
 
@@ -1436,7 +1387,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 		pkt_len = bdp->cbd_datlen;
 		ndev->stats.rx_bytes += pkt_len;
 
-		index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep);
+		index = fec_enet_get_bd_index(bdp, &rxq->bd);
 		skb = rxq->rx_skbuff[index];
 
 		/* The packet length includes FCS, but we don't want to
@@ -1533,7 +1484,7 @@ rx_processing_done:
 		}
 
 		/* Update BD pointer to next entry */
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 
 		/* Doing this here will keep the FEC running while we process
 		 * incoming frames.  On a heavily loaded network, we should be
@@ -1541,7 +1492,7 @@ rx_processing_done:
 		 */
 		writel(0, fep->hwp + FEC_R_DES_ACTIVE(queue_id));
 	}
-	rxq->cur_rx = bdp;
+	rxq->bd.cur = bdp;
 	return pkt_received;
 }
 
@@ -2651,8 +2602,8 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 
 	for (q = 0; q < fep->num_rx_queues; q++) {
 		rxq = fep->rx_queue[q];
-		bdp = rxq->rx_bd_base;
-		for (i = 0; i < rxq->rx_ring_size; i++) {
+		bdp = rxq->bd.base;
+		for (i = 0; i < rxq->bd.ring_size; i++) {
 			skb = rxq->rx_skbuff[i];
 			rxq->rx_skbuff[i] = NULL;
 			if (skb) {
@@ -2662,14 +2613,14 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 						 DMA_FROM_DEVICE);
 				dev_kfree_skb(skb);
 			}
-			bdp = fec_enet_get_nextdesc(bdp, fep, q);
+			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 		}
 	}
 
 	for (q = 0; q < fep->num_tx_queues; q++) {
 		txq = fep->tx_queue[q];
-		bdp = txq->tx_bd_base;
-		for (i = 0; i < txq->tx_ring_size; i++) {
+		bdp = txq->bd.base;
+		for (i = 0; i < txq->bd.ring_size; i++) {
 			kfree(txq->tx_bounce[i]);
 			txq->tx_bounce[i] = NULL;
 			skb = txq->tx_skbuff[i];
@@ -2689,7 +2640,7 @@ static void fec_enet_free_queue(struct net_device *ndev)
 		if (fep->tx_queue[i] && fep->tx_queue[i]->tso_hdrs) {
 			txq = fep->tx_queue[i];
 			dma_free_coherent(NULL,
-					  txq->tx_ring_size * TSO_HEADER_SIZE,
+					  txq->bd.ring_size * TSO_HEADER_SIZE,
 					  txq->tso_hdrs,
 					  txq->tso_hdrs_dma);
 		}
@@ -2715,15 +2666,15 @@ static int fec_enet_alloc_queue(struct net_device *ndev)
 		}
 
 		fep->tx_queue[i] = txq;
-		txq->tx_ring_size = TX_RING_SIZE;
-		fep->total_tx_ring_size += fep->tx_queue[i]->tx_ring_size;
+		txq->bd.ring_size = TX_RING_SIZE;
+		fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size;
 
 		txq->tx_stop_threshold = FEC_MAX_SKB_DESCS;
 		txq->tx_wake_threshold =
-				(txq->tx_ring_size - txq->tx_stop_threshold) / 2;
+			(txq->bd.ring_size - txq->tx_stop_threshold) / 2;
 
 		txq->tso_hdrs = dma_alloc_coherent(NULL,
-					txq->tx_ring_size * TSO_HEADER_SIZE,
+					txq->bd.ring_size * TSO_HEADER_SIZE,
 					&txq->tso_hdrs_dma,
 					GFP_KERNEL);
 		if (!txq->tso_hdrs) {
@@ -2740,8 +2691,8 @@ static int fec_enet_alloc_queue(struct net_device *ndev)
 			goto alloc_failed;
 		}
 
-		fep->rx_queue[i]->rx_ring_size = RX_RING_SIZE;
-		fep->total_rx_ring_size += fep->rx_queue[i]->rx_ring_size;
+		fep->rx_queue[i]->bd.ring_size = RX_RING_SIZE;
+		fep->total_rx_ring_size += fep->rx_queue[i]->bd.ring_size;
 	}
 	return ret;
 
@@ -2760,8 +2711,8 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
 	struct fec_enet_priv_rx_q *rxq;
 
 	rxq = fep->rx_queue[queue];
-	bdp = rxq->rx_bd_base;
-	for (i = 0; i < rxq->rx_ring_size; i++) {
+	bdp = rxq->bd.base;
+	for (i = 0; i < rxq->bd.ring_size; i++) {
 		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
 		if (!skb)
 			goto err_alloc;
@@ -2779,11 +2730,11 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
 			ebdp->cbd_esc = BD_ENET_RX_INT;
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 	}
 
 	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep, queue);
+	bdp = fec_enet_get_prevdesc(bdp, &rxq->bd);
 	bdp->cbd_sc |= BD_SC_WRAP;
 	return 0;
 
@@ -2801,8 +2752,8 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
 	struct fec_enet_priv_tx_q *txq;
 
 	txq = fep->tx_queue[queue];
-	bdp = txq->tx_bd_base;
-	for (i = 0; i < txq->tx_ring_size; i++) {
+	bdp = txq->bd.base;
+	for (i = 0; i < txq->bd.ring_size; i++) {
 		txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
 		if (!txq->tx_bounce[i])
 			goto err_alloc;
@@ -2815,11 +2766,11 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
 			ebdp->cbd_esc = BD_ENET_TX_INT;
 		}
 
-		bdp = fec_enet_get_nextdesc(bdp, fep, queue);
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 	}
 
 	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, fep, queue);
+	bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	return 0;
@@ -3110,13 +3061,15 @@ static const struct net_device_ops fec_netdev_ops = {
 static int fec_enet_init(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_enet_priv_tx_q *txq;
-	struct fec_enet_priv_rx_q *rxq;
 	struct bufdesc *cbd_base;
 	dma_addr_t bd_dma;
 	int bd_size;
 	unsigned int i;
+	unsigned dsize = fep->bufdesc_ex ? sizeof(struct bufdesc_ex) :
+			sizeof(struct bufdesc);
+	unsigned dsize_log2 = __fls(dsize);
 
+	WARN_ON(dsize != (1 << dsize_log2));
 #if defined(CONFIG_ARM)
 	fep->rx_align = 0xf;
 	fep->tx_align = 0xf;
@@ -3127,12 +3080,7 @@ static int fec_enet_init(struct net_device *ndev)
 
 	fec_enet_alloc_queue(ndev);
 
-	if (fep->bufdesc_ex)
-		fep->bufdesc_size = sizeof(struct bufdesc_ex);
-	else
-		fep->bufdesc_size = sizeof(struct bufdesc);
-	bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) *
-			fep->bufdesc_size;
+	bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * dsize;
 
 	/* Allocate memory for buffer descriptors. */
 	cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma,
@@ -3150,33 +3098,33 @@ static int fec_enet_init(struct net_device *ndev)
 
 	/* Set receive and transmit descriptor base. */
 	for (i = 0; i < fep->num_rx_queues; i++) {
-		rxq = fep->rx_queue[i];
-		rxq->index = i;
-		rxq->rx_bd_base = (struct bufdesc *)cbd_base;
-		rxq->bd_dma = bd_dma;
-		if (fep->bufdesc_ex) {
-			bd_dma += sizeof(struct bufdesc_ex) * rxq->rx_ring_size;
-			cbd_base = (struct bufdesc *)
-				(((struct bufdesc_ex *)cbd_base) + rxq->rx_ring_size);
-		} else {
-			bd_dma += sizeof(struct bufdesc) * rxq->rx_ring_size;
-			cbd_base += rxq->rx_ring_size;
-		}
+		struct fec_enet_priv_rx_q *rxq = fep->rx_queue[i];
+		unsigned size = dsize * rxq->bd.ring_size;
+
+		rxq->bd.qid = i;
+		rxq->bd.base = cbd_base;
+		rxq->bd.cur = cbd_base;
+		rxq->bd.dma = bd_dma;
+		rxq->bd.dsize = dsize;
+		rxq->bd.dsize_log2 = dsize_log2;
+		bd_dma += size;
+		cbd_base = (struct bufdesc *)(((void *)cbd_base) + size);
+		rxq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize);
 	}
 
 	for (i = 0; i < fep->num_tx_queues; i++) {
-		txq = fep->tx_queue[i];
-		txq->index = i;
-		txq->tx_bd_base = (struct bufdesc *)cbd_base;
-		txq->bd_dma = bd_dma;
-		if (fep->bufdesc_ex) {
-			bd_dma += sizeof(struct bufdesc_ex) * txq->tx_ring_size;
-			cbd_base = (struct bufdesc *)
-			 (((struct bufdesc_ex *)cbd_base) + txq->tx_ring_size);
-		} else {
-			bd_dma += sizeof(struct bufdesc) * txq->tx_ring_size;
-			cbd_base += txq->tx_ring_size;
-		}
+		struct fec_enet_priv_tx_q *txq = fep->tx_queue[i];
+		unsigned size = dsize * txq->bd.ring_size;
+
+		txq->bd.qid = i;
+		txq->bd.base = cbd_base;
+		txq->bd.cur = cbd_base;
+		txq->bd.dma = bd_dma;
+		txq->bd.dsize = dsize;
+		txq->bd.dsize_log2 = dsize_log2;
+		bd_dma += size;
+		cbd_base = (struct bufdesc *)(((void *)cbd_base) + size);
+		txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize);
 	}
 
 
-- 
2.5.0

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

* [PATCH net-next 05/40] net: fec: add variable reg_desc_active to speed things up
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

There is no need for complex macros every time we need to activate
a queue. Also, no need to call skb_get_queue_mapping when we already
know which queue it is using.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      |  7 +----
 drivers/net/ethernet/freescale/fec_main.c | 44 +++++++++++++++++--------------
 2 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 6018d0e4..f8d7fdb 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -294,12 +294,6 @@ struct bufdesc_ex {
 #define FEC_R_BUFF_SIZE(X)	(((X) == 1) ? FEC_R_BUFF_SIZE_1 : \
 				(((X) == 2) ? \
 					FEC_R_BUFF_SIZE_2 : FEC_R_BUFF_SIZE_0))
-#define FEC_R_DES_ACTIVE(X)	(((X) == 1) ? FEC_R_DES_ACTIVE_1 : \
-				(((X) == 2) ? \
-				   FEC_R_DES_ACTIVE_2 : FEC_R_DES_ACTIVE_0))
-#define FEC_X_DES_ACTIVE(X)	(((X) == 1) ? FEC_X_DES_ACTIVE_1 : \
-				(((X) == 2) ? \
-				   FEC_X_DES_ACTIVE_2 : FEC_X_DES_ACTIVE_0))
 
 #define FEC_DMA_CFG(X)		(((X) == 2) ? FEC_DMA_CFG_2 : FEC_DMA_CFG_1)
 
@@ -438,6 +432,7 @@ struct bufdesc_prop {
 	struct bufdesc	*base;
 	struct bufdesc	*last;
 	struct bufdesc	*cur;
+	void __iomem	*reg_desc_active;
 	dma_addr_t	dma;
 	unsigned short ring_size;
 	unsigned char dsize;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index feff466..0e8c8b6 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -326,7 +326,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 	struct bufdesc *bdp = txq->bd.cur;
 	struct bufdesc_ex *ebdp;
 	int nr_frags = skb_shinfo(skb)->nr_frags;
-	unsigned short queue = skb_get_queue_mapping(skb);
 	int frag, frag_len;
 	unsigned short status;
 	unsigned int estatus = 0;
@@ -359,7 +358,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 		if (fep->bufdesc_ex) {
 			if (fep->quirks & FEC_QUIRK_HAS_AVB)
-				estatus |= FEC_TX_BD_FTYPE(queue);
+				estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 			if (skb->ip_summed == CHECKSUM_PARTIAL)
 				estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
 			ebdp->cbd_bdu = 0;
@@ -413,7 +412,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	dma_addr_t addr;
 	unsigned short status;
 	unsigned short buflen;
-	unsigned short queue;
 	unsigned int estatus = 0;
 	unsigned int index;
 	int entries_free;
@@ -442,7 +440,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	bufaddr = skb->data;
 	buflen = skb_headlen(skb);
 
-	queue = skb_get_queue_mapping(skb);
 	index = fec_enet_get_bd_index(bdp, &txq->bd);
 	if (((unsigned long) bufaddr) & fep->tx_align ||
 		fep->quirks & FEC_QUIRK_SWAP_FRAME) {
@@ -485,7 +482,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
 		if (fep->quirks & FEC_QUIRK_HAS_AVB)
-			estatus |= FEC_TX_BD_FTYPE(queue);
+			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
@@ -519,7 +516,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	txq->bd.cur = bdp;
 
 	/* Trigger transmission start */
-	writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue));
+	writel(0, txq->bd.reg_desc_active);
 
 	return 0;
 }
@@ -532,7 +529,6 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc);
-	unsigned short queue = skb_get_queue_mapping(skb);
 	unsigned short status;
 	unsigned int estatus = 0;
 	dma_addr_t addr;
@@ -564,7 +560,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 
 	if (fep->bufdesc_ex) {
 		if (fep->quirks & FEC_QUIRK_HAS_AVB)
-			estatus |= FEC_TX_BD_FTYPE(queue);
+			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
 		ebdp->cbd_bdu = 0;
@@ -593,7 +589,6 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc);
-	unsigned short queue = skb_get_queue_mapping(skb);
 	void *bufaddr;
 	unsigned long dmabuf;
 	unsigned short status;
@@ -628,7 +623,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 
 	if (fep->bufdesc_ex) {
 		if (fep->quirks & FEC_QUIRK_HAS_AVB)
-			estatus |= FEC_TX_BD_FTYPE(queue);
+			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
 		ebdp->cbd_bdu = 0;
@@ -648,7 +643,6 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	int total_len, data_left;
 	struct bufdesc *bdp = txq->bd.cur;
-	unsigned short queue = skb_get_queue_mapping(skb);
 	struct tso_t tso;
 	unsigned int index = 0;
 	int ret;
@@ -713,11 +707,11 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 
 	/* Trigger transmission start */
 	if (!(fep->quirks & FEC_QUIRK_ERR007885) ||
-	    !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) ||
-	    !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) ||
-	    !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) ||
-	    !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)))
-		writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue));
+	    !readl(txq->bd.reg_desc_active) ||
+	    !readl(txq->bd.reg_desc_active) ||
+	    !readl(txq->bd.reg_desc_active) ||
+	    !readl(txq->bd.reg_desc_active))
+		writel(0, txq->bd.reg_desc_active);
 
 	return 0;
 
@@ -817,7 +811,7 @@ static void fec_enet_active_rxring(struct net_device *ndev)
 	int i;
 
 	for (i = 0; i < fep->num_rx_queues; i++)
-		writel(0, fep->hwp + FEC_R_DES_ACTIVE(i));
+		writel(0, fep->rx_queue[i]->bd.reg_desc_active);
 }
 
 static void fec_enet_enable_ring(struct net_device *ndev)
@@ -1249,8 +1243,8 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 
 	/* ERR006538: Keep the transmitter going */
 	if (bdp != txq->bd.cur &&
-	    readl(fep->hwp + FEC_X_DES_ACTIVE(queue_id)) == 0)
-		writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue_id));
+	    readl(txq->bd.reg_desc_active) == 0)
+		writel(0, txq->bd.reg_desc_active);
 }
 
 static void
@@ -1490,7 +1484,7 @@ rx_processing_done:
 		 * incoming frames.  On a heavily loaded network, we should be
 		 * able to keep up at the expense of system resources.
 		 */
-		writel(0, fep->hwp + FEC_R_DES_ACTIVE(queue_id));
+		writel(0, rxq->bd.reg_desc_active);
 	}
 	rxq->bd.cur = bdp;
 	return pkt_received;
@@ -3054,6 +3048,14 @@ static const struct net_device_ops fec_netdev_ops = {
 	.ndo_set_features	= fec_set_features,
 };
 
+const unsigned short offset_des_active_rxq[] = {
+	FEC_R_DES_ACTIVE_0, FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2
+};
+
+const unsigned short offset_des_active_txq[] = {
+	FEC_X_DES_ACTIVE_0, FEC_X_DES_ACTIVE_1, FEC_X_DES_ACTIVE_2
+};
+
  /*
   * XXX:  We need to clean up on failure exits here.
   *
@@ -3107,6 +3109,7 @@ static int fec_enet_init(struct net_device *ndev)
 		rxq->bd.dma = bd_dma;
 		rxq->bd.dsize = dsize;
 		rxq->bd.dsize_log2 = dsize_log2;
+		rxq->bd.reg_desc_active = fep->hwp + offset_des_active_rxq[i];
 		bd_dma += size;
 		cbd_base = (struct bufdesc *)(((void *)cbd_base) + size);
 		rxq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize);
@@ -3122,6 +3125,7 @@ static int fec_enet_init(struct net_device *ndev)
 		txq->bd.dma = bd_dma;
 		txq->bd.dsize = dsize;
 		txq->bd.dsize_log2 = dsize_log2;
+		txq->bd.reg_desc_active = fep->hwp + offset_des_active_txq[i];
 		bd_dma += size;
 		cbd_base = (struct bufdesc *)(((void *)cbd_base) + size);
 		txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize);
-- 
2.5.0

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

* [PATCH net-next 05/40] net: fec: add variable reg_desc_active to speed things up
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

There is no need for complex macros every time we need to activate
a queue. Also, no need to call skb_get_queue_mapping when we already
know which queue it is using.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      |  7 +----
 drivers/net/ethernet/freescale/fec_main.c | 44 +++++++++++++++++--------------
 2 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 6018d0e4..f8d7fdb 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -294,12 +294,6 @@ struct bufdesc_ex {
 #define FEC_R_BUFF_SIZE(X)	(((X) == 1) ? FEC_R_BUFF_SIZE_1 : \
 				(((X) == 2) ? \
 					FEC_R_BUFF_SIZE_2 : FEC_R_BUFF_SIZE_0))
-#define FEC_R_DES_ACTIVE(X)	(((X) == 1) ? FEC_R_DES_ACTIVE_1 : \
-				(((X) == 2) ? \
-				   FEC_R_DES_ACTIVE_2 : FEC_R_DES_ACTIVE_0))
-#define FEC_X_DES_ACTIVE(X)	(((X) == 1) ? FEC_X_DES_ACTIVE_1 : \
-				(((X) == 2) ? \
-				   FEC_X_DES_ACTIVE_2 : FEC_X_DES_ACTIVE_0))
 
 #define FEC_DMA_CFG(X)		(((X) == 2) ? FEC_DMA_CFG_2 : FEC_DMA_CFG_1)
 
@@ -438,6 +432,7 @@ struct bufdesc_prop {
 	struct bufdesc	*base;
 	struct bufdesc	*last;
 	struct bufdesc	*cur;
+	void __iomem	*reg_desc_active;
 	dma_addr_t	dma;
 	unsigned short ring_size;
 	unsigned char dsize;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index feff466..0e8c8b6 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -326,7 +326,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 	struct bufdesc *bdp = txq->bd.cur;
 	struct bufdesc_ex *ebdp;
 	int nr_frags = skb_shinfo(skb)->nr_frags;
-	unsigned short queue = skb_get_queue_mapping(skb);
 	int frag, frag_len;
 	unsigned short status;
 	unsigned int estatus = 0;
@@ -359,7 +358,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 		if (fep->bufdesc_ex) {
 			if (fep->quirks & FEC_QUIRK_HAS_AVB)
-				estatus |= FEC_TX_BD_FTYPE(queue);
+				estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 			if (skb->ip_summed == CHECKSUM_PARTIAL)
 				estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
 			ebdp->cbd_bdu = 0;
@@ -413,7 +412,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	dma_addr_t addr;
 	unsigned short status;
 	unsigned short buflen;
-	unsigned short queue;
 	unsigned int estatus = 0;
 	unsigned int index;
 	int entries_free;
@@ -442,7 +440,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	bufaddr = skb->data;
 	buflen = skb_headlen(skb);
 
-	queue = skb_get_queue_mapping(skb);
 	index = fec_enet_get_bd_index(bdp, &txq->bd);
 	if (((unsigned long) bufaddr) & fep->tx_align ||
 		fep->quirks & FEC_QUIRK_SWAP_FRAME) {
@@ -485,7 +482,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
 		if (fep->quirks & FEC_QUIRK_HAS_AVB)
-			estatus |= FEC_TX_BD_FTYPE(queue);
+			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
@@ -519,7 +516,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	txq->bd.cur = bdp;
 
 	/* Trigger transmission start */
-	writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue));
+	writel(0, txq->bd.reg_desc_active);
 
 	return 0;
 }
@@ -532,7 +529,6 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc);
-	unsigned short queue = skb_get_queue_mapping(skb);
 	unsigned short status;
 	unsigned int estatus = 0;
 	dma_addr_t addr;
@@ -564,7 +560,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 
 	if (fep->bufdesc_ex) {
 		if (fep->quirks & FEC_QUIRK_HAS_AVB)
-			estatus |= FEC_TX_BD_FTYPE(queue);
+			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
 		ebdp->cbd_bdu = 0;
@@ -593,7 +589,6 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc);
-	unsigned short queue = skb_get_queue_mapping(skb);
 	void *bufaddr;
 	unsigned long dmabuf;
 	unsigned short status;
@@ -628,7 +623,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 
 	if (fep->bufdesc_ex) {
 		if (fep->quirks & FEC_QUIRK_HAS_AVB)
-			estatus |= FEC_TX_BD_FTYPE(queue);
+			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
 		ebdp->cbd_bdu = 0;
@@ -648,7 +643,6 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	int total_len, data_left;
 	struct bufdesc *bdp = txq->bd.cur;
-	unsigned short queue = skb_get_queue_mapping(skb);
 	struct tso_t tso;
 	unsigned int index = 0;
 	int ret;
@@ -713,11 +707,11 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 
 	/* Trigger transmission start */
 	if (!(fep->quirks & FEC_QUIRK_ERR007885) ||
-	    !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) ||
-	    !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) ||
-	    !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) ||
-	    !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)))
-		writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue));
+	    !readl(txq->bd.reg_desc_active) ||
+	    !readl(txq->bd.reg_desc_active) ||
+	    !readl(txq->bd.reg_desc_active) ||
+	    !readl(txq->bd.reg_desc_active))
+		writel(0, txq->bd.reg_desc_active);
 
 	return 0;
 
@@ -817,7 +811,7 @@ static void fec_enet_active_rxring(struct net_device *ndev)
 	int i;
 
 	for (i = 0; i < fep->num_rx_queues; i++)
-		writel(0, fep->hwp + FEC_R_DES_ACTIVE(i));
+		writel(0, fep->rx_queue[i]->bd.reg_desc_active);
 }
 
 static void fec_enet_enable_ring(struct net_device *ndev)
@@ -1249,8 +1243,8 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 
 	/* ERR006538: Keep the transmitter going */
 	if (bdp != txq->bd.cur &&
-	    readl(fep->hwp + FEC_X_DES_ACTIVE(queue_id)) == 0)
-		writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue_id));
+	    readl(txq->bd.reg_desc_active) == 0)
+		writel(0, txq->bd.reg_desc_active);
 }
 
 static void
@@ -1490,7 +1484,7 @@ rx_processing_done:
 		 * incoming frames.  On a heavily loaded network, we should be
 		 * able to keep up at the expense of system resources.
 		 */
-		writel(0, fep->hwp + FEC_R_DES_ACTIVE(queue_id));
+		writel(0, rxq->bd.reg_desc_active);
 	}
 	rxq->bd.cur = bdp;
 	return pkt_received;
@@ -3054,6 +3048,14 @@ static const struct net_device_ops fec_netdev_ops = {
 	.ndo_set_features	= fec_set_features,
 };
 
+const unsigned short offset_des_active_rxq[] = {
+	FEC_R_DES_ACTIVE_0, FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2
+};
+
+const unsigned short offset_des_active_txq[] = {
+	FEC_X_DES_ACTIVE_0, FEC_X_DES_ACTIVE_1, FEC_X_DES_ACTIVE_2
+};
+
  /*
   * XXX:  We need to clean up on failure exits here.
   *
@@ -3107,6 +3109,7 @@ static int fec_enet_init(struct net_device *ndev)
 		rxq->bd.dma = bd_dma;
 		rxq->bd.dsize = dsize;
 		rxq->bd.dsize_log2 = dsize_log2;
+		rxq->bd.reg_desc_active = fep->hwp + offset_des_active_rxq[i];
 		bd_dma += size;
 		cbd_base = (struct bufdesc *)(((void *)cbd_base) + size);
 		rxq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize);
@@ -3122,6 +3125,7 @@ static int fec_enet_init(struct net_device *ndev)
 		txq->bd.dma = bd_dma;
 		txq->bd.dsize = dsize;
 		txq->bd.dsize_log2 = dsize_log2;
+		txq->bd.reg_desc_active = fep->hwp + offset_des_active_txq[i];
 		bd_dma += size;
 		cbd_base = (struct bufdesc *)(((void *)cbd_base) + size);
 		txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize);
-- 
2.5.0

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

* [PATCH net-next 06/40] net: fec: don't disable FEC_ENET_TS_TIMER interrupt
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Only the interrupt routine processes this condition.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      | 1 +
 drivers/net/ethernet/freescale/fec_main.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index f8d7fdb..684fe91f 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -359,6 +359,7 @@ struct bufdesc_ex {
 #define FEC_ENET_TS_TIMER       ((uint)0x00008000)
 
 #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | FEC_ENET_TS_TIMER)
+#define FEC_NAPI_IMASK	(FEC_ENET_MII | FEC_ENET_TS_TIMER)
 #define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
 
 /* ENET interrupt coalescing macro define */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 0e8c8b6..e8f35fb 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1545,7 +1545,7 @@ fec_enet_interrupt(int irq, void *dev_id)
 
 		if (napi_schedule_prep(&fep->napi)) {
 			/* Disable the NAPI interrupts */
-			writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
+			writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK);
 			__napi_schedule(&fep->napi);
 		}
 	}
-- 
2.5.0

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

* [PATCH net-next 06/40] net: fec: don't disable FEC_ENET_TS_TIMER interrupt
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Only the interrupt routine processes this condition.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      | 1 +
 drivers/net/ethernet/freescale/fec_main.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index f8d7fdb..684fe91f 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -359,6 +359,7 @@ struct bufdesc_ex {
 #define FEC_ENET_TS_TIMER       ((uint)0x00008000)
 
 #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | FEC_ENET_TS_TIMER)
+#define FEC_NAPI_IMASK	(FEC_ENET_MII | FEC_ENET_TS_TIMER)
 #define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
 
 /* ENET interrupt coalescing macro define */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 0e8c8b6..e8f35fb 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1545,7 +1545,7 @@ fec_enet_interrupt(int irq, void *dev_id)
 
 		if (napi_schedule_prep(&fep->napi)) {
 			/* Disable the NAPI interrupts */
-			writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
+			writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK);
 			__napi_schedule(&fep->napi);
 		}
 	}
-- 
2.5.0

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

* [PATCH net-next 07/40] net: fec: don't transfer ownership until descriptor write is complete
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index e8f35fb..b87f80d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -388,6 +388,10 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 		bdp->cbd_bufaddr = addr;
 		bdp->cbd_datlen = frag_len;
+		/* Make sure the updates to rest of the descriptor are
+		 * performed before transferring ownership.
+		 */
+		wmb();
 		bdp->cbd_sc = status;
 	}
 
@@ -497,6 +501,10 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 
 	bdp->cbd_datlen = buflen;
 	bdp->cbd_bufaddr = addr;
+	/* Make sure the updates to rest of the descriptor are performed before
+	 * transferring ownership.
+	 */
+	wmb();
 
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
 	 * it's the last BD of the frame, and to put the CRC on the end.
@@ -1467,7 +1475,6 @@ rx_processing_done:
 
 		/* Mark the buffer empty */
 		status |= BD_ENET_RX_EMPTY;
-		bdp->cbd_sc = status;
 
 		if (fep->bufdesc_ex) {
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
@@ -1476,6 +1483,11 @@ rx_processing_done:
 			ebdp->cbd_prot = 0;
 			ebdp->cbd_bdu = 0;
 		}
+		/* Make sure the updates to rest of the descriptor are
+		 * performed before transferring ownership.
+		 */
+		wmb();
+		bdp->cbd_sc = status;
 
 		/* Update BD pointer to next entry */
 		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
-- 
2.5.0

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

* [PATCH net-next 07/40] net: fec: don't transfer ownership until descriptor write is complete
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index e8f35fb..b87f80d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -388,6 +388,10 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 		bdp->cbd_bufaddr = addr;
 		bdp->cbd_datlen = frag_len;
+		/* Make sure the updates to rest of the descriptor are
+		 * performed before transferring ownership.
+		 */
+		wmb();
 		bdp->cbd_sc = status;
 	}
 
@@ -497,6 +501,10 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 
 	bdp->cbd_datlen = buflen;
 	bdp->cbd_bufaddr = addr;
+	/* Make sure the updates to rest of the descriptor are performed before
+	 * transferring ownership.
+	 */
+	wmb();
 
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
 	 * it's the last BD of the frame, and to put the CRC on the end.
@@ -1467,7 +1475,6 @@ rx_processing_done:
 
 		/* Mark the buffer empty */
 		status |= BD_ENET_RX_EMPTY;
-		bdp->cbd_sc = status;
 
 		if (fep->bufdesc_ex) {
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
@@ -1476,6 +1483,11 @@ rx_processing_done:
 			ebdp->cbd_prot = 0;
 			ebdp->cbd_bdu = 0;
 		}
+		/* Make sure the updates to rest of the descriptor are
+		 * performed before transferring ownership.
+		 */
+		wmb();
+		bdp->cbd_sc = status;
 
 		/* Update BD pointer to next entry */
 		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
-- 
2.5.0

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

* [PATCH net-next 08/40] net: fec: move cbd_bufaddr assignment closer to the mapping function
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, andrew, linux, Troy Kisky, laci, l.stach,
	shawnguo, linux-arm-kernel, tremyfr

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index b87f80d..15a93f90 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -476,6 +476,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 				estatus |= BD_ENET_TX_TS;
 		}
 	}
+	bdp->cbd_bufaddr = addr;
+	bdp->cbd_datlen = buflen;
 
 	if (fep->bufdesc_ex) {
 
@@ -499,8 +501,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
 
-	bdp->cbd_datlen = buflen;
-	bdp->cbd_bufaddr = addr;
 	/* Make sure the updates to rest of the descriptor are performed before
 	 * transferring ownership.
 	 */
-- 
2.5.0

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

* [PATCH net-next 08/40] net: fec: move cbd_bufaddr assignment closer to the mapping function
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index b87f80d..15a93f90 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -476,6 +476,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 				estatus |= BD_ENET_TX_TS;
 		}
 	}
+	bdp->cbd_bufaddr = addr;
+	bdp->cbd_datlen = buflen;
 
 	if (fep->bufdesc_ex) {
 
@@ -499,8 +501,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
 
-	bdp->cbd_datlen = buflen;
-	bdp->cbd_bufaddr = addr;
 	/* Make sure the updates to rest of the descriptor are performed before
 	 * transferring ownership.
 	 */
-- 
2.5.0

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

* [PATCH net-next 09/40] net: fec: only check queue 0 if RXF_0/TXF_0 interrupt is set
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 15a93f90..3ed79fd 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1523,14 +1523,14 @@ fec_enet_collect_events(struct fec_enet_private *fep, uint int_events)
 	if (int_events == 0)
 		return false;
 
-	if (int_events & FEC_ENET_RXF)
+	if (int_events & FEC_ENET_RXF_0)
 		fep->work_rx |= (1 << 2);
 	if (int_events & FEC_ENET_RXF_1)
 		fep->work_rx |= (1 << 0);
 	if (int_events & FEC_ENET_RXF_2)
 		fep->work_rx |= (1 << 1);
 
-	if (int_events & FEC_ENET_TXF)
+	if (int_events & FEC_ENET_TXF_0)
 		fep->work_tx |= (1 << 2);
 	if (int_events & FEC_ENET_TXF_1)
 		fep->work_tx |= (1 << 0);
-- 
2.5.0

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

* [PATCH net-next 09/40] net: fec: only check queue 0 if RXF_0/TXF_0 interrupt is set
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 15a93f90..3ed79fd 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1523,14 +1523,14 @@ fec_enet_collect_events(struct fec_enet_private *fep, uint int_events)
 	if (int_events == 0)
 		return false;
 
-	if (int_events & FEC_ENET_RXF)
+	if (int_events & FEC_ENET_RXF_0)
 		fep->work_rx |= (1 << 2);
 	if (int_events & FEC_ENET_RXF_1)
 		fep->work_rx |= (1 << 0);
 	if (int_events & FEC_ENET_RXF_2)
 		fep->work_rx |= (1 << 1);
 
-	if (int_events & FEC_ENET_TXF)
+	if (int_events & FEC_ENET_TXF_0)
 		fep->work_tx |= (1 << 2);
 	if (int_events & FEC_ENET_TXF_1)
 		fep->work_tx |= (1 << 0);
-- 
2.5.0

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

* [PATCH net-next 10/40] net: fec: pass rxq to fec_enet_rx_queue instead of queue_id
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

The queue_id is the qid member of struct bufdesc_prop.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 3ed79fd..01b9740 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1320,11 +1320,9 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb,
  * not been given to the system, we just set the empty indicator,
  * effectively tossing the packet.
  */
-static int
-fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
+static int fec_rxq(struct net_device *ndev, struct fec_enet_private *fep,
+		   struct fec_enet_priv_rx_q *rxq, int budget)
 {
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_enet_priv_rx_q *rxq;
 	struct bufdesc *bdp;
 	unsigned short status;
 	struct  sk_buff *skb_new = NULL;
@@ -1342,8 +1340,6 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 #ifdef CONFIG_M532x
 	flush_cache_all();
 #endif
-	queue_id = FEC_ENET_GET_QUQUE(queue_id);
-	rxq = fep->rx_queue[queue_id];
 
 	/* First, grab all of the stats for the incoming packet.
 	 * These get messed up if we get called due to a busy condition.
@@ -1508,11 +1504,12 @@ fec_enet_rx(struct net_device *ndev, int budget)
 	int     pkt_received = 0;
 	u16	queue_id;
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct fec_enet_priv_rx_q *rxq;
 
 	for_each_set_bit(queue_id, &fep->work_rx, FEC_ENET_MAX_RX_QS) {
 		clear_bit(queue_id, &fep->work_rx);
-		pkt_received += fec_enet_rx_queue(ndev,
-					budget - pkt_received, queue_id);
+		rxq = fep->rx_queue[FEC_ENET_GET_QUQUE(queue_id)];
+		pkt_received += fec_rxq(ndev, fep, rxq, budget - pkt_received);
 	}
 	return pkt_received;
 }
-- 
2.5.0

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

* [PATCH net-next 10/40] net: fec: pass rxq to fec_enet_rx_queue instead of queue_id
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

The queue_id is the qid member of struct bufdesc_prop.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 3ed79fd..01b9740 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1320,11 +1320,9 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb,
  * not been given to the system, we just set the empty indicator,
  * effectively tossing the packet.
  */
-static int
-fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
+static int fec_rxq(struct net_device *ndev, struct fec_enet_private *fep,
+		   struct fec_enet_priv_rx_q *rxq, int budget)
 {
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_enet_priv_rx_q *rxq;
 	struct bufdesc *bdp;
 	unsigned short status;
 	struct  sk_buff *skb_new = NULL;
@@ -1342,8 +1340,6 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
 #ifdef CONFIG_M532x
 	flush_cache_all();
 #endif
-	queue_id = FEC_ENET_GET_QUQUE(queue_id);
-	rxq = fep->rx_queue[queue_id];
 
 	/* First, grab all of the stats for the incoming packet.
 	 * These get messed up if we get called due to a busy condition.
@@ -1508,11 +1504,12 @@ fec_enet_rx(struct net_device *ndev, int budget)
 	int     pkt_received = 0;
 	u16	queue_id;
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct fec_enet_priv_rx_q *rxq;
 
 	for_each_set_bit(queue_id, &fep->work_rx, FEC_ENET_MAX_RX_QS) {
 		clear_bit(queue_id, &fep->work_rx);
-		pkt_received += fec_enet_rx_queue(ndev,
-					budget - pkt_received, queue_id);
+		rxq = fep->rx_queue[FEC_ENET_GET_QUQUE(queue_id)];
+		pkt_received += fec_rxq(ndev, fep, rxq, budget - pkt_received);
 	}
 	return pkt_received;
 }
-- 
2.5.0

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

* [PATCH net-next 11/40] net: fec: pass txq to fec_enet_tx_queue instead of queue_id
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

queue_id is the qid member of struct bufdesc_prop.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 01b9740..711a8d6 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1149,25 +1149,18 @@ fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
 	hwtstamps->hwtstamp = ns_to_ktime(ns);
 }
 
-static void
-fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
+static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
+		    struct fec_enet_priv_tx_q *txq)
 {
-	struct	fec_enet_private *fep;
 	struct bufdesc *bdp;
 	unsigned short status;
 	struct	sk_buff	*skb;
-	struct fec_enet_priv_tx_q *txq;
 	struct netdev_queue *nq;
 	int	index = 0;
 	int	entries_free;
 
-	fep = netdev_priv(ndev);
-
-	queue_id = FEC_ENET_GET_QUQUE(queue_id);
-
-	txq = fep->tx_queue[queue_id];
 	/* get next bdp of dirty_tx */
-	nq = netdev_get_tx_queue(ndev, queue_id);
+	nq = netdev_get_tx_queue(ndev, txq->bd.qid);
 	bdp = txq->dirty_tx;
 
 	/* get next bdp of dirty_tx */
@@ -1259,11 +1252,13 @@ static void
 fec_enet_tx(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct fec_enet_priv_tx_q *txq;
 	u16 queue_id;
 	/* First process class A queue, then Class B and Best Effort queue */
 	for_each_set_bit(queue_id, &fep->work_tx, FEC_ENET_MAX_TX_QS) {
 		clear_bit(queue_id, &fep->work_tx);
-		fec_enet_tx_queue(ndev, queue_id);
+		txq = fep->tx_queue[FEC_ENET_GET_QUQUE(queue_id)];
+		fec_txq(ndev, fep, txq);
 	}
 	return;
 }
-- 
2.5.0

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

* [PATCH net-next 11/40] net: fec: pass txq to fec_enet_tx_queue instead of queue_id
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

queue_id is the qid member of struct bufdesc_prop.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 01b9740..711a8d6 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1149,25 +1149,18 @@ fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
 	hwtstamps->hwtstamp = ns_to_ktime(ns);
 }
 
-static void
-fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
+static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
+		    struct fec_enet_priv_tx_q *txq)
 {
-	struct	fec_enet_private *fep;
 	struct bufdesc *bdp;
 	unsigned short status;
 	struct	sk_buff	*skb;
-	struct fec_enet_priv_tx_q *txq;
 	struct netdev_queue *nq;
 	int	index = 0;
 	int	entries_free;
 
-	fep = netdev_priv(ndev);
-
-	queue_id = FEC_ENET_GET_QUQUE(queue_id);
-
-	txq = fep->tx_queue[queue_id];
 	/* get next bdp of dirty_tx */
-	nq = netdev_get_tx_queue(ndev, queue_id);
+	nq = netdev_get_tx_queue(ndev, txq->bd.qid);
 	bdp = txq->dirty_tx;
 
 	/* get next bdp of dirty_tx */
@@ -1259,11 +1252,13 @@ static void
 fec_enet_tx(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct fec_enet_priv_tx_q *txq;
 	u16 queue_id;
 	/* First process class A queue, then Class B and Best Effort queue */
 	for_each_set_bit(queue_id, &fep->work_tx, FEC_ENET_MAX_TX_QS) {
 		clear_bit(queue_id, &fep->work_tx);
-		fec_enet_tx_queue(ndev, queue_id);
+		txq = fep->tx_queue[FEC_ENET_GET_QUQUE(queue_id)];
+		fec_txq(ndev, fep, txq);
 	}
 	return;
 }
-- 
2.5.0

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

* [PATCH net-next 12/40] net: fec: reduce interrupts
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

By clearing the NAPI interrupts in the NAPI routine
and not in the interrupt handler, we can reduce the
number of interrupts. We also don't need any status
variables as the registers are still valid.

Also, notice that if budget pkts are received, the
next call to fec_enet_rx_napi will now continue to
receive the previously pending packets.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      |   6 +-
 drivers/net/ethernet/freescale/fec_main.c | 127 ++++++++++++------------------
 2 files changed, 50 insertions(+), 83 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 684fe91f..be0e3d9 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -489,11 +489,7 @@ struct fec_enet_private {
 
 	unsigned int total_tx_ring_size;
 	unsigned int total_rx_ring_size;
-
-	unsigned long work_tx;
-	unsigned long work_rx;
-	unsigned long work_ts;
-	unsigned long work_mdio;
+	uint	events;
 
 	struct	platform_device *pdev;
 
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 711a8d6..8bebf01 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -70,8 +70,6 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
 
 #define DRIVER_NAME	"fec"
 
-#define FEC_ENET_GET_QUQUE(_x) ((_x == 0) ? 1 : ((_x == 1) ? 2 : 0))
-
 /* Pause frame feild and FIFO threshold */
 #define FEC_ENET_FCE	(1 << 5)
 #define FEC_ENET_RSEM_V	0x84
@@ -1248,21 +1246,6 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 		writel(0, txq->bd.reg_desc_active);
 }
 
-static void
-fec_enet_tx(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_enet_priv_tx_q *txq;
-	u16 queue_id;
-	/* First process class A queue, then Class B and Best Effort queue */
-	for_each_set_bit(queue_id, &fep->work_tx, FEC_ENET_MAX_TX_QS) {
-		clear_bit(queue_id, &fep->work_tx);
-		txq = fep->tx_queue[FEC_ENET_GET_QUQUE(queue_id)];
-		fec_txq(ndev, fep, txq);
-	}
-	return;
-}
-
 static int
 fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff *skb)
 {
@@ -1493,92 +1476,80 @@ rx_processing_done:
 	return pkt_received;
 }
 
-static int
-fec_enet_rx(struct net_device *ndev, int budget)
-{
-	int     pkt_received = 0;
-	u16	queue_id;
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_enet_priv_rx_q *rxq;
-
-	for_each_set_bit(queue_id, &fep->work_rx, FEC_ENET_MAX_RX_QS) {
-		clear_bit(queue_id, &fep->work_rx);
-		rxq = fep->rx_queue[FEC_ENET_GET_QUQUE(queue_id)];
-		pkt_received += fec_rxq(ndev, fep, rxq, budget - pkt_received);
-	}
-	return pkt_received;
-}
-
-static bool
-fec_enet_collect_events(struct fec_enet_private *fep, uint int_events)
-{
-	if (int_events == 0)
-		return false;
-
-	if (int_events & FEC_ENET_RXF_0)
-		fep->work_rx |= (1 << 2);
-	if (int_events & FEC_ENET_RXF_1)
-		fep->work_rx |= (1 << 0);
-	if (int_events & FEC_ENET_RXF_2)
-		fep->work_rx |= (1 << 1);
-
-	if (int_events & FEC_ENET_TXF_0)
-		fep->work_tx |= (1 << 2);
-	if (int_events & FEC_ENET_TXF_1)
-		fep->work_tx |= (1 << 0);
-	if (int_events & FEC_ENET_TXF_2)
-		fep->work_tx |= (1 << 1);
-
-	return true;
-}
-
 static irqreturn_t
 fec_enet_interrupt(int irq, void *dev_id)
 {
 	struct net_device *ndev = dev_id;
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	uint int_events;
-	irqreturn_t ret = IRQ_NONE;
+	uint eir = readl(fep->hwp + FEC_IEVENT);
+	uint int_events = eir & readl(fep->hwp + FEC_IMASK);
 
-	int_events = readl(fep->hwp + FEC_IEVENT);
-	writel(int_events, fep->hwp + FEC_IEVENT);
-	fec_enet_collect_events(fep, int_events);
-
-	if ((fep->work_tx || fep->work_rx) && fep->link) {
-		ret = IRQ_HANDLED;
+	if (!int_events)
+		return IRQ_NONE;
 
+	if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
 		if (napi_schedule_prep(&fep->napi)) {
 			/* Disable the NAPI interrupts */
 			writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK);
 			__napi_schedule(&fep->napi);
+			int_events &= ~(FEC_ENET_RXF | FEC_ENET_TXF);
+			if (!int_events)
+				return IRQ_HANDLED;
+		} else {
+			fep->events |= int_events;
+			pr_info("%s: couldn't schedule NAPI\n", __func__);
 		}
 	}
 
-	if (int_events & FEC_ENET_MII) {
-		ret = IRQ_HANDLED;
+	writel(int_events, fep->hwp + FEC_IEVENT);
+	if (int_events & FEC_ENET_MII)
 		complete(&fep->mdio_done);
-	}
 
-	if (fep->ptp_clock)
+	if ((int_events & FEC_ENET_TS_TIMER) && fep->ptp_clock)
 		fec_ptp_check_pps_event(fep);
-
-	return ret;
+	return IRQ_HANDLED;
 }
 
 static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
 {
 	struct net_device *ndev = napi->dev;
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	int pkts;
-
-	pkts = fec_enet_rx(ndev, budget);
+	int pkts = 0;
+	uint events;
 
-	fec_enet_tx(ndev);
+	do {
+		events = readl(fep->hwp + FEC_IEVENT);
+		if (fep->events) {
+			events |= fep->events;
+			fep->events = 0;
+		}
+		events &= FEC_ENET_RXF | FEC_ENET_TXF;
+		if (!events) {
+			if (budget) {
+				napi_complete(napi);
+				writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+			}
+			return pkts;
+		}
 
-	if (pkts < budget) {
-		napi_complete(napi);
-		writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-	}
+		writel(events, fep->hwp + FEC_IEVENT);
+		if (events & FEC_ENET_RXF_1)
+			pkts += fec_rxq(ndev, fep, fep->rx_queue[1],
+					budget - pkts);
+		if (events & FEC_ENET_RXF_2)
+			pkts += fec_rxq(ndev, fep, fep->rx_queue[2],
+					budget - pkts);
+		if (events & FEC_ENET_RXF_0)
+			pkts += fec_rxq(ndev, fep, fep->rx_queue[0],
+					budget - pkts);
+		if (events & FEC_ENET_TXF_1)
+			fec_txq(ndev, fep, fep->tx_queue[1]);
+		if (events & FEC_ENET_TXF_2)
+			fec_txq(ndev, fep, fep->tx_queue[2]);
+		if (events & FEC_ENET_TXF_0)
+			fec_txq(ndev, fep, fep->tx_queue[0]);
+	} while (pkts < budget);
+	fep->events |= events & FEC_ENET_RXF;	/* save for next callback */
 	return pkts;
 }
 
-- 
2.5.0

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

* [PATCH net-next 12/40] net: fec: reduce interrupts
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

By clearing the NAPI interrupts in the NAPI routine
and not in the interrupt handler, we can reduce the
number of interrupts. We also don't need any status
variables as the registers are still valid.

Also, notice that if budget pkts are received, the
next call to fec_enet_rx_napi will now continue to
receive the previously pending packets.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      |   6 +-
 drivers/net/ethernet/freescale/fec_main.c | 127 ++++++++++++------------------
 2 files changed, 50 insertions(+), 83 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 684fe91f..be0e3d9 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -489,11 +489,7 @@ struct fec_enet_private {
 
 	unsigned int total_tx_ring_size;
 	unsigned int total_rx_ring_size;
-
-	unsigned long work_tx;
-	unsigned long work_rx;
-	unsigned long work_ts;
-	unsigned long work_mdio;
+	uint	events;
 
 	struct	platform_device *pdev;
 
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 711a8d6..8bebf01 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -70,8 +70,6 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
 
 #define DRIVER_NAME	"fec"
 
-#define FEC_ENET_GET_QUQUE(_x) ((_x == 0) ? 1 : ((_x == 1) ? 2 : 0))
-
 /* Pause frame feild and FIFO threshold */
 #define FEC_ENET_FCE	(1 << 5)
 #define FEC_ENET_RSEM_V	0x84
@@ -1248,21 +1246,6 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 		writel(0, txq->bd.reg_desc_active);
 }
 
-static void
-fec_enet_tx(struct net_device *ndev)
-{
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_enet_priv_tx_q *txq;
-	u16 queue_id;
-	/* First process class A queue, then Class B and Best Effort queue */
-	for_each_set_bit(queue_id, &fep->work_tx, FEC_ENET_MAX_TX_QS) {
-		clear_bit(queue_id, &fep->work_tx);
-		txq = fep->tx_queue[FEC_ENET_GET_QUQUE(queue_id)];
-		fec_txq(ndev, fep, txq);
-	}
-	return;
-}
-
 static int
 fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff *skb)
 {
@@ -1493,92 +1476,80 @@ rx_processing_done:
 	return pkt_received;
 }
 
-static int
-fec_enet_rx(struct net_device *ndev, int budget)
-{
-	int     pkt_received = 0;
-	u16	queue_id;
-	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_enet_priv_rx_q *rxq;
-
-	for_each_set_bit(queue_id, &fep->work_rx, FEC_ENET_MAX_RX_QS) {
-		clear_bit(queue_id, &fep->work_rx);
-		rxq = fep->rx_queue[FEC_ENET_GET_QUQUE(queue_id)];
-		pkt_received += fec_rxq(ndev, fep, rxq, budget - pkt_received);
-	}
-	return pkt_received;
-}
-
-static bool
-fec_enet_collect_events(struct fec_enet_private *fep, uint int_events)
-{
-	if (int_events == 0)
-		return false;
-
-	if (int_events & FEC_ENET_RXF_0)
-		fep->work_rx |= (1 << 2);
-	if (int_events & FEC_ENET_RXF_1)
-		fep->work_rx |= (1 << 0);
-	if (int_events & FEC_ENET_RXF_2)
-		fep->work_rx |= (1 << 1);
-
-	if (int_events & FEC_ENET_TXF_0)
-		fep->work_tx |= (1 << 2);
-	if (int_events & FEC_ENET_TXF_1)
-		fep->work_tx |= (1 << 0);
-	if (int_events & FEC_ENET_TXF_2)
-		fep->work_tx |= (1 << 1);
-
-	return true;
-}
-
 static irqreturn_t
 fec_enet_interrupt(int irq, void *dev_id)
 {
 	struct net_device *ndev = dev_id;
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	uint int_events;
-	irqreturn_t ret = IRQ_NONE;
+	uint eir = readl(fep->hwp + FEC_IEVENT);
+	uint int_events = eir & readl(fep->hwp + FEC_IMASK);
 
-	int_events = readl(fep->hwp + FEC_IEVENT);
-	writel(int_events, fep->hwp + FEC_IEVENT);
-	fec_enet_collect_events(fep, int_events);
-
-	if ((fep->work_tx || fep->work_rx) && fep->link) {
-		ret = IRQ_HANDLED;
+	if (!int_events)
+		return IRQ_NONE;
 
+	if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
 		if (napi_schedule_prep(&fep->napi)) {
 			/* Disable the NAPI interrupts */
 			writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK);
 			__napi_schedule(&fep->napi);
+			int_events &= ~(FEC_ENET_RXF | FEC_ENET_TXF);
+			if (!int_events)
+				return IRQ_HANDLED;
+		} else {
+			fep->events |= int_events;
+			pr_info("%s: couldn't schedule NAPI\n", __func__);
 		}
 	}
 
-	if (int_events & FEC_ENET_MII) {
-		ret = IRQ_HANDLED;
+	writel(int_events, fep->hwp + FEC_IEVENT);
+	if (int_events & FEC_ENET_MII)
 		complete(&fep->mdio_done);
-	}
 
-	if (fep->ptp_clock)
+	if ((int_events & FEC_ENET_TS_TIMER) && fep->ptp_clock)
 		fec_ptp_check_pps_event(fep);
-
-	return ret;
+	return IRQ_HANDLED;
 }
 
 static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
 {
 	struct net_device *ndev = napi->dev;
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	int pkts;
-
-	pkts = fec_enet_rx(ndev, budget);
+	int pkts = 0;
+	uint events;
 
-	fec_enet_tx(ndev);
+	do {
+		events = readl(fep->hwp + FEC_IEVENT);
+		if (fep->events) {
+			events |= fep->events;
+			fep->events = 0;
+		}
+		events &= FEC_ENET_RXF | FEC_ENET_TXF;
+		if (!events) {
+			if (budget) {
+				napi_complete(napi);
+				writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+			}
+			return pkts;
+		}
 
-	if (pkts < budget) {
-		napi_complete(napi);
-		writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-	}
+		writel(events, fep->hwp + FEC_IEVENT);
+		if (events & FEC_ENET_RXF_1)
+			pkts += fec_rxq(ndev, fep, fep->rx_queue[1],
+					budget - pkts);
+		if (events & FEC_ENET_RXF_2)
+			pkts += fec_rxq(ndev, fep, fep->rx_queue[2],
+					budget - pkts);
+		if (events & FEC_ENET_RXF_0)
+			pkts += fec_rxq(ndev, fep, fep->rx_queue[0],
+					budget - pkts);
+		if (events & FEC_ENET_TXF_1)
+			fec_txq(ndev, fep, fep->tx_queue[1]);
+		if (events & FEC_ENET_TXF_2)
+			fec_txq(ndev, fep, fep->tx_queue[2]);
+		if (events & FEC_ENET_TXF_0)
+			fec_txq(ndev, fep, fep->tx_queue[0]);
+	} while (pkts < budget);
+	fep->events |= events & FEC_ENET_RXF;	/* save for next callback */
 	return pkts;
 }
 
-- 
2.5.0

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

* [PATCH net-next 13/40] net: fec: split off napi routine with 3 queues
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

If we only have 1 tx/rx queue, we need not check
the other queues.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 39 +++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 8bebf01..04b1fb7 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1510,7 +1510,7 @@ fec_enet_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
+static int fec_enet_napi_q3(struct napi_struct *napi, int budget)
 {
 	struct net_device *ndev = napi->dev;
 	struct fec_enet_private *fep = netdev_priv(ndev);
@@ -1553,6 +1553,39 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
 	return pkts;
 }
 
+static int fec_enet_napi_q1(struct napi_struct *napi, int budget)
+{
+	struct net_device *ndev = napi->dev;
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	int pkts = 0;
+	uint events;
+
+	do {
+		events = readl(fep->hwp + FEC_IEVENT);
+		if (fep->events) {
+			events |= fep->events;
+			fep->events = 0;
+		}
+		events &= FEC_ENET_RXF_0 | FEC_ENET_TXF_0;
+		if (!events) {
+			if (budget) {
+				napi_complete(napi);
+				writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+			}
+			return pkts;
+		}
+
+		writel(events, fep->hwp + FEC_IEVENT);
+		if (events & FEC_ENET_RXF_0)
+			pkts += fec_rxq(ndev, fep, fep->rx_queue[0],
+					budget - pkts);
+		if (events & FEC_ENET_TXF_0)
+			fec_txq(ndev, fep, fep->tx_queue[0]);
+	} while (pkts < budget);
+	fep->events |= FEC_ENET_RXF_0;	/* save for next callback */
+	return pkts;
+}
+
 /* ------------------------------------------------------------------------- */
 static void fec_get_mac(struct net_device *ndev)
 {
@@ -3113,7 +3146,9 @@ static int fec_enet_init(struct net_device *ndev)
 	ndev->ethtool_ops = &fec_enet_ethtool_ops;
 
 	writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
-	netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, NAPI_POLL_WEIGHT);
+	netif_napi_add(ndev, &fep->napi, (fep->num_rx_queues |
+		       fep->num_tx_queues) == 1 ? fec_enet_napi_q1 :
+		       fec_enet_napi_q3, NAPI_POLL_WEIGHT);
 
 	if (fep->quirks & FEC_QUIRK_HAS_VLAN)
 		/* enable hw VLAN support */
-- 
2.5.0

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

* [PATCH net-next 13/40] net: fec: split off napi routine with 3 queues
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

If we only have 1 tx/rx queue, we need not check
the other queues.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 39 +++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 8bebf01..04b1fb7 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1510,7 +1510,7 @@ fec_enet_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
+static int fec_enet_napi_q3(struct napi_struct *napi, int budget)
 {
 	struct net_device *ndev = napi->dev;
 	struct fec_enet_private *fep = netdev_priv(ndev);
@@ -1553,6 +1553,39 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
 	return pkts;
 }
 
+static int fec_enet_napi_q1(struct napi_struct *napi, int budget)
+{
+	struct net_device *ndev = napi->dev;
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	int pkts = 0;
+	uint events;
+
+	do {
+		events = readl(fep->hwp + FEC_IEVENT);
+		if (fep->events) {
+			events |= fep->events;
+			fep->events = 0;
+		}
+		events &= FEC_ENET_RXF_0 | FEC_ENET_TXF_0;
+		if (!events) {
+			if (budget) {
+				napi_complete(napi);
+				writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+			}
+			return pkts;
+		}
+
+		writel(events, fep->hwp + FEC_IEVENT);
+		if (events & FEC_ENET_RXF_0)
+			pkts += fec_rxq(ndev, fep, fep->rx_queue[0],
+					budget - pkts);
+		if (events & FEC_ENET_TXF_0)
+			fec_txq(ndev, fep, fep->tx_queue[0]);
+	} while (pkts < budget);
+	fep->events |= FEC_ENET_RXF_0;	/* save for next callback */
+	return pkts;
+}
+
 /* ------------------------------------------------------------------------- */
 static void fec_get_mac(struct net_device *ndev)
 {
@@ -3113,7 +3146,9 @@ static int fec_enet_init(struct net_device *ndev)
 	ndev->ethtool_ops = &fec_enet_ethtool_ops;
 
 	writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
-	netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, NAPI_POLL_WEIGHT);
+	netif_napi_add(ndev, &fep->napi, (fep->num_rx_queues |
+		       fep->num_tx_queues) == 1 ? fec_enet_napi_q1 :
+		       fec_enet_napi_q3, NAPI_POLL_WEIGHT);
 
 	if (fep->quirks & FEC_QUIRK_HAS_VLAN)
 		/* enable hw VLAN support */
-- 
2.5.0

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

* [PATCH net-next 14/40] net: fec: don't clear all rx queue bits when just one is being checked
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

FEC_ENET_RXF is 3 separate bits, we only check one queue
at a time. So, when the last queue is being checked, it is
bad to remove the interrupt on the 1st queue.

Also, since this is now done in the napi
routine and not the interrupt, it is not needed.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 04b1fb7..a7af1ac 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1330,8 +1330,6 @@ static int fec_rxq(struct net_device *ndev, struct fec_enet_private *fep,
 			break;
 		pkt_received++;
 
-		writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT);
-
 		/* Check for errors. */
 		status ^= BD_ENET_RX_LAST;
 		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
-- 
2.5.0

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

* [PATCH net-next 14/40] net: fec: don't clear all rx queue bits when just one is being checked
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

FEC_ENET_RXF is 3 separate bits, we only check one queue
at a time. So, when the last queue is being checked, it is
bad to remove the interrupt on the 1st queue.

Also, since this is now done in the napi
routine and not the interrupt, it is not needed.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 04b1fb7..a7af1ac 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1330,8 +1330,6 @@ static int fec_rxq(struct net_device *ndev, struct fec_enet_private *fep,
 			break;
 		pkt_received++;
 
-		writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT);
-
 		/* Check for errors. */
 		status ^= BD_ENET_RX_LAST;
 		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
-- 
2.5.0

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

* [PATCH net-next 15/40] net: fec: set cbd_sc without relying on previous value
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Relying on the wrap bit to stay valid once initialized
when the controller also writes to this byte seems
undesirable since we can easily know what the value
should be.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index a7af1ac..9285425 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -338,9 +338,8 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		ebdp = (struct bufdesc_ex *)bdp;
 
-		status = bdp->cbd_sc;
-		status &= ~BD_ENET_TX_STATS;
-		status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
+		status = (BD_ENET_TX_TC | BD_ENET_TX_READY) |
+				((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 		frag_len = skb_shinfo(skb)->frags[frag].size;
 
 		/* Handle the last BD specially */
@@ -435,8 +434,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	/* Fill in a Tx ring entry */
 	bdp = txq->bd.cur;
 	last_bdp = bdp;
-	status = bdp->cbd_sc;
-	status &= ~BD_ENET_TX_STATS;
 
 	/* Set buffer length and buffer pointer */
 	bufaddr = skb->data;
@@ -461,6 +458,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 		return NETDEV_TX_OK;
 	}
 
+	status = (BD_ENET_TX_TC | BD_ENET_TX_READY) |
+			((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 	if (nr_frags) {
 		last_bdp = fec_enet_txq_submit_frag_skb(txq, skb, ndev);
 		if (IS_ERR(last_bdp))
@@ -507,7 +506,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
 	 * it's the last BD of the frame, and to put the CRC on the end.
 	 */
-	status |= (BD_ENET_TX_READY | BD_ENET_TX_TC);
 	bdp->cbd_sc = status;
 
 	/* If this was the last BD in the ring, start at the beginning again. */
@@ -539,10 +537,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 	unsigned int estatus = 0;
 	dma_addr_t addr;
 
-	status = bdp->cbd_sc;
-	status &= ~BD_ENET_TX_STATS;
-
-	status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
+	status = (BD_ENET_TX_TC | BD_ENET_TX_READY) |
+			((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 
 	if (((unsigned long) data) & fep->tx_align ||
 		fep->quirks & FEC_QUIRK_SWAP_FRAME) {
@@ -600,10 +596,8 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 	unsigned short status;
 	unsigned int estatus = 0;
 
-	status = bdp->cbd_sc;
-	status &= ~BD_ENET_TX_STATS;
-	status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
-
+	status = (BD_ENET_TX_TC | BD_ENET_TX_READY) |
+			((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 	bufaddr = txq->tso_hdrs + index * TSO_HEADER_SIZE;
 	dmabuf = txq->tso_hdrs_dma + index * TSO_HEADER_SIZE;
 	if (((unsigned long)bufaddr) & fep->tx_align ||
@@ -1442,12 +1436,6 @@ static int fec_rxq(struct net_device *ndev, struct fec_enet_private *fep,
 		}
 
 rx_processing_done:
-		/* Clear the status flags for this buffer */
-		status &= ~BD_ENET_RX_STATS;
-
-		/* Mark the buffer empty */
-		status |= BD_ENET_RX_EMPTY;
-
 		if (fep->bufdesc_ex) {
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 
@@ -1459,7 +1447,8 @@ rx_processing_done:
 		 * performed before transferring ownership.
 		 */
 		wmb();
-		bdp->cbd_sc = status;
+		bdp->cbd_sc = BD_ENET_RX_EMPTY |
+				((bdp == rxq->bd.last) ? BD_SC_WRAP : 0);
 
 		/* Update BD pointer to next entry */
 		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
-- 
2.5.0

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

* [PATCH net-next 15/40] net: fec: set cbd_sc without relying on previous value
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Relying on the wrap bit to stay valid once initialized
when the controller also writes to this byte seems
undesirable since we can easily know what the value
should be.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index a7af1ac..9285425 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -338,9 +338,8 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		ebdp = (struct bufdesc_ex *)bdp;
 
-		status = bdp->cbd_sc;
-		status &= ~BD_ENET_TX_STATS;
-		status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
+		status = (BD_ENET_TX_TC | BD_ENET_TX_READY) |
+				((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 		frag_len = skb_shinfo(skb)->frags[frag].size;
 
 		/* Handle the last BD specially */
@@ -435,8 +434,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	/* Fill in a Tx ring entry */
 	bdp = txq->bd.cur;
 	last_bdp = bdp;
-	status = bdp->cbd_sc;
-	status &= ~BD_ENET_TX_STATS;
 
 	/* Set buffer length and buffer pointer */
 	bufaddr = skb->data;
@@ -461,6 +458,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 		return NETDEV_TX_OK;
 	}
 
+	status = (BD_ENET_TX_TC | BD_ENET_TX_READY) |
+			((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 	if (nr_frags) {
 		last_bdp = fec_enet_txq_submit_frag_skb(txq, skb, ndev);
 		if (IS_ERR(last_bdp))
@@ -507,7 +506,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
 	 * it's the last BD of the frame, and to put the CRC on the end.
 	 */
-	status |= (BD_ENET_TX_READY | BD_ENET_TX_TC);
 	bdp->cbd_sc = status;
 
 	/* If this was the last BD in the ring, start at the beginning again. */
@@ -539,10 +537,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 	unsigned int estatus = 0;
 	dma_addr_t addr;
 
-	status = bdp->cbd_sc;
-	status &= ~BD_ENET_TX_STATS;
-
-	status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
+	status = (BD_ENET_TX_TC | BD_ENET_TX_READY) |
+			((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 
 	if (((unsigned long) data) & fep->tx_align ||
 		fep->quirks & FEC_QUIRK_SWAP_FRAME) {
@@ -600,10 +596,8 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 	unsigned short status;
 	unsigned int estatus = 0;
 
-	status = bdp->cbd_sc;
-	status &= ~BD_ENET_TX_STATS;
-	status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
-
+	status = (BD_ENET_TX_TC | BD_ENET_TX_READY) |
+			((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 	bufaddr = txq->tso_hdrs + index * TSO_HEADER_SIZE;
 	dmabuf = txq->tso_hdrs_dma + index * TSO_HEADER_SIZE;
 	if (((unsigned long)bufaddr) & fep->tx_align ||
@@ -1442,12 +1436,6 @@ static int fec_rxq(struct net_device *ndev, struct fec_enet_private *fep,
 		}
 
 rx_processing_done:
-		/* Clear the status flags for this buffer */
-		status &= ~BD_ENET_RX_STATS;
-
-		/* Mark the buffer empty */
-		status |= BD_ENET_RX_EMPTY;
-
 		if (fep->bufdesc_ex) {
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 
@@ -1459,7 +1447,8 @@ rx_processing_done:
 		 * performed before transferring ownership.
 		 */
 		wmb();
-		bdp->cbd_sc = status;
+		bdp->cbd_sc = BD_ENET_RX_EMPTY |
+				((bdp == rxq->bd.last) ? BD_SC_WRAP : 0);
 
 		/* Update BD pointer to next entry */
 		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
-- 
2.5.0

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

* [PATCH net-next 16/40] net: fec: eliminate calls to fec_enet_get_prevdesc
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

This shrinks the code a little.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 34 ++++++++-----------------------
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 9285425..1a838cc 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -758,6 +758,7 @@ static void fec_enet_bd_init(struct net_device *dev)
 	struct bufdesc *bdp;
 	unsigned int i;
 	unsigned int q;
+	unsigned status;
 
 	for (q = 0; q < fep->num_rx_queues; q++) {
 		/* Initialize the receive buffer descriptors. */
@@ -765,19 +766,13 @@ static void fec_enet_bd_init(struct net_device *dev)
 		bdp = rxq->bd.base;
 
 		for (i = 0; i < rxq->bd.ring_size; i++) {
-
 			/* Initialize the BD for every fragment in the page. */
-			if (bdp->cbd_bufaddr)
-				bdp->cbd_sc = BD_ENET_RX_EMPTY;
-			else
-				bdp->cbd_sc = 0;
+			status = bdp->cbd_bufaddr ? BD_ENET_RX_EMPTY : 0;
+			if (bdp == rxq->bd.last)
+				status |= BD_SC_WRAP;
+			bdp->cbd_sc = status;
 			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 		}
-
-		/* Set the last buffer to wrap */
-		bdp = fec_enet_get_prevdesc(bdp, &rxq->bd);
-		bdp->cbd_sc |= BD_SC_WRAP;
-
 		rxq->bd.cur = rxq->bd.base;
 	}
 
@@ -789,18 +784,15 @@ static void fec_enet_bd_init(struct net_device *dev)
 
 		for (i = 0; i < txq->bd.ring_size; i++) {
 			/* Initialize the BD for every fragment in the page. */
-			bdp->cbd_sc = 0;
 			if (txq->tx_skbuff[i]) {
 				dev_kfree_skb_any(txq->tx_skbuff[i]);
 				txq->tx_skbuff[i] = NULL;
 			}
 			bdp->cbd_bufaddr = 0;
+			bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
-
-		/* Set the last buffer to wrap */
 		bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
-		bdp->cbd_sc |= BD_SC_WRAP;
 		txq->dirty_tx = bdp;
 	}
 }
@@ -2712,19 +2704,16 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
 		}
 
 		rxq->rx_skbuff[i] = skb;
-		bdp->cbd_sc = BD_ENET_RX_EMPTY;
 
 		if (fep->bufdesc_ex) {
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 			ebdp->cbd_esc = BD_ENET_RX_INT;
 		}
+		bdp->cbd_sc = BD_ENET_RX_EMPTY |
+				((bdp == rxq->bd.last) ? BD_SC_WRAP : 0);
 
 		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 	}
-
-	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, &rxq->bd);
-	bdp->cbd_sc |= BD_SC_WRAP;
 	return 0;
 
  err_alloc:
@@ -2747,21 +2736,16 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
 		if (!txq->tx_bounce[i])
 			goto err_alloc;
 
-		bdp->cbd_sc = 0;
 		bdp->cbd_bufaddr = 0;
 
 		if (fep->bufdesc_ex) {
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 			ebdp->cbd_esc = BD_ENET_TX_INT;
 		}
+		bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 
 		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 	}
-
-	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
-	bdp->cbd_sc |= BD_SC_WRAP;
-
 	return 0;
 
  err_alloc:
-- 
2.5.0

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

* [PATCH net-next 16/40] net: fec: eliminate calls to fec_enet_get_prevdesc
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

This shrinks the code a little.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 34 ++++++++-----------------------
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 9285425..1a838cc 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -758,6 +758,7 @@ static void fec_enet_bd_init(struct net_device *dev)
 	struct bufdesc *bdp;
 	unsigned int i;
 	unsigned int q;
+	unsigned status;
 
 	for (q = 0; q < fep->num_rx_queues; q++) {
 		/* Initialize the receive buffer descriptors. */
@@ -765,19 +766,13 @@ static void fec_enet_bd_init(struct net_device *dev)
 		bdp = rxq->bd.base;
 
 		for (i = 0; i < rxq->bd.ring_size; i++) {
-
 			/* Initialize the BD for every fragment in the page. */
-			if (bdp->cbd_bufaddr)
-				bdp->cbd_sc = BD_ENET_RX_EMPTY;
-			else
-				bdp->cbd_sc = 0;
+			status = bdp->cbd_bufaddr ? BD_ENET_RX_EMPTY : 0;
+			if (bdp == rxq->bd.last)
+				status |= BD_SC_WRAP;
+			bdp->cbd_sc = status;
 			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 		}
-
-		/* Set the last buffer to wrap */
-		bdp = fec_enet_get_prevdesc(bdp, &rxq->bd);
-		bdp->cbd_sc |= BD_SC_WRAP;
-
 		rxq->bd.cur = rxq->bd.base;
 	}
 
@@ -789,18 +784,15 @@ static void fec_enet_bd_init(struct net_device *dev)
 
 		for (i = 0; i < txq->bd.ring_size; i++) {
 			/* Initialize the BD for every fragment in the page. */
-			bdp->cbd_sc = 0;
 			if (txq->tx_skbuff[i]) {
 				dev_kfree_skb_any(txq->tx_skbuff[i]);
 				txq->tx_skbuff[i] = NULL;
 			}
 			bdp->cbd_bufaddr = 0;
+			bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
-
-		/* Set the last buffer to wrap */
 		bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
-		bdp->cbd_sc |= BD_SC_WRAP;
 		txq->dirty_tx = bdp;
 	}
 }
@@ -2712,19 +2704,16 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
 		}
 
 		rxq->rx_skbuff[i] = skb;
-		bdp->cbd_sc = BD_ENET_RX_EMPTY;
 
 		if (fep->bufdesc_ex) {
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 			ebdp->cbd_esc = BD_ENET_RX_INT;
 		}
+		bdp->cbd_sc = BD_ENET_RX_EMPTY |
+				((bdp == rxq->bd.last) ? BD_SC_WRAP : 0);
 
 		bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
 	}
-
-	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, &rxq->bd);
-	bdp->cbd_sc |= BD_SC_WRAP;
 	return 0;
 
  err_alloc:
@@ -2747,21 +2736,16 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
 		if (!txq->tx_bounce[i])
 			goto err_alloc;
 
-		bdp->cbd_sc = 0;
 		bdp->cbd_bufaddr = 0;
 
 		if (fep->bufdesc_ex) {
 			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 			ebdp->cbd_esc = BD_ENET_TX_INT;
 		}
+		bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 
 		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 	}
-
-	/* Set the last buffer to wrap. */
-	bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
-	bdp->cbd_sc |= BD_SC_WRAP;
-
 	return 0;
 
  err_alloc:
-- 
2.5.0

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

* [PATCH net-next 17/40] net: fec: move restart test for efficiency
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

This saves 1 comparison.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1a838cc..fcbbf0d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1154,8 +1154,13 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 		/* Order the load of bd.cur and cbd_sc */
 		rmb();
 		status = READ_ONCE(bdp->cbd_sc);
-		if (status & BD_ENET_TX_READY)
+		if (status & BD_ENET_TX_READY) {
+			if (!readl(txq->bd.reg_desc_active)) {
+				/* ERR006358 has hit, restart tx */
+				writel(0, txq->bd.reg_desc_active);
+			}
 			break;
+		}
 
 		index = fec_enet_get_bd_index(bdp, &txq->bd);
 
@@ -1225,11 +1230,6 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 				netif_tx_wake_queue(nq);
 		}
 	}
-
-	/* ERR006538: Keep the transmitter going */
-	if (bdp != txq->bd.cur &&
-	    readl(txq->bd.reg_desc_active) == 0)
-		writel(0, txq->bd.reg_desc_active);
 }
 
 static int
-- 
2.5.0

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

* [PATCH net-next 17/40] net: fec: move restart test for efficiency
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

This saves 1 comparison.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1a838cc..fcbbf0d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1154,8 +1154,13 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 		/* Order the load of bd.cur and cbd_sc */
 		rmb();
 		status = READ_ONCE(bdp->cbd_sc);
-		if (status & BD_ENET_TX_READY)
+		if (status & BD_ENET_TX_READY) {
+			if (!readl(txq->bd.reg_desc_active)) {
+				/* ERR006358 has hit, restart tx */
+				writel(0, txq->bd.reg_desc_active);
+			}
 			break;
+		}
 
 		index = fec_enet_get_bd_index(bdp, &txq->bd);
 
@@ -1225,11 +1230,6 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 				netif_tx_wake_queue(nq);
 		}
 	}
-
-	/* ERR006538: Keep the transmitter going */
-	if (bdp != txq->bd.cur &&
-	    readl(txq->bd.reg_desc_active) == 0)
-		writel(0, txq->bd.reg_desc_active);
 }
 
 static int
-- 
2.5.0

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

* [PATCH net-next 18/40] net: fec: clear cbd_sc after transmission to help with debugging
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

When the tx queue is dumped, it is easier to see that this
entry is idle.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index fcbbf0d..1759705 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1161,6 +1161,7 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 			}
 			break;
 		}
+		bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 
 		index = fec_enet_get_bd_index(bdp, &txq->bd);
 
-- 
2.5.0

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

* [PATCH net-next 18/40] net: fec: clear cbd_sc after transmission to help with debugging
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

When the tx queue is dumped, it is easier to see that this
entry is idle.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index fcbbf0d..1759705 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1161,6 +1161,7 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 			}
 			break;
 		}
+		bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 
 		index = fec_enet_get_bd_index(bdp, &txq->bd);
 
-- 
2.5.0

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

* [PATCH net-next 19/40] net: fec: dump all tx queues in fec_dump
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Dump all tx queues, not just queue 0.
Also, disable fec interrupts first.
The interrupts will be reenabled in fec_restart.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 36 +++++++++++++++++--------------
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1759705..1225282 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -271,26 +271,30 @@ static void swap_buffer2(void *dst_buf, void *src_buf, int len)
 static void fec_dump(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct bufdesc *bdp;
-	struct fec_enet_priv_tx_q *txq;
-	int index = 0;
+	int i;
 
+	/* Disable all FEC interrupts */
+	writel(0, fep->hwp + FEC_IMASK);
 	netdev_info(ndev, "TX ring dump\n");
 	pr_info("Nr     SC     addr       len  SKB\n");
 
-	txq = fep->tx_queue[0];
-	bdp = txq->bd.base;
-
-	do {
-		pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
-			index,
-			bdp == txq->bd.cur ? 'S' : ' ',
-			bdp == txq->dirty_tx ? 'H' : ' ',
-			bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
-			txq->tx_skbuff[index]);
-		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
-		index++;
-	} while (bdp != txq->bd.base);
+	for (i = 0; i < fep->num_tx_queues; i++) {
+		struct fec_enet_priv_tx_q *txq = fep->tx_queue[i];
+		struct bufdesc *bdp = txq->bd.base;
+		int index = 0;
+
+		pr_info("tx queue %d\n", i);
+		do {
+			pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
+				index,
+				bdp == txq->bd.cur ? 'S' : ' ',
+				bdp == txq->dirty_tx ? 'H' : ' ',
+				bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
+				txq->tx_skbuff[index]);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+			index++;
+		} while (bdp != txq->bd.base);
+	}
 }
 
 static inline bool is_ipv4_pkt(struct sk_buff *skb)
-- 
2.5.0

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

* [PATCH net-next 19/40] net: fec: dump all tx queues in fec_dump
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Dump all tx queues, not just queue 0.
Also, disable fec interrupts first.
The interrupts will be reenabled in fec_restart.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 36 +++++++++++++++++--------------
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1759705..1225282 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -271,26 +271,30 @@ static void swap_buffer2(void *dst_buf, void *src_buf, int len)
 static void fec_dump(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct bufdesc *bdp;
-	struct fec_enet_priv_tx_q *txq;
-	int index = 0;
+	int i;
 
+	/* Disable all FEC interrupts */
+	writel(0, fep->hwp + FEC_IMASK);
 	netdev_info(ndev, "TX ring dump\n");
 	pr_info("Nr     SC     addr       len  SKB\n");
 
-	txq = fep->tx_queue[0];
-	bdp = txq->bd.base;
-
-	do {
-		pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
-			index,
-			bdp == txq->bd.cur ? 'S' : ' ',
-			bdp == txq->dirty_tx ? 'H' : ' ',
-			bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
-			txq->tx_skbuff[index]);
-		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
-		index++;
-	} while (bdp != txq->bd.base);
+	for (i = 0; i < fep->num_tx_queues; i++) {
+		struct fec_enet_priv_tx_q *txq = fep->tx_queue[i];
+		struct bufdesc *bdp = txq->bd.base;
+		int index = 0;
+
+		pr_info("tx queue %d\n", i);
+		do {
+			pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
+				index,
+				bdp == txq->bd.cur ? 'S' : ' ',
+				bdp == txq->dirty_tx ? 'H' : ' ',
+				bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
+				txq->tx_skbuff[index]);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+			index++;
+		} while (bdp != txq->bd.base);
+	}
 }
 
 static inline bool is_ipv4_pkt(struct sk_buff *skb)
-- 
2.5.0

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

* [PATCH net-next 20/40] net: fec: detect tx int lost
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

If a tx int is lost, no need to reset
the fec. Just mark the event and call napi_schedule.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 36 ++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1225282..47df66e 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1091,14 +1091,48 @@ fec_stop(struct net_device *ndev)
 	}
 }
 
+uint txint_flags[] = {FEC_ENET_TXF_0, FEC_ENET_TXF_1, FEC_ENET_TXF_2};
 
 static void
 fec_timeout(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct bufdesc *bdp;
+	unsigned short status;
+	int i;
+	uint events = 0;
 
-	fec_dump(ndev);
+	for (i = 0; i < fep->num_tx_queues; i++) {
+		struct fec_enet_priv_tx_q *txq = fep->tx_queue[i];
+		int index;
+		struct sk_buff *skb = NULL;
+
+		bdp = txq->dirty_tx;
+		while (1) {
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+			if (bdp == txq->bd.cur)
+				break;
+			index = fec_enet_get_bd_index(bdp, &txq->bd);
+			skb = txq->tx_skbuff[index];
+			if (skb) {
+				status = bdp->cbd_sc;
+				if ((status & BD_ENET_TX_READY) == 0)
+					events |= txint_flags[i];
+				break;
+			}
+		}
+	}
+	if (events) {
+		fep->events |= events;
+		/* Disable the RX/TX interrupt */
+		writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK);
+		napi_schedule(&fep->napi);
+		netif_wake_queue(fep->netdev);
+		pr_err("%s: tx int lost\n", __func__);
+		return;
+	}
 
+	fec_dump(ndev);
 	ndev->stats.tx_errors++;
 
 	schedule_work(&fep->tx_timeout_work);
-- 
2.5.0

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

* [PATCH net-next 20/40] net: fec: detect tx int lost
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

If a tx int is lost, no need to reset
the fec. Just mark the event and call napi_schedule.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 36 ++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1225282..47df66e 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1091,14 +1091,48 @@ fec_stop(struct net_device *ndev)
 	}
 }
 
+uint txint_flags[] = {FEC_ENET_TXF_0, FEC_ENET_TXF_1, FEC_ENET_TXF_2};
 
 static void
 fec_timeout(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct bufdesc *bdp;
+	unsigned short status;
+	int i;
+	uint events = 0;
 
-	fec_dump(ndev);
+	for (i = 0; i < fep->num_tx_queues; i++) {
+		struct fec_enet_priv_tx_q *txq = fep->tx_queue[i];
+		int index;
+		struct sk_buff *skb = NULL;
+
+		bdp = txq->dirty_tx;
+		while (1) {
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+			if (bdp == txq->bd.cur)
+				break;
+			index = fec_enet_get_bd_index(bdp, &txq->bd);
+			skb = txq->tx_skbuff[index];
+			if (skb) {
+				status = bdp->cbd_sc;
+				if ((status & BD_ENET_TX_READY) == 0)
+					events |= txint_flags[i];
+				break;
+			}
+		}
+	}
+	if (events) {
+		fep->events |= events;
+		/* Disable the RX/TX interrupt */
+		writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK);
+		napi_schedule(&fep->napi);
+		netif_wake_queue(fep->netdev);
+		pr_err("%s: tx int lost\n", __func__);
+		return;
+	}
 
+	fec_dump(ndev);
 	ndev->stats.tx_errors++;
 
 	schedule_work(&fep->tx_timeout_work);
-- 
2.5.0

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

* [PATCH net-next 21/40] net: fec: print more debug info in fec_timeout
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Print the current interrupt flags and mask and
the interrupt state during the last interrupt in
fec_timeout.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      | 1 +
 drivers/net/ethernet/freescale/fec_main.c | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index be0e3d9..d2ca2e2 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -490,6 +490,7 @@ struct fec_enet_private {
 	unsigned int total_tx_ring_size;
 	unsigned int total_rx_ring_size;
 	uint	events;
+	uint	last_ievents;
 
 	struct	platform_device *pdev;
 
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 47df66e..bc084ad9 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1102,6 +1102,9 @@ fec_timeout(struct net_device *ndev)
 	int i;
 	uint events = 0;
 
+	pr_err("%s: last=%x %x, mask %x\n", __func__, fep->last_ievents,
+	       readl(fep->hwp + FEC_IEVENT), readl(fep->hwp + FEC_IMASK));
+
 	for (i = 0; i < fep->num_tx_queues; i++) {
 		struct fec_enet_priv_tx_q *txq = fep->tx_queue[i];
 		int index;
@@ -1504,6 +1507,7 @@ fec_enet_interrupt(int irq, void *dev_id)
 
 	if (!int_events)
 		return IRQ_NONE;
+	fep->last_ievents = int_events;
 
 	if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
 		if (napi_schedule_prep(&fep->napi)) {
-- 
2.5.0

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

* [PATCH net-next 21/40] net: fec: print more debug info in fec_timeout
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Print the current interrupt flags and mask and
the interrupt state during the last interrupt in
fec_timeout.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      | 1 +
 drivers/net/ethernet/freescale/fec_main.c | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index be0e3d9..d2ca2e2 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -490,6 +490,7 @@ struct fec_enet_private {
 	unsigned int total_tx_ring_size;
 	unsigned int total_rx_ring_size;
 	uint	events;
+	uint	last_ievents;
 
 	struct	platform_device *pdev;
 
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 47df66e..bc084ad9 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1102,6 +1102,9 @@ fec_timeout(struct net_device *ndev)
 	int i;
 	uint events = 0;
 
+	pr_err("%s: last=%x %x, mask %x\n", __func__, fep->last_ievents,
+	       readl(fep->hwp + FEC_IEVENT), readl(fep->hwp + FEC_IMASK));
+
 	for (i = 0; i < fep->num_tx_queues; i++) {
 		struct fec_enet_priv_tx_q *txq = fep->tx_queue[i];
 		int index;
@@ -1504,6 +1507,7 @@ fec_enet_interrupt(int irq, void *dev_id)
 
 	if (!int_events)
 		return IRQ_NONE;
+	fep->last_ievents = int_events;
 
 	if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
 		if (napi_schedule_prep(&fep->napi)) {
-- 
2.5.0

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

* [PATCH net-next 22/40] net: fec: call dma_unmap_single on mapped tx buffers at restart
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index bc084ad9..da2e3c530 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -403,6 +403,7 @@ dma_mapping_error:
 		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
 				bdp->cbd_datlen, DMA_TO_DEVICE);
+		bdp->cbd_bufaddr = 0;
 	}
 	return ERR_PTR(-ENOMEM);
 }
@@ -788,11 +789,18 @@ static void fec_enet_bd_init(struct net_device *dev)
 
 		for (i = 0; i < txq->bd.ring_size; i++) {
 			/* Initialize the BD for every fragment in the page. */
+			if (bdp->cbd_bufaddr) {
+				if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr))
+					dma_unmap_single(&fep->pdev->dev,
+							 bdp->cbd_bufaddr,
+							 bdp->cbd_datlen,
+							 DMA_TO_DEVICE);
+				bdp->cbd_bufaddr = 0;
+			}
 			if (txq->tx_skbuff[i]) {
 				dev_kfree_skb_any(txq->tx_skbuff[i]);
 				txq->tx_skbuff[i] = NULL;
 			}
-			bdp->cbd_bufaddr = 0;
 			bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
@@ -2635,6 +2643,7 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 						 bdp->cbd_bufaddr,
 						 FEC_ENET_RX_FRSIZE - fep->rx_align,
 						 DMA_FROM_DEVICE);
+				bdp->cbd_bufaddr = 0;
 				dev_kfree_skb(skb);
 			}
 			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
@@ -2645,11 +2654,20 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 		txq = fep->tx_queue[q];
 		bdp = txq->bd.base;
 		for (i = 0; i < txq->bd.ring_size; i++) {
+			if (bdp->cbd_bufaddr) {
+				if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr))
+					dma_unmap_single(&fep->pdev->dev,
+							 bdp->cbd_bufaddr,
+							 bdp->cbd_datlen,
+							 DMA_TO_DEVICE);
+				bdp->cbd_bufaddr = 0;
+			}
 			kfree(txq->tx_bounce[i]);
 			txq->tx_bounce[i] = NULL;
 			skb = txq->tx_skbuff[i];
 			txq->tx_skbuff[i] = NULL;
 			dev_kfree_skb(skb);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
 	}
 }
-- 
2.5.0

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

* [PATCH net-next 22/40] net: fec: call dma_unmap_single on mapped tx buffers at restart
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index bc084ad9..da2e3c530 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -403,6 +403,7 @@ dma_mapping_error:
 		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
 				bdp->cbd_datlen, DMA_TO_DEVICE);
+		bdp->cbd_bufaddr = 0;
 	}
 	return ERR_PTR(-ENOMEM);
 }
@@ -788,11 +789,18 @@ static void fec_enet_bd_init(struct net_device *dev)
 
 		for (i = 0; i < txq->bd.ring_size; i++) {
 			/* Initialize the BD for every fragment in the page. */
+			if (bdp->cbd_bufaddr) {
+				if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr))
+					dma_unmap_single(&fep->pdev->dev,
+							 bdp->cbd_bufaddr,
+							 bdp->cbd_datlen,
+							 DMA_TO_DEVICE);
+				bdp->cbd_bufaddr = 0;
+			}
 			if (txq->tx_skbuff[i]) {
 				dev_kfree_skb_any(txq->tx_skbuff[i]);
 				txq->tx_skbuff[i] = NULL;
 			}
-			bdp->cbd_bufaddr = 0;
 			bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
@@ -2635,6 +2643,7 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 						 bdp->cbd_bufaddr,
 						 FEC_ENET_RX_FRSIZE - fep->rx_align,
 						 DMA_FROM_DEVICE);
+				bdp->cbd_bufaddr = 0;
 				dev_kfree_skb(skb);
 			}
 			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
@@ -2645,11 +2654,20 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 		txq = fep->tx_queue[q];
 		bdp = txq->bd.base;
 		for (i = 0; i < txq->bd.ring_size; i++) {
+			if (bdp->cbd_bufaddr) {
+				if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr))
+					dma_unmap_single(&fep->pdev->dev,
+							 bdp->cbd_bufaddr,
+							 bdp->cbd_datlen,
+							 DMA_TO_DEVICE);
+				bdp->cbd_bufaddr = 0;
+			}
 			kfree(txq->tx_bounce[i]);
 			txq->tx_bounce[i] = NULL;
 			skb = txq->tx_skbuff[i];
 			txq->tx_skbuff[i] = NULL;
 			dev_kfree_skb(skb);
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
 	}
 }
-- 
2.5.0

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

* [PATCH net-next 23/40] net: fec: don't set cbd_bufaddr unless no mapping error
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index da2e3c530..29c5781 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -597,7 +597,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc);
 	void *bufaddr;
-	unsigned long dmabuf;
+	dma_addr_t dmabuf;
 	unsigned short status;
 	unsigned int estatus = 0;
 
@@ -1287,19 +1287,21 @@ fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff
 {
 	struct  fec_enet_private *fep = netdev_priv(ndev);
 	int off;
+	dma_addr_t dmabuf;
 
 	off = ((unsigned long)skb->data) & fep->rx_align;
 	if (off)
 		skb_reserve(skb, fep->rx_align + 1 - off);
 
-	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
-					  FEC_ENET_RX_FRSIZE - fep->rx_align,
-					  DMA_FROM_DEVICE);
-	if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+	dmabuf = dma_map_single(&fep->pdev->dev, skb->data,
+				FEC_ENET_RX_FRSIZE - fep->rx_align,
+				DMA_FROM_DEVICE);
+	if (dma_mapping_error(&fep->pdev->dev, dmabuf)) {
 		if (net_ratelimit())
 			netdev_err(ndev, "Rx DMA memory map failed\n");
 		return -ENOMEM;
 	}
+	bdp->cbd_bufaddr = dmabuf;
 
 	return 0;
 }
-- 
2.5.0

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

* [PATCH net-next 23/40] net: fec: don't set cbd_bufaddr unless no mapping error
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index da2e3c530..29c5781 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -597,7 +597,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc);
 	void *bufaddr;
-	unsigned long dmabuf;
+	dma_addr_t dmabuf;
 	unsigned short status;
 	unsigned int estatus = 0;
 
@@ -1287,19 +1287,21 @@ fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff
 {
 	struct  fec_enet_private *fep = netdev_priv(ndev);
 	int off;
+	dma_addr_t dmabuf;
 
 	off = ((unsigned long)skb->data) & fep->rx_align;
 	if (off)
 		skb_reserve(skb, fep->rx_align + 1 - off);
 
-	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
-					  FEC_ENET_RX_FRSIZE - fep->rx_align,
-					  DMA_FROM_DEVICE);
-	if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+	dmabuf = dma_map_single(&fep->pdev->dev, skb->data,
+				FEC_ENET_RX_FRSIZE - fep->rx_align,
+				DMA_FROM_DEVICE);
+	if (dma_mapping_error(&fep->pdev->dev, dmabuf)) {
 		if (net_ratelimit())
 			netdev_err(ndev, "Rx DMA memory map failed\n");
 		return -ENOMEM;
 	}
+	bdp->cbd_bufaddr = dmabuf;
 
 	return 0;
 }
-- 
2.5.0

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

* [PATCH net-next 24/40] net: fec: return NETDEV_TX_BUSY, when not enough space in ring
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 29c5781..98b9be2 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -424,10 +424,9 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 
 	entries_free = fec_enet_get_free_txdesc_num(txq);
 	if (entries_free < MAX_SKB_FRAGS + 1) {
-		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "NOT enough BD for SG!\n");
-		return NETDEV_TX_OK;
+		return NETDEV_TX_BUSY;
 	}
 
 	/* Protocol checksum off-load for TCP and UDP. */
@@ -653,10 +652,9 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	int ret;
 
 	if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(txq)) {
-		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "NOT enough BD for TSO!\n");
-		return NETDEV_TX_OK;
+		return NETDEV_TX_BUSY;
 	}
 
 	/* Protocol checksum off-load for TCP and UDP. */
-- 
2.5.0

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

* [PATCH net-next 24/40] net: fec: return NETDEV_TX_BUSY, when not enough space in ring
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 29c5781..98b9be2 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -424,10 +424,9 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 
 	entries_free = fec_enet_get_free_txdesc_num(txq);
 	if (entries_free < MAX_SKB_FRAGS + 1) {
-		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "NOT enough BD for SG!\n");
-		return NETDEV_TX_OK;
+		return NETDEV_TX_BUSY;
 	}
 
 	/* Protocol checksum off-load for TCP and UDP. */
@@ -653,10 +652,9 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	int ret;
 
 	if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(txq)) {
-		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "NOT enough BD for TSO!\n");
-		return NETDEV_TX_OK;
+		return NETDEV_TX_BUSY;
 	}
 
 	/* Protocol checksum off-load for TCP and UDP. */
-- 
2.5.0

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

* [PATCH net-next 25/40] net: fec: don't free skb until it has been unmapped
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 98b9be2..380c8e2 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -381,7 +381,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 		addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len,
 				      DMA_TO_DEVICE);
 		if (dma_mapping_error(&fep->pdev->dev, addr)) {
-			dev_kfree_skb_any(skb);
 			if (net_ratelimit())
 				netdev_err(ndev, "Tx DMA memory map failed\n");
 			goto dma_mapping_error;
@@ -405,6 +404,7 @@ dma_mapping_error:
 				bdp->cbd_datlen, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
 	}
+	dev_kfree_skb_any(skb);
 	return ERR_PTR(-ENOMEM);
 }
 
-- 
2.5.0

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

* [PATCH net-next 25/40] net: fec: don't free skb until it has been unmapped
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 98b9be2..380c8e2 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -381,7 +381,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 		addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len,
 				      DMA_TO_DEVICE);
 		if (dma_mapping_error(&fep->pdev->dev, addr)) {
-			dev_kfree_skb_any(skb);
 			if (net_ratelimit())
 				netdev_err(ndev, "Tx DMA memory map failed\n");
 			goto dma_mapping_error;
@@ -405,6 +404,7 @@ dma_mapping_error:
 				bdp->cbd_datlen, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
 	}
+	dev_kfree_skb_any(skb);
 	return ERR_PTR(-ENOMEM);
 }
 
-- 
2.5.0

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

* [PATCH net-next 26/40] net: fec: set cbd_esc only once
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 380c8e2..cf53e21 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -569,6 +569,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
+		if (is_last)
+			estatus |= BD_ENET_TX_INT;
 		ebdp->cbd_bdu = 0;
 		ebdp->cbd_esc = estatus;
 	}
@@ -576,12 +578,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 	/* Handle the last BD specially */
 	if (last_tcp)
 		status |= (BD_ENET_TX_LAST | BD_ENET_TX_TC);
-	if (is_last) {
+	if (is_last)
 		status |= BD_ENET_TX_INTR;
-		if (fep->bufdesc_ex)
-			ebdp->cbd_esc |= BD_ENET_TX_INT;
-	}
-
 	bdp->cbd_sc = status;
 
 	return 0;
-- 
2.5.0

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

* [PATCH net-next 26/40] net: fec: set cbd_esc only once
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 380c8e2..cf53e21 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -569,6 +569,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
+		if (is_last)
+			estatus |= BD_ENET_TX_INT;
 		ebdp->cbd_bdu = 0;
 		ebdp->cbd_esc = estatus;
 	}
@@ -576,12 +578,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 	/* Handle the last BD specially */
 	if (last_tcp)
 		status |= (BD_ENET_TX_LAST | BD_ENET_TX_TC);
-	if (is_last) {
+	if (is_last)
 		status |= BD_ENET_TX_INTR;
-		if (fep->bufdesc_ex)
-			ebdp->cbd_esc |= BD_ENET_TX_INT;
-	}
-
 	bdp->cbd_sc = status;
 
 	return 0;
-- 
2.5.0

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

* [PATCH net-next 27/40] net: fec: enable interrupt on very last descriptor only
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index cf53e21..7258051 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -689,7 +689,8 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 							bdp, index,
 							tso.data, size,
 							size == data_left,
-							total_len == 0);
+							(total_len == 0) &&
+							(size == data_left));
 			if (ret)
 				goto err_release;
 
-- 
2.5.0

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

* [PATCH net-next 27/40] net: fec: enable interrupt on very last descriptor only
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index cf53e21..7258051 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -689,7 +689,8 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 							bdp, index,
 							tso.data, size,
 							size == data_left,
-							total_len == 0);
+							(total_len == 0) &&
+							(size == data_left));
 			if (ret)
 				goto err_release;
 
-- 
2.5.0

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

* [PATCH net-next 28/40] net: fec: unmap initial buffer on error
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 7258051..e141f6f 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -404,7 +404,6 @@ dma_mapping_error:
 				bdp->cbd_datlen, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
 	}
-	dev_kfree_skb_any(skb);
 	return ERR_PTR(-ENOMEM);
 }
 
@@ -466,8 +465,12 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 			((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 	if (nr_frags) {
 		last_bdp = fec_enet_txq_submit_frag_skb(txq, skb, ndev);
-		if (IS_ERR(last_bdp))
+		if (IS_ERR(last_bdp)) {
+			dma_unmap_single(&fep->pdev->dev, addr,
+					 buflen, DMA_TO_DEVICE);
+			dev_kfree_skb_any(skb);
 			return NETDEV_TX_OK;
+		}
 	} else {
 		status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
 		if (fep->bufdesc_ex) {
-- 
2.5.0

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

* [PATCH net-next 28/40] net: fec: unmap initial buffer on error
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 7258051..e141f6f 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -404,7 +404,6 @@ dma_mapping_error:
 				bdp->cbd_datlen, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
 	}
-	dev_kfree_skb_any(skb);
 	return ERR_PTR(-ENOMEM);
 }
 
@@ -466,8 +465,12 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 			((bdp == txq->bd.last) ? BD_SC_WRAP : 0);
 	if (nr_frags) {
 		last_bdp = fec_enet_txq_submit_frag_skb(txq, skb, ndev);
-		if (IS_ERR(last_bdp))
+		if (IS_ERR(last_bdp)) {
+			dma_unmap_single(&fep->pdev->dev, addr,
+					 buflen, DMA_TO_DEVICE);
+			dev_kfree_skb_any(skb);
 			return NETDEV_TX_OK;
+		}
 	} else {
 		status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
 		if (fep->bufdesc_ex) {
-- 
2.5.0

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

* [PATCH net-next 29/40] net: fec: don't free skb when returning busy
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

>From Documentation/networking/driver.txt

If you return NETDEV_TX_BUSY from the ndo_start_xmit method, you
must not keep any reference to that SKB and you must not attempt
to free it up.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index e141f6f..3a82bfe 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -558,7 +558,6 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 
 	addr = dma_map_single(&fep->pdev->dev, data, size, DMA_TO_DEVICE);
 	if (dma_mapping_error(&fep->pdev->dev, addr)) {
-		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "Tx DMA memory map failed\n");
 		return NETDEV_TX_BUSY;
@@ -616,7 +615,6 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 		dmabuf = dma_map_single(&fep->pdev->dev, bufaddr,
 					hdr_len, DMA_TO_DEVICE);
 		if (dma_mapping_error(&fep->pdev->dev, dmabuf)) {
-			dev_kfree_skb_any(skb);
 			if (net_ratelimit())
 				netdev_err(ndev, "Tx DMA memory map failed\n");
 			return NETDEV_TX_BUSY;
-- 
2.5.0

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

* [PATCH net-next 29/40] net: fec: don't free skb when returning busy
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

>From Documentation/networking/driver.txt

If you return NETDEV_TX_BUSY from the ndo_start_xmit method, you
must not keep any reference to that SKB and you must not attempt
to free it up.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index e141f6f..3a82bfe 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -558,7 +558,6 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 
 	addr = dma_map_single(&fep->pdev->dev, data, size, DMA_TO_DEVICE);
 	if (dma_mapping_error(&fep->pdev->dev, addr)) {
-		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "Tx DMA memory map failed\n");
 		return NETDEV_TX_BUSY;
@@ -616,7 +615,6 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 		dmabuf = dma_map_single(&fep->pdev->dev, bufaddr,
 					hdr_len, DMA_TO_DEVICE);
 		if (dma_mapping_error(&fep->pdev->dev, dmabuf)) {
-			dev_kfree_skb_any(skb);
 			if (net_ratelimit())
 				netdev_err(ndev, "Tx DMA memory map failed\n");
 			return NETDEV_TX_BUSY;
-- 
2.5.0

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

* [PATCH net-next 30/40] net: fec: move last_bdp assignment for symmetry
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

This way both if clauses assign last_bdp instead
of only one clause overriding the default.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 3a82bfe..b829c29 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -436,7 +436,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 
 	/* Fill in a Tx ring entry */
 	bdp = txq->bd.cur;
-	last_bdp = bdp;
 
 	/* Set buffer length and buffer pointer */
 	bufaddr = skb->data;
@@ -472,6 +471,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 			return NETDEV_TX_OK;
 		}
 	} else {
+		last_bdp = bdp;
 		status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
 		if (fep->bufdesc_ex) {
 			estatus = BD_ENET_TX_INT;
-- 
2.5.0

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

* [PATCH net-next 30/40] net: fec: move last_bdp assignment for symmetry
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

This way both if clauses assign last_bdp instead
of only one clause overriding the default.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 3a82bfe..b829c29 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -436,7 +436,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 
 	/* Fill in a Tx ring entry */
 	bdp = txq->bd.cur;
-	last_bdp = bdp;
 
 	/* Set buffer length and buffer pointer */
 	bufaddr = skb->data;
@@ -472,6 +471,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 			return NETDEV_TX_OK;
 		}
 	} else {
+		last_bdp = bdp;
 		status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
 		if (fep->bufdesc_ex) {
 			estatus = BD_ENET_TX_INT;
-- 
2.5.0

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

* [PATCH net-next 31/40] net: fec: don't transfer ownership until entire tso is queued
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Otherwise, we cannot undo our work if an error condition arises
later.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index b829c29..ee6cd69 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -590,7 +590,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 static int
 fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 			 struct sk_buff *skb, struct net_device *ndev,
-			 struct bufdesc *bdp, int index)
+			 struct bufdesc *bdp, int index,
+			 unsigned short *pstatus)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
@@ -632,9 +633,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 		ebdp->cbd_bdu = 0;
 		ebdp->cbd_esc = estatus;
 	}
-
-	bdp->cbd_sc = status;
-
+	*pstatus = status;
 	return 0;
 }
 
@@ -646,7 +645,10 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	int total_len, data_left;
 	struct bufdesc *bdp = txq->bd.cur;
+	struct bufdesc *first_bdp = bdp;
 	struct tso_t tso;
+	unsigned short status = 0;
+	unsigned short *pstatus = &status;
 	unsigned int index = 0;
 	int ret;
 
@@ -676,7 +678,8 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 		/* prepare packet headers: MAC + IP + TCP */
 		hdr = txq->tso_hdrs + index * TSO_HEADER_SIZE;
 		tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
-		ret = fec_enet_txq_put_hdr_tso(txq, skb, ndev, bdp, index);
+		ret = fec_enet_txq_put_hdr_tso(txq, skb, ndev, bdp, index,
+					       pstatus);
 		if (ret)
 			goto err_release;
 
@@ -700,12 +703,23 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 		}
 
 		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+		pstatus = &bdp->cbd_sc;
 	}
 
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
-
 	skb_tx_timestamp(skb);
+	/* Make sure the updates to rest of the descriptor are performed before
+	 * transferring ownership.
+	 */
+	wmb();
+	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
+	 */
+	first_bdp->cbd_sc = status;
+	/* Make sure ownership is transferred before the
+	 * update to txq->bd.cur.
+	 */
+	wmb();
 	txq->bd.cur = bdp;
 
 	/* Trigger transmission start */
-- 
2.5.0

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

* [PATCH net-next 31/40] net: fec: don't transfer ownership until entire tso is queued
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Otherwise, we cannot undo our work if an error condition arises
later.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index b829c29..ee6cd69 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -590,7 +590,8 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
 static int
 fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 			 struct sk_buff *skb, struct net_device *ndev,
-			 struct bufdesc *bdp, int index)
+			 struct bufdesc *bdp, int index,
+			 unsigned short *pstatus)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
@@ -632,9 +633,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
 		ebdp->cbd_bdu = 0;
 		ebdp->cbd_esc = estatus;
 	}
-
-	bdp->cbd_sc = status;
-
+	*pstatus = status;
 	return 0;
 }
 
@@ -646,7 +645,10 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	int total_len, data_left;
 	struct bufdesc *bdp = txq->bd.cur;
+	struct bufdesc *first_bdp = bdp;
 	struct tso_t tso;
+	unsigned short status = 0;
+	unsigned short *pstatus = &status;
 	unsigned int index = 0;
 	int ret;
 
@@ -676,7 +678,8 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 		/* prepare packet headers: MAC + IP + TCP */
 		hdr = txq->tso_hdrs + index * TSO_HEADER_SIZE;
 		tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
-		ret = fec_enet_txq_put_hdr_tso(txq, skb, ndev, bdp, index);
+		ret = fec_enet_txq_put_hdr_tso(txq, skb, ndev, bdp, index,
+					       pstatus);
 		if (ret)
 			goto err_release;
 
@@ -700,12 +703,23 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 		}
 
 		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+		pstatus = &bdp->cbd_sc;
 	}
 
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
-
 	skb_tx_timestamp(skb);
+	/* Make sure the updates to rest of the descriptor are performed before
+	 * transferring ownership.
+	 */
+	wmb();
+	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
+	 */
+	first_bdp->cbd_sc = status;
+	/* Make sure ownership is transferred before the
+	 * update to txq->bd.cur.
+	 */
+	wmb();
 	txq->bd.cur = bdp;
 
 	/* Trigger transmission start */
-- 
2.5.0

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

* [PATCH net-next 32/40] net: fec: fix err_release in fec_enet_txq_submit_tso
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Unmap descriptors upon error.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index ee6cd69..9da2c6d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -319,6 +319,18 @@ fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)
 	return 0;
 }
 
+static void unmap_descriptors(struct fec_enet_private *fep,
+			      struct fec_enet_priv_tx_q *txq,
+			      struct bufdesc *bdp, struct bufdesc *end)
+{
+	while (bdp != end) {
+		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+				 bdp->cbd_datlen, DMA_TO_DEVICE);
+		bdp->cbd_bufaddr = 0;
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+	}
+}
+
 static struct bufdesc *
 fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 			     struct sk_buff *skb,
@@ -335,7 +347,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 	unsigned int index;
 	void *bufaddr;
 	dma_addr_t addr;
-	int i;
 
 	for (frag = 0; frag < nr_frags; frag++) {
 		this_frag = &skb_shinfo(skb)->frags[frag];
@@ -397,13 +408,8 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 	return bdp;
 dma_mapping_error:
-	bdp = txq->bd.cur;
-	for (i = 0; i < frag; i++) {
-		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
-		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-				bdp->cbd_datlen, DMA_TO_DEVICE);
-		bdp->cbd_bufaddr = 0;
-	}
+	unmap_descriptors(fep, txq,
+			  fec_enet_get_nextdesc(txq->bd.cur, &txq->bd), bdp);
 	return ERR_PTR(-ENOMEM);
 }
 
@@ -733,8 +739,9 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	return 0;
 
 err_release:
-	/* TODO: Release all used data descriptors for TSO */
-	return ret;
+	unmap_descriptors(fep, txq, first_bdp, bdp);
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
 }
 
 static netdev_tx_t
-- 
2.5.0

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

* [PATCH net-next 32/40] net: fec: fix err_release in fec_enet_txq_submit_tso
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Unmap descriptors upon error.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index ee6cd69..9da2c6d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -319,6 +319,18 @@ fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)
 	return 0;
 }
 
+static void unmap_descriptors(struct fec_enet_private *fep,
+			      struct fec_enet_priv_tx_q *txq,
+			      struct bufdesc *bdp, struct bufdesc *end)
+{
+	while (bdp != end) {
+		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+				 bdp->cbd_datlen, DMA_TO_DEVICE);
+		bdp->cbd_bufaddr = 0;
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+	}
+}
+
 static struct bufdesc *
 fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 			     struct sk_buff *skb,
@@ -335,7 +347,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 	unsigned int index;
 	void *bufaddr;
 	dma_addr_t addr;
-	int i;
 
 	for (frag = 0; frag < nr_frags; frag++) {
 		this_frag = &skb_shinfo(skb)->frags[frag];
@@ -397,13 +408,8 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
 
 	return bdp;
 dma_mapping_error:
-	bdp = txq->bd.cur;
-	for (i = 0; i < frag; i++) {
-		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
-		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-				bdp->cbd_datlen, DMA_TO_DEVICE);
-		bdp->cbd_bufaddr = 0;
-	}
+	unmap_descriptors(fep, txq,
+			  fec_enet_get_nextdesc(txq->bd.cur, &txq->bd), bdp);
 	return ERR_PTR(-ENOMEM);
 }
 
@@ -733,8 +739,9 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	return 0;
 
 err_release:
-	/* TODO: Release all used data descriptors for TSO */
-	return ret;
+	unmap_descriptors(fep, txq, first_bdp, bdp);
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
 }
 
 static netdev_tx_t
-- 
2.5.0

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

* [PATCH net-next 33/40] net: fec: shrink the window for 'tx int lost'
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Perform skb_tx_timestamp before transferring ownership

This shrinks the window for 'tx int lost'
If the packet is transmitted and napi clears the tx interrupt
before the txq->bd.cur assignment, then the tx interrupt is
effectively lost.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 9da2c6d..512b1ad 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -510,27 +510,24 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	index = fec_enet_get_bd_index(last_bdp, &txq->bd);
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
+	last_bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
+	skb_tx_timestamp(skb);
 
 	/* Make sure the updates to rest of the descriptor are performed before
 	 * transferring ownership.
 	 */
 	wmb();
 
-	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
-	 * it's the last BD of the frame, and to put the CRC on the end.
+	/* Send it on its way.  Transfer ownership
+	 * Make sure the update to bdp and tx_skbuff are performed before
+	 * the update to txq->bd.cur.
+	 * Keep window for interrupt between the next 3 lines as small as
+	 * possible, to avoid "tx int lost" in case no more tx interrupts
+	 * happen within 2 seconds.
 	 */
 	bdp->cbd_sc = status;
-
-	/* If this was the last BD in the ring, start at the beginning again. */
-	bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
-
-	skb_tx_timestamp(skb);
-
-	/* Make sure the update to bdp and tx_skbuff are performed before
-	 * txq->bd.cur.
-	 */
 	wmb();
-	txq->bd.cur = bdp;
+	txq->bd.cur = last_bdp;
 
 	/* Trigger transmission start */
 	writel(0, txq->bd.reg_desc_active);
@@ -719,12 +716,12 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	 * transferring ownership.
 	 */
 	wmb();
-	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
+	/* Send it on its way.  Transfer ownership
+	 * Keep window for interrupt between the next 3 lines as small as
+	 * possible, to avoid "tx int lost" in case no more tx interrupts
+	 * happen within 2 seconds.
 	 */
 	first_bdp->cbd_sc = status;
-	/* Make sure ownership is transferred before the
-	 * update to txq->bd.cur.
-	 */
 	wmb();
 	txq->bd.cur = bdp;
 
-- 
2.5.0

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

* [PATCH net-next 33/40] net: fec: shrink the window for 'tx int lost'
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

Perform skb_tx_timestamp before transferring ownership

This shrinks the window for 'tx int lost'
If the packet is transmitted and napi clears the tx interrupt
before the txq->bd.cur assignment, then the tx interrupt is
effectively lost.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 9da2c6d..512b1ad 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -510,27 +510,24 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 	index = fec_enet_get_bd_index(last_bdp, &txq->bd);
 	/* Save skb pointer */
 	txq->tx_skbuff[index] = skb;
+	last_bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
+	skb_tx_timestamp(skb);
 
 	/* Make sure the updates to rest of the descriptor are performed before
 	 * transferring ownership.
 	 */
 	wmb();
 
-	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
-	 * it's the last BD of the frame, and to put the CRC on the end.
+	/* Send it on its way.  Transfer ownership
+	 * Make sure the update to bdp and tx_skbuff are performed before
+	 * the update to txq->bd.cur.
+	 * Keep window for interrupt between the next 3 lines as small as
+	 * possible, to avoid "tx int lost" in case no more tx interrupts
+	 * happen within 2 seconds.
 	 */
 	bdp->cbd_sc = status;
-
-	/* If this was the last BD in the ring, start at the beginning again. */
-	bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
-
-	skb_tx_timestamp(skb);
-
-	/* Make sure the update to bdp and tx_skbuff are performed before
-	 * txq->bd.cur.
-	 */
 	wmb();
-	txq->bd.cur = bdp;
+	txq->bd.cur = last_bdp;
 
 	/* Trigger transmission start */
 	writel(0, txq->bd.reg_desc_active);
@@ -719,12 +716,12 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
 	 * transferring ownership.
 	 */
 	wmb();
-	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
+	/* Send it on its way.  Transfer ownership
+	 * Keep window for interrupt between the next 3 lines as small as
+	 * possible, to avoid "tx int lost" in case no more tx interrupts
+	 * happen within 2 seconds.
 	 */
 	first_bdp->cbd_sc = status;
-	/* Make sure ownership is transferred before the
-	 * update to txq->bd.cur.
-	 */
 	wmb();
 	txq->bd.cur = bdp;
 
-- 
2.5.0

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

* [PATCH net-next 34/40] net: fec: update dirty_tx even if no skb
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

If dirty_tx isn't updated, then dma_unmap_single
will be called twice.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 512b1ad..8dea600 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1236,10 +1236,8 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 			dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
 					bdp->cbd_datlen, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
-		if (!skb) {
-			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
-			continue;
-		}
+		if (!skb)
+			goto skb_done;
 
 		/* Check for errors. */
 		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
@@ -1278,7 +1276,7 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 
 		/* Free the sk buffer associated with this last transmit */
 		dev_kfree_skb_any(skb);
-
+skb_done:
 		/* Make sure the update to bdp and tx_skbuff are performed
 		 * before dirty_tx
 		 */
-- 
2.5.0

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

* [PATCH net-next 34/40] net: fec: update dirty_tx even if no skb
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

If dirty_tx isn't updated, then dma_unmap_single
will be called twice.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 512b1ad..8dea600 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1236,10 +1236,8 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 			dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
 					bdp->cbd_datlen, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
-		if (!skb) {
-			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
-			continue;
-		}
+		if (!skb)
+			goto skb_done;
 
 		/* Check for errors. */
 		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
@@ -1278,7 +1276,7 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 
 		/* Free the sk buffer associated with this last transmit */
 		dev_kfree_skb_any(skb);
-
+skb_done:
 		/* Make sure the update to bdp and tx_skbuff are performed
 		 * before dirty_tx
 		 */
-- 
2.5.0

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

* [PATCH net-next 35/40] net: fec: rename dirty_tx to pending_tx
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:25   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

dirty_tx always pointed to the last entry that was
trasmitted. pending_tx always points to the next entry
to be transmitted. This should be a little more efficient.

This will allow 1 more entry in the queue to be used.
That is, ring_size -1 entries instead of ring_size -2.

This also allows the removal of fec_enet_get_prevdesc.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      | 14 +++++-------
 drivers/net/ethernet/freescale/fec_main.c | 38 ++++++++++---------------------
 2 files changed, 18 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index d2ca2e2..a16e47e 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -440,6 +440,10 @@ struct bufdesc_prop {
 	unsigned char dsize_log2;
 };
 
+/* bd.cur points to the currently available buffer.
+ * pending_tx tracks the current buffer that is being sent by the
+ * controller.  When bd.cur and pending_tx are equal, nothing is pending.
+ */
 struct fec_enet_priv_tx_q {
 	struct bufdesc_prop bd;
 	unsigned char *tx_bounce[TX_RING_SIZE];
@@ -448,7 +452,7 @@ struct fec_enet_priv_tx_q {
 	unsigned short tx_stop_threshold;
 	unsigned short tx_wake_threshold;
 
-	struct bufdesc	*dirty_tx;
+	struct bufdesc	*pending_tx;
 	char *tso_hdrs;
 	dma_addr_t tso_hdrs_dma;
 };
@@ -458,13 +462,7 @@ struct fec_enet_priv_rx_q {
 	struct  sk_buff *rx_skbuff[RX_RING_SIZE];
 };
 
-/* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors.  The
- * cur_rx and cur_tx point to the currently available buffer.
- * The dirty_tx tracks the current buffer that is being sent by the
- * controller.  The cur_tx and dirty_tx are equal under both completely
- * empty and completely full conditions.  The empty/ready indicator in
- * the buffer descriptor determines the actual condition.
+/* The FEC buffer descriptors track the ring buffers.
  */
 struct fec_enet_private {
 	/* Hardware registers of the FEC device */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 8dea600..9db645d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -226,13 +226,6 @@ static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp,
 			: (struct bufdesc *)(((unsigned)bdp) + bd->dsize);
 }
 
-static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp,
-					     struct bufdesc_prop *bd)
-{
-	return (bdp <= bd->base) ? bd->last
-			: (struct bufdesc *)(((unsigned)bdp) - bd->dsize);
-}
-
 static int fec_enet_get_bd_index(struct bufdesc *bdp,
 				 struct bufdesc_prop *bd)
 {
@@ -243,7 +236,7 @@ static int fec_enet_get_free_txdesc_num(struct fec_enet_priv_tx_q *txq)
 {
 	int entries;
 
-	entries = (((const char *)txq->dirty_tx -
+	entries = (((const char *)txq->pending_tx -
 			(const char *)txq->bd.cur) >> txq->bd.dsize_log2) - 1;
 
 	return entries >= 0 ? entries : entries + txq->bd.ring_size;
@@ -288,7 +281,7 @@ static void fec_dump(struct net_device *ndev)
 			pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
 				index,
 				bdp == txq->bd.cur ? 'S' : ' ',
-				bdp == txq->dirty_tx ? 'H' : ' ',
+				bdp == txq->pending_tx ? 'H' : ' ',
 				bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
 				txq->tx_skbuff[index]);
 			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
@@ -802,6 +795,7 @@ static void fec_enet_bd_init(struct net_device *dev)
 		txq = fep->tx_queue[q];
 		bdp = txq->bd.base;
 		txq->bd.cur = bdp;
+		txq->pending_tx = bdp;
 
 		for (i = 0; i < txq->bd.ring_size; i++) {
 			/* Initialize the BD for every fragment in the page. */
@@ -820,8 +814,6 @@ static void fec_enet_bd_init(struct net_device *dev)
 			bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
-		bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
-		txq->dirty_tx = bdp;
 	}
 }
 
@@ -1134,11 +1126,8 @@ fec_timeout(struct net_device *ndev)
 		int index;
 		struct sk_buff *skb = NULL;
 
-		bdp = txq->dirty_tx;
-		while (1) {
-			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
-			if (bdp == txq->bd.cur)
-				break;
+		bdp = txq->pending_tx;
+		while (bdp != txq->bd.cur) {
 			index = fec_enet_get_bd_index(bdp, &txq->bd);
 			skb = txq->tx_skbuff[index];
 			if (skb) {
@@ -1147,6 +1136,7 @@ fec_timeout(struct net_device *ndev)
 					events |= txint_flags[i];
 				break;
 			}
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
 	}
 	if (events) {
@@ -1208,12 +1198,8 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 	int	index = 0;
 	int	entries_free;
 
-	/* get next bdp of dirty_tx */
 	nq = netdev_get_tx_queue(ndev, txq->bd.qid);
-	bdp = txq->dirty_tx;
-
-	/* get next bdp of dirty_tx */
-	bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+	bdp = txq->pending_tx;
 
 	while (bdp != READ_ONCE(txq->bd.cur)) {
 		/* Order the load of bd.cur and cbd_sc */
@@ -1277,14 +1263,14 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 		/* Free the sk buffer associated with this last transmit */
 		dev_kfree_skb_any(skb);
 skb_done:
+		/* Update pointer to next buffer descriptor to be transmitted */
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+
 		/* Make sure the update to bdp and tx_skbuff are performed
-		 * before dirty_tx
+		 * before pending_tx
 		 */
 		wmb();
-		txq->dirty_tx = bdp;
-
-		/* Update pointer to next buffer descriptor to be transmitted */
-		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+		txq->pending_tx = bdp;
 
 		/* Since we have freed up a buffer, the ring is no longer full
 		 */
-- 
2.5.0

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

* [PATCH net-next 35/40] net: fec: rename dirty_tx to pending_tx
@ 2016-01-28 21:25   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

dirty_tx always pointed to the last entry that was
trasmitted. pending_tx always points to the next entry
to be transmitted. This should be a little more efficient.

This will allow 1 more entry in the queue to be used.
That is, ring_size -1 entries instead of ring_size -2.

This also allows the removal of fec_enet_get_prevdesc.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec.h      | 14 +++++-------
 drivers/net/ethernet/freescale/fec_main.c | 38 ++++++++++---------------------
 2 files changed, 18 insertions(+), 34 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index d2ca2e2..a16e47e 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -440,6 +440,10 @@ struct bufdesc_prop {
 	unsigned char dsize_log2;
 };
 
+/* bd.cur points to the currently available buffer.
+ * pending_tx tracks the current buffer that is being sent by the
+ * controller.  When bd.cur and pending_tx are equal, nothing is pending.
+ */
 struct fec_enet_priv_tx_q {
 	struct bufdesc_prop bd;
 	unsigned char *tx_bounce[TX_RING_SIZE];
@@ -448,7 +452,7 @@ struct fec_enet_priv_tx_q {
 	unsigned short tx_stop_threshold;
 	unsigned short tx_wake_threshold;
 
-	struct bufdesc	*dirty_tx;
+	struct bufdesc	*pending_tx;
 	char *tso_hdrs;
 	dma_addr_t tso_hdrs_dma;
 };
@@ -458,13 +462,7 @@ struct fec_enet_priv_rx_q {
 	struct  sk_buff *rx_skbuff[RX_RING_SIZE];
 };
 
-/* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors.  The
- * cur_rx and cur_tx point to the currently available buffer.
- * The dirty_tx tracks the current buffer that is being sent by the
- * controller.  The cur_tx and dirty_tx are equal under both completely
- * empty and completely full conditions.  The empty/ready indicator in
- * the buffer descriptor determines the actual condition.
+/* The FEC buffer descriptors track the ring buffers.
  */
 struct fec_enet_private {
 	/* Hardware registers of the FEC device */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 8dea600..9db645d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -226,13 +226,6 @@ static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp,
 			: (struct bufdesc *)(((unsigned)bdp) + bd->dsize);
 }
 
-static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp,
-					     struct bufdesc_prop *bd)
-{
-	return (bdp <= bd->base) ? bd->last
-			: (struct bufdesc *)(((unsigned)bdp) - bd->dsize);
-}
-
 static int fec_enet_get_bd_index(struct bufdesc *bdp,
 				 struct bufdesc_prop *bd)
 {
@@ -243,7 +236,7 @@ static int fec_enet_get_free_txdesc_num(struct fec_enet_priv_tx_q *txq)
 {
 	int entries;
 
-	entries = (((const char *)txq->dirty_tx -
+	entries = (((const char *)txq->pending_tx -
 			(const char *)txq->bd.cur) >> txq->bd.dsize_log2) - 1;
 
 	return entries >= 0 ? entries : entries + txq->bd.ring_size;
@@ -288,7 +281,7 @@ static void fec_dump(struct net_device *ndev)
 			pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
 				index,
 				bdp == txq->bd.cur ? 'S' : ' ',
-				bdp == txq->dirty_tx ? 'H' : ' ',
+				bdp == txq->pending_tx ? 'H' : ' ',
 				bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
 				txq->tx_skbuff[index]);
 			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
@@ -802,6 +795,7 @@ static void fec_enet_bd_init(struct net_device *dev)
 		txq = fep->tx_queue[q];
 		bdp = txq->bd.base;
 		txq->bd.cur = bdp;
+		txq->pending_tx = bdp;
 
 		for (i = 0; i < txq->bd.ring_size; i++) {
 			/* Initialize the BD for every fragment in the page. */
@@ -820,8 +814,6 @@ static void fec_enet_bd_init(struct net_device *dev)
 			bdp->cbd_sc = (bdp == txq->bd.last) ? BD_SC_WRAP : 0;
 			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
-		bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
-		txq->dirty_tx = bdp;
 	}
 }
 
@@ -1134,11 +1126,8 @@ fec_timeout(struct net_device *ndev)
 		int index;
 		struct sk_buff *skb = NULL;
 
-		bdp = txq->dirty_tx;
-		while (1) {
-			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
-			if (bdp == txq->bd.cur)
-				break;
+		bdp = txq->pending_tx;
+		while (bdp != txq->bd.cur) {
 			index = fec_enet_get_bd_index(bdp, &txq->bd);
 			skb = txq->tx_skbuff[index];
 			if (skb) {
@@ -1147,6 +1136,7 @@ fec_timeout(struct net_device *ndev)
 					events |= txint_flags[i];
 				break;
 			}
+			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
 		}
 	}
 	if (events) {
@@ -1208,12 +1198,8 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 	int	index = 0;
 	int	entries_free;
 
-	/* get next bdp of dirty_tx */
 	nq = netdev_get_tx_queue(ndev, txq->bd.qid);
-	bdp = txq->dirty_tx;
-
-	/* get next bdp of dirty_tx */
-	bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+	bdp = txq->pending_tx;
 
 	while (bdp != READ_ONCE(txq->bd.cur)) {
 		/* Order the load of bd.cur and cbd_sc */
@@ -1277,14 +1263,14 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_private *fep,
 		/* Free the sk buffer associated with this last transmit */
 		dev_kfree_skb_any(skb);
 skb_done:
+		/* Update pointer to next buffer descriptor to be transmitted */
+		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+
 		/* Make sure the update to bdp and tx_skbuff are performed
-		 * before dirty_tx
+		 * before pending_tx
 		 */
 		wmb();
-		txq->dirty_tx = bdp;
-
-		/* Update pointer to next buffer descriptor to be transmitted */
-		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
+		txq->pending_tx = bdp;
 
 		/* Since we have freed up a buffer, the ring is no longer full
 		 */
-- 
2.5.0

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

* [PATCH net-next 36/40] net: fec: use mac set by bootloader before fuses
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:26   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

If a bootloader initializes the mac, prefer that
to device tree or fuses.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 33 +++++++++++++------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 9db645d..11968a9 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1625,16 +1625,24 @@ static void fec_get_mac(struct net_device *ndev)
 	struct fec_platform_data *pdata = dev_get_platdata(&fep->pdev->dev);
 	unsigned char *iap, tmpaddr[ETH_ALEN];
 
-	/*
-	 * try to get mac address in following order:
+	/* try to get mac address in following order:
 	 *
 	 * 1) module parameter via kernel command line in form
 	 *    fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0
 	 */
 	iap = macaddr;
 
-	/*
-	 * 2) from device tree data
+	/* 2) FEC mac registers set by bootloader
+	 */
+	if (!is_valid_ether_addr(iap)) {
+		*((__be32 *)&tmpaddr[0]) =
+			cpu_to_be32(readl(fep->hwp + FEC_ADDR_LOW));
+		*((__be16 *)&tmpaddr[4]) =
+			cpu_to_be16(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
+		iap = &tmpaddr[0];
+	}
+
+	/* 3) from device tree data
 	 */
 	if (!is_valid_ether_addr(iap)) {
 		struct device_node *np = fep->pdev->dev.of_node;
@@ -1645,8 +1653,7 @@ static void fec_get_mac(struct net_device *ndev)
 		}
 	}
 
-	/*
-	 * 3) from flash or fuse (via platform data)
+	/* 4) from flash or fuse (via platform data)
 	 */
 	if (!is_valid_ether_addr(iap)) {
 #ifdef CONFIG_M5272
@@ -1658,19 +1665,7 @@ static void fec_get_mac(struct net_device *ndev)
 #endif
 	}
 
-	/*
-	 * 4) FEC mac registers set by bootloader
-	 */
-	if (!is_valid_ether_addr(iap)) {
-		*((__be32 *) &tmpaddr[0]) =
-			cpu_to_be32(readl(fep->hwp + FEC_ADDR_LOW));
-		*((__be16 *) &tmpaddr[4]) =
-			cpu_to_be16(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
-		iap = &tmpaddr[0];
-	}
-
-	/*
-	 * 5) random mac address
+	/* 5) random mac address
 	 */
 	if (!is_valid_ether_addr(iap)) {
 		/* Report it and use a random ethernet address instead */
-- 
2.5.0

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

* [PATCH net-next 36/40] net: fec: use mac set by bootloader before fuses
@ 2016-01-28 21:26   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: linux-arm-kernel

If a bootloader initializes the mac, prefer that
to device tree or fuses.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 33 +++++++++++++------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 9db645d..11968a9 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1625,16 +1625,24 @@ static void fec_get_mac(struct net_device *ndev)
 	struct fec_platform_data *pdata = dev_get_platdata(&fep->pdev->dev);
 	unsigned char *iap, tmpaddr[ETH_ALEN];
 
-	/*
-	 * try to get mac address in following order:
+	/* try to get mac address in following order:
 	 *
 	 * 1) module parameter via kernel command line in form
 	 *    fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0
 	 */
 	iap = macaddr;
 
-	/*
-	 * 2) from device tree data
+	/* 2) FEC mac registers set by bootloader
+	 */
+	if (!is_valid_ether_addr(iap)) {
+		*((__be32 *)&tmpaddr[0]) =
+			cpu_to_be32(readl(fep->hwp + FEC_ADDR_LOW));
+		*((__be16 *)&tmpaddr[4]) =
+			cpu_to_be16(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
+		iap = &tmpaddr[0];
+	}
+
+	/* 3) from device tree data
 	 */
 	if (!is_valid_ether_addr(iap)) {
 		struct device_node *np = fep->pdev->dev.of_node;
@@ -1645,8 +1653,7 @@ static void fec_get_mac(struct net_device *ndev)
 		}
 	}
 
-	/*
-	 * 3) from flash or fuse (via platform data)
+	/* 4) from flash or fuse (via platform data)
 	 */
 	if (!is_valid_ether_addr(iap)) {
 #ifdef CONFIG_M5272
@@ -1658,19 +1665,7 @@ static void fec_get_mac(struct net_device *ndev)
 #endif
 	}
 
-	/*
-	 * 4) FEC mac registers set by bootloader
-	 */
-	if (!is_valid_ether_addr(iap)) {
-		*((__be32 *) &tmpaddr[0]) =
-			cpu_to_be32(readl(fep->hwp + FEC_ADDR_LOW));
-		*((__be16 *) &tmpaddr[4]) =
-			cpu_to_be16(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
-		iap = &tmpaddr[0];
-	}
-
-	/*
-	 * 5) random mac address
+	/* 5) random mac address
 	 */
 	if (!is_valid_ether_addr(iap)) {
 		/* Report it and use a random ethernet address instead */
-- 
2.5.0

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

* [PATCH net-next 37/40] net: fec: add events device file
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:26   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

This is for debug purposes. If a receive interrupt
is lost, writing to this file can recover the FEC.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 52 +++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 11968a9..00c9b7e 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3273,6 +3273,53 @@ fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, int *num_rx)
 
 }
 
+static ssize_t fec_show_events(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	int qid;
+	int complete_cnt[] = {0, 0, 0};
+
+	for (qid = 0; qid < fep->num_rx_queues; qid++) {
+		struct fec_enet_priv_rx_q *rxq = fep->rx_queue[qid];
+		struct bufdesc *bdp = rxq->bd.cur;
+
+		do {
+			unsigned status = bdp->cbd_sc;
+
+			if (status & BD_ENET_RX_EMPTY)
+				break;
+			complete_cnt[qid]++;
+			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
+		} while (bdp != rxq->bd.cur);
+	}
+	return sprintf(buf, "%08x %08x %08x %08x %d %d %d\n", fep->events,
+			fep->last_ievents,
+			readl(fep->hwp + FEC_IEVENT),
+			readl(fep->hwp + FEC_IMASK),
+			complete_cnt[0], complete_cnt[1], complete_cnt[2]);
+}
+
+static ssize_t fec_set_events(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	unsigned long events;
+
+	/* Disable the RX/TX interrupt */
+	writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK);
+	if (!kstrtoul(buf, 16, &events))
+		fep->events |= events;
+	napi_schedule(&fep->napi);
+	netif_wake_queue(fep->netdev);
+	return count;
+}
+
+static DEVICE_ATTR(events, 0644, fec_show_events, fec_set_events);
+
 static int
 fec_probe(struct platform_device *pdev)
 {
@@ -3451,6 +3498,9 @@ fec_probe(struct platform_device *pdev)
 	fec_enet_clk_enable(ndev, false);
 	pinctrl_pm_select_sleep_state(&pdev->dev);
 
+	ret = device_create_file(&pdev->dev, &dev_attr_events);
+	if (ret)
+		dev_err(&pdev->dev, "Error creating fec sysfs file(%d)\n", ret);
 	ret = register_netdev(ndev);
 	if (ret)
 		goto failed_register;
@@ -3470,6 +3520,7 @@ fec_probe(struct platform_device *pdev)
 	return 0;
 
 failed_register:
+	device_remove_file(&pdev->dev, &dev_attr_events);
 	fec_enet_mii_remove(fep);
 failed_mii_init:
 failed_irq:
@@ -3496,6 +3547,7 @@ fec_drv_remove(struct platform_device *pdev)
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
+	device_remove_file(&pdev->dev, &dev_attr_events);
 	cancel_work_sync(&fep->tx_timeout_work);
 	fec_ptp_stop(pdev);
 	unregister_netdev(ndev);
-- 
2.5.0

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

* [PATCH net-next 37/40] net: fec: add events device file
@ 2016-01-28 21:26   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: linux-arm-kernel

This is for debug purposes. If a receive interrupt
is lost, writing to this file can recover the FEC.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 52 +++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 11968a9..00c9b7e 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3273,6 +3273,53 @@ fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, int *num_rx)
 
 }
 
+static ssize_t fec_show_events(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	int qid;
+	int complete_cnt[] = {0, 0, 0};
+
+	for (qid = 0; qid < fep->num_rx_queues; qid++) {
+		struct fec_enet_priv_rx_q *rxq = fep->rx_queue[qid];
+		struct bufdesc *bdp = rxq->bd.cur;
+
+		do {
+			unsigned status = bdp->cbd_sc;
+
+			if (status & BD_ENET_RX_EMPTY)
+				break;
+			complete_cnt[qid]++;
+			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
+		} while (bdp != rxq->bd.cur);
+	}
+	return sprintf(buf, "%08x %08x %08x %08x %d %d %d\n", fep->events,
+			fep->last_ievents,
+			readl(fep->hwp + FEC_IEVENT),
+			readl(fep->hwp + FEC_IMASK),
+			complete_cnt[0], complete_cnt[1], complete_cnt[2]);
+}
+
+static ssize_t fec_set_events(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	unsigned long events;
+
+	/* Disable the RX/TX interrupt */
+	writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK);
+	if (!kstrtoul(buf, 16, &events))
+		fep->events |= events;
+	napi_schedule(&fep->napi);
+	netif_wake_queue(fep->netdev);
+	return count;
+}
+
+static DEVICE_ATTR(events, 0644, fec_show_events, fec_set_events);
+
 static int
 fec_probe(struct platform_device *pdev)
 {
@@ -3451,6 +3498,9 @@ fec_probe(struct platform_device *pdev)
 	fec_enet_clk_enable(ndev, false);
 	pinctrl_pm_select_sleep_state(&pdev->dev);
 
+	ret = device_create_file(&pdev->dev, &dev_attr_events);
+	if (ret)
+		dev_err(&pdev->dev, "Error creating fec sysfs file(%d)\n", ret);
 	ret = register_netdev(ndev);
 	if (ret)
 		goto failed_register;
@@ -3470,6 +3520,7 @@ fec_probe(struct platform_device *pdev)
 	return 0;
 
 failed_register:
+	device_remove_file(&pdev->dev, &dev_attr_events);
 	fec_enet_mii_remove(fep);
 failed_mii_init:
 failed_irq:
@@ -3496,6 +3547,7 @@ fec_drv_remove(struct platform_device *pdev)
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
+	device_remove_file(&pdev->dev, &dev_attr_events);
 	cancel_work_sync(&fep->tx_timeout_work);
 	fec_ptp_stop(pdev);
 	unregister_netdev(ndev);
-- 
2.5.0

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

* [PATCH net-next 38/40] net: fec: recover from lost rxf_0 interrupt
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:26   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

The following is true of linux-3.14. I have not been able
to verify on mainline, because I cannot get the cpuidle
driver to work.

If gpio6 workaround is not used for interrupts, then
it is possible for the entire receive queue to become
full without an interrupt. If that happens, and the last
rxf_0 interrupt is lost, then the FEC can no longer receive
packets. However packet transmission is still fine, so the tx
watchdog will never fire. The only way to recover before this
is a ifconfig down/up. Skipping the FEC_ENET_RXF_0 check
will allow the rx queue to recover from the condition when
the next packet is transmitted.

This patch also has the advantage of increasing iperf speed.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 00c9b7e..8372d9b 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1608,9 +1608,10 @@ static int fec_enet_napi_q1(struct napi_struct *napi, int budget)
 		}
 
 		writel(events, fep->hwp + FEC_IEVENT);
-		if (events & FEC_ENET_RXF_0)
-			pkts += fec_rxq(ndev, fep, fep->rx_queue[0],
-					budget - pkts);
+		/* don't check FEC_ENET_RXF_0, to recover from a full queue
+		 * but bit clear condition
+		 */
+		pkts += fec_rxq(ndev, fep, fep->rx_queue[0], budget - pkts);
 		if (events & FEC_ENET_TXF_0)
 			fec_txq(ndev, fep, fep->tx_queue[0]);
 	} while (pkts < budget);
-- 
2.5.0

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

* [PATCH net-next 38/40] net: fec: recover from lost rxf_0 interrupt
@ 2016-01-28 21:26   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: linux-arm-kernel

The following is true of linux-3.14. I have not been able
to verify on mainline, because I cannot get the cpuidle
driver to work.

If gpio6 workaround is not used for interrupts, then
it is possible for the entire receive queue to become
full without an interrupt. If that happens, and the last
rxf_0 interrupt is lost, then the FEC can no longer receive
packets. However packet transmission is still fine, so the tx
watchdog will never fire. The only way to recover before this
is a ifconfig down/up. Skipping the FEC_ENET_RXF_0 check
will allow the rx queue to recover from the condition when
the next packet is transmitted.

This patch also has the advantage of increasing iperf speed.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 00c9b7e..8372d9b 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1608,9 +1608,10 @@ static int fec_enet_napi_q1(struct napi_struct *napi, int budget)
 		}
 
 		writel(events, fep->hwp + FEC_IEVENT);
-		if (events & FEC_ENET_RXF_0)
-			pkts += fec_rxq(ndev, fep, fep->rx_queue[0],
-					budget - pkts);
+		/* don't check FEC_ENET_RXF_0, to recover from a full queue
+		 * but bit clear condition
+		 */
+		pkts += fec_rxq(ndev, fep, fep->rx_queue[0], budget - pkts);
 		if (events & FEC_ENET_TXF_0)
 			fec_txq(ndev, fep, fep->tx_queue[0]);
 	} while (pkts < budget);
-- 
2.5.0

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

* [PATCH net-next 39/40] ARM: dts: imx6qdl-nitrogen6x: add phy interrupt to eliminate polling
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:26   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
index caeed56..1d42331 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
@@ -288,6 +288,15 @@
 	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
 			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
 	status = "okay";
+	phy-handle = <&ethphy>;
+	mdio {
+		#address-cells = <0>;
+		#size-cells = <1>;
+		ethphy: ethernet-phy@6 {
+			reg = <6>;
+			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
+		};
+	};
 };
 
 &hdmi {
@@ -409,6 +418,8 @@
 				/* Phy reset */
 				MX6QDL_PAD_ENET_RXD0__GPIO1_IO27	0x000b0
 				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+				/* ethernet phy interrupt */
+				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x1b0b0
 			>;
 		};
 
-- 
2.5.0

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

* [PATCH net-next 39/40] ARM: dts: imx6qdl-nitrogen6x: add phy interrupt to eliminate polling
@ 2016-01-28 21:26   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
index caeed56..1d42331 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
@@ -288,6 +288,15 @@
 	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
 			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
 	status = "okay";
+	phy-handle = <&ethphy>;
+	mdio {
+		#address-cells = <0>;
+		#size-cells = <1>;
+		ethphy: ethernet-phy at 6 {
+			reg = <6>;
+			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
+		};
+	};
 };
 
 &hdmi {
@@ -409,6 +418,8 @@
 				/* Phy reset */
 				MX6QDL_PAD_ENET_RXD0__GPIO1_IO27	0x000b0
 				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+				/* ethernet phy interrupt */
+				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x1b0b0
 			>;
 		};
 
-- 
2.5.0

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

* [PATCH net-next 40/40] ARM: dts: imx6qdl-nitrogen6_max: add phy interrupt to eliminate polling
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 21:26   ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: netdev, davem, B38611
  Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
	laci, shawnguo, Troy Kisky

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
index a35d54f..771f650 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
@@ -386,6 +386,15 @@
 	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
 			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
 	status = "okay";
+	phy-handle = <&ethphy>;
+	mdio {
+		#address-cells = <0>;
+		#size-cells = <1>;
+		ethphy: ethernet-phy@6 {
+			reg = <6>;
+			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
+		};
+	};
 };
 
 &hdmi {
-- 
2.5.0

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

* [PATCH net-next 40/40] ARM: dts: imx6qdl-nitrogen6_max: add phy interrupt to eliminate polling
@ 2016-01-28 21:26   ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-28 21:26 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
index a35d54f..771f650 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
@@ -386,6 +386,15 @@
 	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
 			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
 	status = "okay";
+	phy-handle = <&ethphy>;
+	mdio {
+		#address-cells = <0>;
+		#size-cells = <1>;
+		ethphy: ethernet-phy at 6 {
+			reg = <6>;
+			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
+		};
+	};
 };
 
 &hdmi {
-- 
2.5.0

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

* Re: [PATCH net-next 08/40] net: fec: move cbd_bufaddr assignment closer to the mapping function
  2016-01-28 21:25   ` Troy Kisky
@ 2016-01-28 22:02     ` Arnd Bergmann
  -1 siblings, 0 replies; 96+ messages in thread
From: Arnd Bergmann @ 2016-01-28 22:02 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Troy Kisky, netdev, davem, B38611, fabio.estevam, andrew, linux,
	laci, l.stach, shawnguo, tremyfr, Johannes Berg

On Thursday 28 January 2016 14:25:32 Troy Kisky wrote:
> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> ---
>  drivers/net/ethernet/freescale/fec_main.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

[note: missing changelog?]

> diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
> index b87f80d..15a93f90 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -476,6 +476,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>  				estatus |= BD_ENET_TX_TS;
>  		}
>  	}
> +	bdp->cbd_bufaddr = addr;
> +	bdp->cbd_datlen = buflen;
>  
>  	if (fep->bufdesc_ex) {
>  
> @@ -499,8 +501,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>  	/* Save skb pointer */
>  	txq->tx_skbuff[index] = skb;
>  
> -	bdp->cbd_datlen = buflen;
> -	bdp->cbd_bufaddr = addr;
>  	/* Make sure the updates to rest of the descriptor are performed before
>  	 * transferring ownership.
>  	 */
> 

This patch and others in the series conflicts with the bugfix "net: fec: make
driver endian-safe" that Johannes sent this week. Can you include his fix
in your series and ensure that all descriptor accesses are done in
an endian-safe way?

	Arnd

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

* [PATCH net-next 08/40] net: fec: move cbd_bufaddr assignment closer to the mapping function
@ 2016-01-28 22:02     ` Arnd Bergmann
  0 siblings, 0 replies; 96+ messages in thread
From: Arnd Bergmann @ 2016-01-28 22:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 28 January 2016 14:25:32 Troy Kisky wrote:
> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> ---
>  drivers/net/ethernet/freescale/fec_main.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

[note: missing changelog?]

> diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
> index b87f80d..15a93f90 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -476,6 +476,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>  				estatus |= BD_ENET_TX_TS;
>  		}
>  	}
> +	bdp->cbd_bufaddr = addr;
> +	bdp->cbd_datlen = buflen;
>  
>  	if (fep->bufdesc_ex) {
>  
> @@ -499,8 +501,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>  	/* Save skb pointer */
>  	txq->tx_skbuff[index] = skb;
>  
> -	bdp->cbd_datlen = buflen;
> -	bdp->cbd_bufaddr = addr;
>  	/* Make sure the updates to rest of the descriptor are performed before
>  	 * transferring ownership.
>  	 */
> 

This patch and others in the series conflicts with the bugfix "net: fec: make
driver endian-safe" that Johannes sent this week. Can you include his fix
in your series and ensure that all descriptor accesses are done in
an endian-safe way?

	Arnd

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

* Re: [PATCH net-next 08/40] net: fec: move cbd_bufaddr assignment closer to the mapping function
  2016-01-28 22:02     ` Arnd Bergmann
@ 2016-01-28 22:14       ` Johannes Berg
  -1 siblings, 0 replies; 96+ messages in thread
From: Johannes Berg @ 2016-01-28 22:14 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Troy Kisky, netdev, davem, B38611, fabio.estevam, andrew, linux,
	laci, l.stach, shawnguo, tremyfr

On Thu, 2016-01-28 at 23:02 +0100, Arnd Bergmann wrote:
> On Thursday 28 January 2016 14:25:32 Troy Kisky wrote:
> > Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> > ---
> >  drivers/net/ethernet/freescale/fec_main.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> [note: missing changelog?]
> 
> > diff --git a/drivers/net/ethernet/freescale/fec_main.c
> > b/drivers/net/ethernet/freescale/fec_main.c
> > index b87f80d..15a93f90 100644
> > --- a/drivers/net/ethernet/freescale/fec_main.c
> > +++ b/drivers/net/ethernet/freescale/fec_main.c
> > @@ -476,6 +476,8 @@ static int fec_enet_txq_submit_skb(struct
> > fec_enet_priv_tx_q *txq,
> >  				estatus |= BD_ENET_TX_TS;
> >  		}
> >  	}
> > +	bdp->cbd_bufaddr = addr;
> > +	bdp->cbd_datlen = buflen;
> >  
> >  	if (fep->bufdesc_ex) {
> >  
> > @@ -499,8 +501,6 @@ static int fec_enet_txq_submit_skb(struct
> > fec_enet_priv_tx_q *txq,
> >  	/* Save skb pointer */
> >  	txq->tx_skbuff[index] = skb;
> >  
> > -	bdp->cbd_datlen = buflen;
> > -	bdp->cbd_bufaddr = addr;
> >  	/* Make sure the updates to rest of the descriptor are
> > performed before
> >  	 * transferring ownership.
> >  	 */
> > 
> 
> This patch and others in the series conflicts with the bugfix "net:
> fec: make driver endian-safe" that Johannes sent this week. Can you
> include his fix in your series and ensure that all descriptor
> accesses are done in an endian-safe way?
> 

My fixes are already in net.git, so you should base on a current
net.git or on net-next.git after net.git is merged there (which davem
usually does after Linus merges from him, IIRC)

johannes

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

* [PATCH net-next 08/40] net: fec: move cbd_bufaddr assignment closer to the mapping function
@ 2016-01-28 22:14       ` Johannes Berg
  0 siblings, 0 replies; 96+ messages in thread
From: Johannes Berg @ 2016-01-28 22:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2016-01-28 at 23:02 +0100, Arnd Bergmann wrote:
> On Thursday 28 January 2016 14:25:32 Troy Kisky wrote:
> > Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> > ---
> > ?drivers/net/ethernet/freescale/fec_main.c | 4 ++--
> > ?1 file changed, 2 insertions(+), 2 deletions(-)
> 
> [note: missing changelog?]
> 
> > diff --git a/drivers/net/ethernet/freescale/fec_main.c
> > b/drivers/net/ethernet/freescale/fec_main.c
> > index b87f80d..15a93f90 100644
> > --- a/drivers/net/ethernet/freescale/fec_main.c
> > +++ b/drivers/net/ethernet/freescale/fec_main.c
> > @@ -476,6 +476,8 @@ static int fec_enet_txq_submit_skb(struct
> > fec_enet_priv_tx_q *txq,
> > ?				estatus |= BD_ENET_TX_TS;
> > ?		}
> > ?	}
> > +	bdp->cbd_bufaddr = addr;
> > +	bdp->cbd_datlen = buflen;
> > ?
> > ?	if (fep->bufdesc_ex) {
> > ?
> > @@ -499,8 +501,6 @@ static int fec_enet_txq_submit_skb(struct
> > fec_enet_priv_tx_q *txq,
> > ?	/* Save skb pointer */
> > ?	txq->tx_skbuff[index] = skb;
> > ?
> > -	bdp->cbd_datlen = buflen;
> > -	bdp->cbd_bufaddr = addr;
> > ?	/* Make sure the updates to rest of the descriptor are
> > performed before
> > ?	?* transferring ownership.
> > ?	?*/
> > 
> 
> This patch and others in the series conflicts with the bugfix "net:
> fec: make driver endian-safe" that Johannes sent this week. Can you
> include his fix in your series and ensure that all descriptor
> accesses are done in an endian-safe way?
> 

My fixes are already in net.git, so you should base on a current
net.git or on net-next.git after net.git is merged there (which davem
usually does after Linus merges from him, IIRC)

johannes

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

* Re: [PATCH net-next 00/40] net: fec: cleanup/fixes
  2016-01-28 21:25 ` Troy Kisky
@ 2016-01-28 22:39   ` David Miller
  -1 siblings, 0 replies; 96+ messages in thread
From: David Miller @ 2016-01-28 22:39 UTC (permalink / raw)
  To: troy.kisky
  Cc: netdev, B38611, fabio.estevam, l.stach, andrew, tremyfr, linux,
	linux-arm-kernel, laci, shawnguo


This is way too many patches to submit at once.  Divide this into more
digestable pieces.

Also the net-next tree is not open.

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

* [PATCH net-next 00/40] net: fec: cleanup/fixes
@ 2016-01-28 22:39   ` David Miller
  0 siblings, 0 replies; 96+ messages in thread
From: David Miller @ 2016-01-28 22:39 UTC (permalink / raw)
  To: linux-arm-kernel


This is way too many patches to submit at once.  Divide this into more
digestable pieces.

Also the net-next tree is not open.

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

* Re: [PATCH net-next 00/40] net: fec: cleanup/fixes
       [not found]   ` <CAGB=+3Sip-+2Qf-KTZfoCCBcO9=9tb=pVCaEs=+eNJ1sWSRgXw@mail.gmail.com>
@ 2016-01-29  0:19       ` David Miller
  0 siblings, 0 replies; 96+ messages in thread
From: David Miller @ 2016-01-29  0:19 UTC (permalink / raw)
  To: laci
  Cc: troy.kisky, netdev, B38611, fabio.estevam, l.stach, andrew,
	tremyfr, linux, linux-arm-kernel, shawnguo

From: Laci Tele <laci@boundarydevices.com>
Date: Thu, 28 Jan 2016 23:57:10 +0100

> If he divides it, then it will be even more.

Do not top-post.

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

* [PATCH net-next 00/40] net: fec: cleanup/fixes
@ 2016-01-29  0:19       ` David Miller
  0 siblings, 0 replies; 96+ messages in thread
From: David Miller @ 2016-01-29  0:19 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laci Tele <laci@boundarydevices.com>
Date: Thu, 28 Jan 2016 23:57:10 +0100

> If he divides it, then it will be even more.

Do not top-post.

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

* Re: [PATCH net-next 08/40] net: fec: move cbd_bufaddr assignment closer to the mapping function
  2016-01-28 22:02     ` Arnd Bergmann
@ 2016-01-29 17:49       ` Troy Kisky
  -1 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-29 17:49 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: netdev, davem, B38611, fabio.estevam, andrew, linux, laci,
	l.stach, shawnguo, tremyfr, Johannes Berg

On 1/28/2016 3:02 PM, Arnd Bergmann wrote:
> On Thursday 28 January 2016 14:25:32 Troy Kisky wrote:
>> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
>> ---
>>  drivers/net/ethernet/freescale/fec_main.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> [note: missing changelog?]
> 
>> diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
>> index b87f80d..15a93f90 100644
>> --- a/drivers/net/ethernet/freescale/fec_main.c
>> +++ b/drivers/net/ethernet/freescale/fec_main.c
>> @@ -476,6 +476,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>>  				estatus |= BD_ENET_TX_TS;
>>  		}
>>  	}
>> +	bdp->cbd_bufaddr = addr;
>> +	bdp->cbd_datlen = buflen;
>>  
>>  	if (fep->bufdesc_ex) {
>>  
>> @@ -499,8 +501,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>>  	/* Save skb pointer */
>>  	txq->tx_skbuff[index] = skb;
>>  
>> -	bdp->cbd_datlen = buflen;
>> -	bdp->cbd_bufaddr = addr;
>>  	/* Make sure the updates to rest of the descriptor are performed before
>>  	 * transferring ownership.
>>  	 */
>>
> 
> This patch and others in the series conflicts with the bugfix "net: fec: make
> driver endian-safe" that Johannes sent this week. Can you include his fix
> in your series and ensure that all descriptor accesses are done in
> an endian-safe way?
> 
> 	Arnd

Sure, I'll rebase and send the first few when net-next is updated.

Thanks
Troy

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

* [PATCH net-next 08/40] net: fec: move cbd_bufaddr assignment closer to the mapping function
@ 2016-01-29 17:49       ` Troy Kisky
  0 siblings, 0 replies; 96+ messages in thread
From: Troy Kisky @ 2016-01-29 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

On 1/28/2016 3:02 PM, Arnd Bergmann wrote:
> On Thursday 28 January 2016 14:25:32 Troy Kisky wrote:
>> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
>> ---
>>  drivers/net/ethernet/freescale/fec_main.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> [note: missing changelog?]
> 
>> diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
>> index b87f80d..15a93f90 100644
>> --- a/drivers/net/ethernet/freescale/fec_main.c
>> +++ b/drivers/net/ethernet/freescale/fec_main.c
>> @@ -476,6 +476,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>>  				estatus |= BD_ENET_TX_TS;
>>  		}
>>  	}
>> +	bdp->cbd_bufaddr = addr;
>> +	bdp->cbd_datlen = buflen;
>>  
>>  	if (fep->bufdesc_ex) {
>>  
>> @@ -499,8 +501,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>>  	/* Save skb pointer */
>>  	txq->tx_skbuff[index] = skb;
>>  
>> -	bdp->cbd_datlen = buflen;
>> -	bdp->cbd_bufaddr = addr;
>>  	/* Make sure the updates to rest of the descriptor are performed before
>>  	 * transferring ownership.
>>  	 */
>>
> 
> This patch and others in the series conflicts with the bugfix "net: fec: make
> driver endian-safe" that Johannes sent this week. Can you include his fix
> in your series and ensure that all descriptor accesses are done in
> an endian-safe way?
> 
> 	Arnd

Sure, I'll rebase and send the first few when net-next is updated.

Thanks
Troy

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

* Re: [PATCH net-next 39/40] ARM: dts: imx6qdl-nitrogen6x: add phy interrupt to eliminate polling
  2016-01-28 21:26   ` Troy Kisky
@ 2016-02-01 14:03     ` Shawn Guo
  -1 siblings, 0 replies; 96+ messages in thread
From: Shawn Guo @ 2016-02-01 14:03 UTC (permalink / raw)
  To: Troy Kisky
  Cc: netdev, davem, B38611, fabio.estevam, l.stach, andrew, tremyfr,
	linux, linux-arm-kernel, laci

On Thu, Jan 28, 2016 at 02:26:03PM -0700, Troy Kisky wrote:
> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> ---
>  arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
> index caeed56..1d42331 100644
> --- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
> @@ -288,6 +288,15 @@
>  	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
>  			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
>  	status = "okay";
> +	phy-handle = <&ethphy>;

Have a new line between properties and sub-node.

> +	mdio {
> +		#address-cells = <0>;
> +		#size-cells = <1>;

Ditto

Shawn

> +		ethphy: ethernet-phy@6 {
> +			reg = <6>;
> +			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
> +		};
> +	};
>  };
>  
>  &hdmi {
> @@ -409,6 +418,8 @@
>  				/* Phy reset */
>  				MX6QDL_PAD_ENET_RXD0__GPIO1_IO27	0x000b0
>  				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
> +				/* ethernet phy interrupt */
> +				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x1b0b0
>  			>;
>  		};
>  
> -- 
> 2.5.0
> 
> 

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

* [PATCH net-next 39/40] ARM: dts: imx6qdl-nitrogen6x: add phy interrupt to eliminate polling
@ 2016-02-01 14:03     ` Shawn Guo
  0 siblings, 0 replies; 96+ messages in thread
From: Shawn Guo @ 2016-02-01 14:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 28, 2016 at 02:26:03PM -0700, Troy Kisky wrote:
> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> ---
>  arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
> index caeed56..1d42331 100644
> --- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
> @@ -288,6 +288,15 @@
>  	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
>  			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
>  	status = "okay";
> +	phy-handle = <&ethphy>;

Have a new line between properties and sub-node.

> +	mdio {
> +		#address-cells = <0>;
> +		#size-cells = <1>;

Ditto

Shawn

> +		ethphy: ethernet-phy at 6 {
> +			reg = <6>;
> +			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
> +		};
> +	};
>  };
>  
>  &hdmi {
> @@ -409,6 +418,8 @@
>  				/* Phy reset */
>  				MX6QDL_PAD_ENET_RXD0__GPIO1_IO27	0x000b0
>  				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
> +				/* ethernet phy interrupt */
> +				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x1b0b0
>  			>;
>  		};
>  
> -- 
> 2.5.0
> 
> 

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

* Re: [PATCH net-next 40/40] ARM: dts: imx6qdl-nitrogen6_max: add phy interrupt to eliminate polling
  2016-01-28 21:26   ` Troy Kisky
@ 2016-02-01 14:04     ` Shawn Guo
  -1 siblings, 0 replies; 96+ messages in thread
From: Shawn Guo @ 2016-02-01 14:04 UTC (permalink / raw)
  To: Troy Kisky
  Cc: netdev, davem, B38611, fabio.estevam, l.stach, andrew, tremyfr,
	linux, linux-arm-kernel, laci

On Thu, Jan 28, 2016 at 02:26:04PM -0700, Troy Kisky wrote:
> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> ---
>  arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
> index a35d54f..771f650 100644
> --- a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
> @@ -386,6 +386,15 @@
>  	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
>  			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
>  	status = "okay";
> +	phy-handle = <&ethphy>;

Please keep 'status' at the bottom of the property list.

Shawn

> +	mdio {
> +		#address-cells = <0>;
> +		#size-cells = <1>;
> +		ethphy: ethernet-phy@6 {
> +			reg = <6>;
> +			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
> +		};
> +	};
>  };
>  
>  &hdmi {
> -- 
> 2.5.0
> 
> 

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

* [PATCH net-next 40/40] ARM: dts: imx6qdl-nitrogen6_max: add phy interrupt to eliminate polling
@ 2016-02-01 14:04     ` Shawn Guo
  0 siblings, 0 replies; 96+ messages in thread
From: Shawn Guo @ 2016-02-01 14:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 28, 2016 at 02:26:04PM -0700, Troy Kisky wrote:
> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> ---
>  arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
> index a35d54f..771f650 100644
> --- a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
> @@ -386,6 +386,15 @@
>  	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
>  			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
>  	status = "okay";
> +	phy-handle = <&ethphy>;

Please keep 'status' at the bottom of the property list.

Shawn

> +	mdio {
> +		#address-cells = <0>;
> +		#size-cells = <1>;
> +		ethphy: ethernet-phy at 6 {
> +			reg = <6>;
> +			interrupts-extended = <&gpio1 28 IRQ_TYPE_LEVEL_LOW>;
> +		};
> +	};
>  };
>  
>  &hdmi {
> -- 
> 2.5.0
> 
> 

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

end of thread, other threads:[~2016-02-01 14:04 UTC | newest]

Thread overview: 96+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-28 21:25 [PATCH net-next 00/40] net: fec: cleanup/fixes Troy Kisky
2016-01-28 21:25 ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 01/40] net: fec: stop the "rcv is not +last, " error messages Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 02/40] net: fec: fix rx error counts Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 03/40] net: fec: fix fec_enet_get_free_txdesc_num Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 04/40] net: fec: add struct bufdesc_prop Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 05/40] net: fec: add variable reg_desc_active to speed things up Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 06/40] net: fec: don't disable FEC_ENET_TS_TIMER interrupt Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 07/40] net: fec: don't transfer ownership until descriptor write is complete Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 08/40] net: fec: move cbd_bufaddr assignment closer to the mapping function Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 22:02   ` Arnd Bergmann
2016-01-28 22:02     ` Arnd Bergmann
2016-01-28 22:14     ` Johannes Berg
2016-01-28 22:14       ` Johannes Berg
2016-01-29 17:49     ` Troy Kisky
2016-01-29 17:49       ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 09/40] net: fec: only check queue 0 if RXF_0/TXF_0 interrupt is set Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 10/40] net: fec: pass rxq to fec_enet_rx_queue instead of queue_id Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 11/40] net: fec: pass txq to fec_enet_tx_queue " Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 12/40] net: fec: reduce interrupts Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 13/40] net: fec: split off napi routine with 3 queues Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 14/40] net: fec: don't clear all rx queue bits when just one is being checked Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 15/40] net: fec: set cbd_sc without relying on previous value Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 16/40] net: fec: eliminate calls to fec_enet_get_prevdesc Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 17/40] net: fec: move restart test for efficiency Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 18/40] net: fec: clear cbd_sc after transmission to help with debugging Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 19/40] net: fec: dump all tx queues in fec_dump Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 20/40] net: fec: detect tx int lost Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 21/40] net: fec: print more debug info in fec_timeout Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 22/40] net: fec: call dma_unmap_single on mapped tx buffers at restart Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 23/40] net: fec: don't set cbd_bufaddr unless no mapping error Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 24/40] net: fec: return NETDEV_TX_BUSY, when not enough space in ring Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 25/40] net: fec: don't free skb until it has been unmapped Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 26/40] net: fec: set cbd_esc only once Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 27/40] net: fec: enable interrupt on very last descriptor only Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 28/40] net: fec: unmap initial buffer on error Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 29/40] net: fec: don't free skb when returning busy Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 30/40] net: fec: move last_bdp assignment for symmetry Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 31/40] net: fec: don't transfer ownership until entire tso is queued Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 32/40] net: fec: fix err_release in fec_enet_txq_submit_tso Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 33/40] net: fec: shrink the window for 'tx int lost' Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 34/40] net: fec: update dirty_tx even if no skb Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:25 ` [PATCH net-next 35/40] net: fec: rename dirty_tx to pending_tx Troy Kisky
2016-01-28 21:25   ` Troy Kisky
2016-01-28 21:26 ` [PATCH net-next 36/40] net: fec: use mac set by bootloader before fuses Troy Kisky
2016-01-28 21:26   ` Troy Kisky
2016-01-28 21:26 ` [PATCH net-next 37/40] net: fec: add events device file Troy Kisky
2016-01-28 21:26   ` Troy Kisky
2016-01-28 21:26 ` [PATCH net-next 38/40] net: fec: recover from lost rxf_0 interrupt Troy Kisky
2016-01-28 21:26   ` Troy Kisky
2016-01-28 21:26 ` [PATCH net-next 39/40] ARM: dts: imx6qdl-nitrogen6x: add phy interrupt to eliminate polling Troy Kisky
2016-01-28 21:26   ` Troy Kisky
2016-02-01 14:03   ` Shawn Guo
2016-02-01 14:03     ` Shawn Guo
2016-01-28 21:26 ` [PATCH net-next 40/40] ARM: dts: imx6qdl-nitrogen6_max: " Troy Kisky
2016-01-28 21:26   ` Troy Kisky
2016-02-01 14:04   ` Shawn Guo
2016-02-01 14:04     ` Shawn Guo
2016-01-28 22:39 ` [PATCH net-next 00/40] net: fec: cleanup/fixes David Miller
2016-01-28 22:39   ` David Miller
     [not found]   ` <CAGB=+3Sip-+2Qf-KTZfoCCBcO9=9tb=pVCaEs=+eNJ1sWSRgXw@mail.gmail.com>
2016-01-29  0:19     ` David Miller
2016-01-29  0:19       ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.