* [PATCH net-next V2 0/8] net: fec: cleanup/fixes
@ 2016-02-05 21:52 Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 1/8] net: fec: stop the "rcv is not +last, " error messages Troy Kisky
` (8 more replies)
0 siblings, 9 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-05 21:52 UTC (permalink / raw)
To: netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd, Troy Kisky
V2 is a rebase on top of johannes endian-safe patch and
is only the 1st eight patches.
The testing for this series was done on a nitrogen6x.
The base commit was
commit b45efa30a626e915192a6c548cd8642379cd47cc
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Testing showed no change in performance.
Testing used imx_v6_v7_defconfig + CONFIG_MICREL_PHY.
The processor was running at 996Mhz.
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 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, and the rest of
my fec patches, for those who would like to test it.
https://github.com:boundarydevices/linux-imx6.git branch net-next_master
Troy Kisky (8):
SDCard
TX/RX
378/405 before any patches
379/407 net: fec: stop the "rcv is not +last, " error messages
378/405 net: fec: fix rx error counts
379/396 net: fec: fix fec_enet_get_free_txdesc_num
379/403 net: fec: add struct bufdesc_prop
390/396 net: fec: add variable reg_desc_active to speed things up
388/396 net: fec: don't disable FEC_ENET_TS_TIMER interrupt
382/403 net: fec: don't transfer ownership until descriptor write is complete
378/403 net: fec: improve error handling
drivers/net/ethernet/freescale/fec.h | 38 ++-
drivers/net/ethernet/freescale/fec_main.c | 396 ++++++++++++++----------------
2 files changed, 196 insertions(+), 238 deletions(-)
--
2.5.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH net-next V2 1/8] net: fec: stop the "rcv is not +last, " error messages
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
@ 2016-02-05 21:52 ` Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 2/8] net: fec: fix rx error counts Troy Kisky
` (7 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-05 21:52 UTC (permalink / raw)
To: netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd, 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 2106d72..cc9677a 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -64,6 +64,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 41c81f6..3e5b24a 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -988,6 +988,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] 14+ messages in thread
* [PATCH net-next V2 2/8] net: fec: fix rx error counts
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 1/8] net: fec: stop the "rcv is not +last, " error messages Troy Kisky
@ 2016-02-05 21:52 ` Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 3/8] net: fec: fix fec_enet_get_free_txdesc_num Troy Kisky
` (6 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-05 21:52 UTC (permalink / raw)
To: netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd, Troy Kisky
On an overrun, the other flags are not
valid, so don't check them.
Also, don't pass bad frames up the stack.
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 3e5b24a..162fa59 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1408,37 +1408,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] 14+ messages in thread
* [PATCH net-next V2 3/8] net: fec: fix fec_enet_get_free_txdesc_num
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 1/8] net: fec: stop the "rcv is not +last, " error messages Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 2/8] net: fec: fix rx error counts Troy Kisky
@ 2016-02-05 21:52 ` Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 4/8] net: fec: add struct bufdesc_prop Troy Kisky
` (5 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-05 21:52 UTC (permalink / raw)
To: netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd, Troy Kisky
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 162fa59..adbddfd 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] 14+ messages in thread
* [PATCH net-next V2 4/8] net: fec: add struct bufdesc_prop
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
` (2 preceding siblings ...)
2016-02-05 21:52 ` [PATCH net-next V2 3/8] net: fec: fix fec_enet_get_free_txdesc_num Troy Kisky
@ 2016-02-05 21:52 ` Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 5/8] net: fec: add variable reg_desc_active to speed things up Troy Kisky
` (4 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-05 21:52 UTC (permalink / raw)
To: netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd, 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 cc9677a..53ec04f 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -448,33 +448,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
@@ -514,8 +515,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 adbddfd..b039288 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,20 +281,20 @@ 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%08x %4u %p\n",
index,
- bdp == txq->cur_tx ? 'S' : ' ',
+ bdp == txq->bd.cur ? 'S' : ' ',
bdp == txq->dirty_tx ? 'H' : ' ',
fec16_to_cpu(bdp->cbd_sc),
fec32_to_cpu(bdp->cbd_bufaddr),
fec16_to_cpu(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)
@@ -373,7 +325,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);
@@ -388,7 +340,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 = fec16_to_cpu(bdp->cbd_sc);
@@ -418,7 +370,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);
@@ -444,9 +396,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, fec32_to_cpu(bdp->cbd_bufaddr),
fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE);
}
@@ -468,7 +420,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())
@@ -483,7 +435,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 = fec16_to_cpu(bdp->cbd_sc);
status &= ~BD_ENET_TX_STATS;
@@ -493,7 +445,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);
@@ -544,7 +496,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
ebdp->cbd_esc = cpu_to_fec32(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;
@@ -558,15 +510,15 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
bdp->cbd_sc = cpu_to_fec16(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));
@@ -697,13 +649,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");
@@ -723,7 +675,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;
@@ -738,9 +690,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,
@@ -753,14 +704,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) ||
@@ -798,7 +749,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);
@@ -819,32 +770,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 = cpu_to_fec16(BD_ENET_RX_EMPTY);
else
bdp->cbd_sc = cpu_to_fec16(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 |= cpu_to_fec16(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 = cpu_to_fec16(0);
if (txq->tx_skbuff[i]) {
@@ -852,11 +803,11 @@ static void fec_enet_bd_init(struct net_device *dev)
txq->tx_skbuff[i] = NULL;
}
bdp->cbd_bufaddr = cpu_to_fec32(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 |= cpu_to_fec16(BD_SC_WRAP);
txq->dirty_tx = bdp;
}
@@ -880,7 +831,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 */
@@ -891,7 +842,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)
@@ -909,7 +860,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;
@@ -1222,16 +1173,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 = fec16_to_cpu(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;
@@ -1242,7 +1193,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
DMA_TO_DEVICE);
bdp->cbd_bufaddr = cpu_to_fec32(0);
if (!skb) {
- bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
continue;
}
@@ -1291,19 +1242,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));
}
@@ -1367,7 +1318,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.
@@ -1400,7 +1351,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 = fec16_to_cpu(bdp->cbd_sc)) & BD_ENET_RX_EMPTY)) {
@@ -1441,7 +1392,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
pkt_len = fec16_to_cpu(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
@@ -1541,7 +1492,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
@@ -1549,7 +1500,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;
}
@@ -2658,8 +2609,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) {
@@ -2669,14 +2620,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];
@@ -2696,7 +2647,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);
}
@@ -2722,15 +2673,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) {
@@ -2747,8 +2698,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;
@@ -2767,8 +2718,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;
@@ -2786,11 +2737,11 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
ebdp->cbd_esc = cpu_to_fec32(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 |= cpu_to_fec16(BD_SC_WRAP);
return 0;
@@ -2808,8 +2759,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;
@@ -2822,11 +2773,11 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
ebdp->cbd_esc = cpu_to_fec32(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 |= cpu_to_fec16(BD_SC_WRAP);
return 0;
@@ -3117,13 +3068,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;
@@ -3134,12 +3087,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,
@@ -3157,33 +3105,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] 14+ messages in thread
* [PATCH net-next V2 5/8] net: fec: add variable reg_desc_active to speed things up
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
` (3 preceding siblings ...)
2016-02-05 21:52 ` [PATCH net-next V2 4/8] net: fec: add struct bufdesc_prop Troy Kisky
@ 2016-02-05 21:52 ` Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 6/8] net: fec: don't disable FEC_ENET_TS_TIMER interrupt Troy Kisky
` (3 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-05 21:52 UTC (permalink / raw)
To: netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd, 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 53ec04f..bedd28a 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -310,12 +310,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)
@@ -454,6 +448,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 b039288..712e3bb 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -328,7 +328,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;
@@ -361,7 +360,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;
@@ -415,7 +414,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;
@@ -444,7 +442,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) {
@@ -487,7 +484,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;
@@ -521,7 +518,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;
}
@@ -534,7 +531,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;
@@ -566,7 +562,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;
@@ -595,7 +591,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;
@@ -630,7 +625,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;
@@ -650,7 +645,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;
@@ -715,11 +709,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;
@@ -819,7 +813,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)
@@ -1255,8 +1249,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
@@ -1498,7 +1492,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;
@@ -3061,6 +3055,14 @@ static const struct net_device_ops fec_netdev_ops = {
.ndo_set_features = fec_set_features,
};
+static const unsigned short offset_des_active_rxq[] = {
+ FEC_R_DES_ACTIVE_0, FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2
+};
+
+static 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.
*
@@ -3114,6 +3116,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);
@@ -3129,6 +3132,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] 14+ messages in thread
* [PATCH net-next V2 6/8] net: fec: don't disable FEC_ENET_TS_TIMER interrupt
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
` (4 preceding siblings ...)
2016-02-05 21:52 ` [PATCH net-next V2 5/8] net: fec: add variable reg_desc_active to speed things up Troy Kisky
@ 2016-02-05 21:52 ` Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete Troy Kisky
` (2 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-05 21:52 UTC (permalink / raw)
To: netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd, 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 bedd28a..195122e 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -375,6 +375,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 712e3bb..ca2708d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1553,7 +1553,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] 14+ messages in thread
* [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
` (5 preceding siblings ...)
2016-02-05 21:52 ` [PATCH net-next V2 6/8] net: fec: don't disable FEC_ENET_TS_TIMER interrupt Troy Kisky
@ 2016-02-05 21:52 ` Troy Kisky
2016-02-06 1:03 ` Joshua Clayton
2016-02-06 11:52 ` Sergei Shtylyov
2016-02-05 21:52 ` [PATCH net-next V2 8/8] net: fec: improve error handling Troy Kisky
2016-02-11 11:15 ` [PATCH net-next V2 0/8] net: fec: cleanup/fixes David Miller
8 siblings, 2 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-05 21:52 UTC (permalink / raw)
To: netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd, Troy Kisky
If you don't own it, you shouldn't write to it.
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 ca2708d..97ca72a 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -390,6 +390,10 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
bdp->cbd_bufaddr = cpu_to_fec32(addr);
bdp->cbd_datlen = cpu_to_fec16(frag_len);
+ /* Make sure the updates to rest of the descriptor are
+ * performed before transferring ownership.
+ */
+ wmb();
bdp->cbd_sc = cpu_to_fec16(status);
}
@@ -499,6 +503,10 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
bdp->cbd_datlen = cpu_to_fec16(buflen);
bdp->cbd_bufaddr = cpu_to_fec32(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.
@@ -1475,7 +1483,6 @@ rx_processing_done:
/* Mark the buffer empty */
status |= BD_ENET_RX_EMPTY;
- bdp->cbd_sc = cpu_to_fec16(status);
if (fep->bufdesc_ex) {
struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
@@ -1484,6 +1491,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 = cpu_to_fec16(status);
/* Update BD pointer to next entry */
bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
--
2.5.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH net-next V2 8/8] net: fec: improve error handling
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
` (6 preceding siblings ...)
2016-02-05 21:52 ` [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete Troy Kisky
@ 2016-02-05 21:52 ` Troy Kisky
2016-02-11 11:15 ` [PATCH net-next V2 0/8] net: fec: cleanup/fixes David Miller
8 siblings, 0 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-05 21:52 UTC (permalink / raw)
To: netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd, Troy Kisky
Unmap initial buffer on error.
Don't free skb until it has been unmapped.
Move cbd_bufaddr assignment closer to the mapping function.
Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
drivers/net/ethernet/freescale/fec_main.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 97ca72a..ef18ca5 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -382,7 +382,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;
@@ -467,8 +466,12 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
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) {
@@ -478,6 +481,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
estatus |= BD_ENET_TX_TS;
}
}
+ bdp->cbd_bufaddr = cpu_to_fec32(addr);
+ bdp->cbd_datlen = cpu_to_fec16(buflen);
if (fep->bufdesc_ex) {
@@ -501,8 +506,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 = cpu_to_fec16(buflen);
- bdp->cbd_bufaddr = cpu_to_fec32(addr);
/* Make sure the updates to rest of the descriptor are performed before
* transferring ownership.
*/
--
2.5.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete
2016-02-05 21:52 ` [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete Troy Kisky
@ 2016-02-06 1:03 ` Joshua Clayton
2016-02-24 20:38 ` Troy Kisky
2016-02-06 11:52 ` Sergei Shtylyov
1 sibling, 1 reply; 14+ messages in thread
From: Joshua Clayton @ 2016-02-06 1:03 UTC (permalink / raw)
To: Troy Kisky
Cc: netdev, davem, B38611, fabio.estevam, andrew, linux, arnd, laci,
johannes, l.stach, shawnguo, linux-arm-kernel, tremyfr
On Fri, 5 Feb 2016 14:52:49 -0700
Troy Kisky <troy.kisky@boundarydevices.com> wrote:
> If you don't own it, you shouldn't write to it.
>
> 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 ca2708d..97ca72a
> 100644 --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -390,6 +390,10 @@ fec_enet_txq_submit_frag_skb(struct
> fec_enet_priv_tx_q *txq,
> bdp->cbd_bufaddr = cpu_to_fec32(addr);
> bdp->cbd_datlen = cpu_to_fec16(frag_len);
> + /* Make sure the updates to rest of the descriptor
> are
> + * performed before transferring ownership.
> + */
> + wmb();
> bdp->cbd_sc = cpu_to_fec16(status);
You use almost exactly the same code in each place.
I'd prefer to have wmb(); bdp->cbd_sc = cpu_to_fec16(status) wrapped in
a function or function like macro, and put the comment in one place.
e.g.
/* Make sure the updates to rest of the descriptor
* performed before transferring ownership.
*/
#define fec_enet_xfr_ownership(status) \
do { \
wmb();
bdp->cbd_sc = cpu_to_fec16(status);
} while (0)
(I don't know if thats the right macro name, I'm just basing it off
your comment)
> }
>
> @@ -499,6 +503,10 @@ static int fec_enet_txq_submit_skb(struct
> fec_enet_priv_tx_q *txq,
> bdp->cbd_datlen = cpu_to_fec16(buflen);
> bdp->cbd_bufaddr = cpu_to_fec32(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. @@ -1475,7 +1483,6 @@ rx_processing_done:
>
> /* Mark the buffer empty */
> status |= BD_ENET_RX_EMPTY;
> - bdp->cbd_sc = cpu_to_fec16(status);
>
> if (fep->bufdesc_ex) {
> struct bufdesc_ex *ebdp = (struct bufdesc_ex
> *)bdp; @@ -1484,6 +1491,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 = cpu_to_fec16(status);
>
> /* Update BD pointer to next entry */
> bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete
2016-02-05 21:52 ` [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete Troy Kisky
2016-02-06 1:03 ` Joshua Clayton
@ 2016-02-06 11:52 ` Sergei Shtylyov
2016-02-24 20:39 ` Troy Kisky
1 sibling, 1 reply; 14+ messages in thread
From: Sergei Shtylyov @ 2016-02-06 11:52 UTC (permalink / raw)
To: Troy Kisky, netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd
Hello.
On 2/6/2016 12:52 AM, Troy Kisky wrote:
> If you don't own it, you shouldn't write to it.
>
> 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 ca2708d..97ca72a 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -390,6 +390,10 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
>
> bdp->cbd_bufaddr = cpu_to_fec32(addr);
> bdp->cbd_datlen = cpu_to_fec16(frag_len);
> + /* Make sure the updates to rest of the descriptor are
> + * performed before transferring ownership.
> + */
> + wmb();
> bdp->cbd_sc = cpu_to_fec16(status);
> }
>
> @@ -499,6 +503,10 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>
> bdp->cbd_datlen = cpu_to_fec16(buflen);
> bdp->cbd_bufaddr = cpu_to_fec32(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.
[...]
> @@ -1484,6 +1491,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 = cpu_to_fec16(status);
I think you can use "ligter" dma_wmb() in this case.
[...]
MBR, Sergei
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net-next V2 0/8] net: fec: cleanup/fixes
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
` (7 preceding siblings ...)
2016-02-05 21:52 ` [PATCH net-next V2 8/8] net: fec: improve error handling Troy Kisky
@ 2016-02-11 11:15 ` David Miller
8 siblings, 0 replies; 14+ messages in thread
From: David Miller @ 2016-02-11 11:15 UTC (permalink / raw)
To: troy.kisky
Cc: netdev, B38611, fabio.estevam, l.stach, andrew, tremyfr, linux,
linux-arm-kernel, laci, shawnguo, johannes, arnd
From: Troy Kisky <troy.kisky@boundarydevices.com>
Date: Fri, 5 Feb 2016 14:52:42 -0700
>
> V2 is a rebase on top of johannes endian-safe patch and
> is only the 1st eight patches.
> The testing for this series was done on a nitrogen6x.
> The base commit was
> commit b45efa30a626e915192a6c548cd8642379cd47cc
> Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
>
> Testing showed no change in performance.
> Testing used imx_v6_v7_defconfig + CONFIG_MICREL_PHY.
> The processor was running at 996Mhz.
> 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 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, and the rest of
> my fec patches, for those who would like to test it.
> https://github.com:boundarydevices/linux-imx6.git branch net-next_master
Series applied, thanks.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete
2016-02-06 1:03 ` Joshua Clayton
@ 2016-02-24 20:38 ` Troy Kisky
0 siblings, 0 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-24 20:38 UTC (permalink / raw)
To: Joshua Clayton
Cc: netdev, davem, B38611, fabio.estevam, andrew, linux, arnd, laci,
johannes, l.stach, shawnguo, linux-arm-kernel, tremyfr
On 2/5/2016 6:03 PM, Joshua Clayton wrote:
> On Fri, 5 Feb 2016 14:52:49 -0700
> Troy Kisky <troy.kisky@boundarydevices.com> wrote:
>
>> If you don't own it, you shouldn't write to it.
>>
>> 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 ca2708d..97ca72a
>> 100644 --- a/drivers/net/ethernet/freescale/fec_main.c
>> +++ b/drivers/net/ethernet/freescale/fec_main.c
>> @@ -390,6 +390,10 @@ fec_enet_txq_submit_frag_skb(struct
>> fec_enet_priv_tx_q *txq,
>> bdp->cbd_bufaddr = cpu_to_fec32(addr);
>> bdp->cbd_datlen = cpu_to_fec16(frag_len);
>> + /* Make sure the updates to rest of the descriptor
>> are
>> + * performed before transferring ownership.
>> + */
>> + wmb();
>> bdp->cbd_sc = cpu_to_fec16(status);
> You use almost exactly the same code in each place.
> I'd prefer to have wmb(); bdp->cbd_sc = cpu_to_fec16(status) wrapped in
> a function or function like macro, and put the comment in one place.
>
Thanks for the review. I added a patch to the end of the series to create a common
"trigger_tx" subroutine which should address this.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete
2016-02-06 11:52 ` Sergei Shtylyov
@ 2016-02-24 20:39 ` Troy Kisky
0 siblings, 0 replies; 14+ messages in thread
From: Troy Kisky @ 2016-02-24 20:39 UTC (permalink / raw)
To: Sergei Shtylyov, netdev, davem, B38611
Cc: fabio.estevam, l.stach, andrew, tremyfr, linux, linux-arm-kernel,
laci, shawnguo, johannes, arnd
On 2/6/2016 4:52 AM, Sergei Shtylyov wrote:
> Hello.
>
> On 2/6/2016 12:52 AM, Troy Kisky wrote:
>
>> If you don't own it, you shouldn't write to it.
>>
>> 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 ca2708d..97ca72a 100644
>> --- a/drivers/net/ethernet/freescale/fec_main.c
>> +++ b/drivers/net/ethernet/freescale/fec_main.c
>> @@ -390,6 +390,10 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
>>
>> bdp->cbd_bufaddr = cpu_to_fec32(addr);
>> bdp->cbd_datlen = cpu_to_fec16(frag_len);
>> + /* Make sure the updates to rest of the descriptor are
>> + * performed before transferring ownership.
>> + */
>> + wmb();
>> bdp->cbd_sc = cpu_to_fec16(status);
>> }
>>
>> @@ -499,6 +503,10 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
>>
>> bdp->cbd_datlen = cpu_to_fec16(buflen);
>> bdp->cbd_bufaddr = cpu_to_fec32(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.
> [...]
>> @@ -1484,6 +1491,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 = cpu_to_fec16(status);
>
> I think you can use "ligter" dma_wmb() in this case.
>
Thanks for the review, I added a patch to the end of the series to address this.
Troy
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2016-02-24 20:39 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-05 21:52 [PATCH net-next V2 0/8] net: fec: cleanup/fixes Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 1/8] net: fec: stop the "rcv is not +last, " error messages Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 2/8] net: fec: fix rx error counts Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 3/8] net: fec: fix fec_enet_get_free_txdesc_num Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 4/8] net: fec: add struct bufdesc_prop Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 5/8] net: fec: add variable reg_desc_active to speed things up Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 6/8] net: fec: don't disable FEC_ENET_TS_TIMER interrupt Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 7/8] net: fec: don't transfer ownership until descriptor write is complete Troy Kisky
2016-02-06 1:03 ` Joshua Clayton
2016-02-24 20:38 ` Troy Kisky
2016-02-06 11:52 ` Sergei Shtylyov
2016-02-24 20:39 ` Troy Kisky
2016-02-05 21:52 ` [PATCH net-next V2 8/8] net: fec: improve error handling Troy Kisky
2016-02-11 11:15 ` [PATCH net-next V2 0/8] net: fec: cleanup/fixes David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).