stmmac: optimize tx clean function
This patch "inline" get_tx_owner and get_ls routines. It Results in a unique read to tdes0, instead of three, to check TX_OWN and LS bits, and other status bits. It helps improve driver TX path by removing two uncached read/writes inside TX clean loop for enhanced descriptors but not for normal ones because the des1 must be read in any case. Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com> Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
be434d5075
commit
c363b6586c
@ -245,6 +245,14 @@ enum rx_frame_status {
|
|||||||
dma_own = 0x8,
|
dma_own = 0x8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Tx status */
|
||||||
|
enum tx_frame_status {
|
||||||
|
tx_done = 0x0,
|
||||||
|
tx_not_ls = 0x1,
|
||||||
|
tx_err = 0x2,
|
||||||
|
tx_dma_own = 0x4,
|
||||||
|
};
|
||||||
|
|
||||||
enum dma_irq_status {
|
enum dma_irq_status {
|
||||||
tx_hard_error = 0x1,
|
tx_hard_error = 0x1,
|
||||||
tx_hard_error_bump_tc = 0x2,
|
tx_hard_error_bump_tc = 0x2,
|
||||||
|
@ -31,7 +31,15 @@ static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
|
|||||||
{
|
{
|
||||||
struct net_device_stats *stats = (struct net_device_stats *)data;
|
struct net_device_stats *stats = (struct net_device_stats *)data;
|
||||||
unsigned int tdes0 = p->des0;
|
unsigned int tdes0 = p->des0;
|
||||||
int ret = 0;
|
int ret = tx_done;
|
||||||
|
|
||||||
|
/* Get tx owner first */
|
||||||
|
if (unlikely(tdes0 & ETDES0_OWN))
|
||||||
|
return tx_dma_own;
|
||||||
|
|
||||||
|
/* Verify tx error by looking at the last segment. */
|
||||||
|
if (likely(!(tdes0 & ETDES0_LAST_SEGMENT)))
|
||||||
|
return tx_not_ls;
|
||||||
|
|
||||||
if (unlikely(tdes0 & ETDES0_ERROR_SUMMARY)) {
|
if (unlikely(tdes0 & ETDES0_ERROR_SUMMARY)) {
|
||||||
if (unlikely(tdes0 & ETDES0_JABBER_TIMEOUT))
|
if (unlikely(tdes0 & ETDES0_JABBER_TIMEOUT))
|
||||||
@ -71,7 +79,7 @@ static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
|
|||||||
dwmac_dma_flush_tx_fifo(ioaddr);
|
dwmac_dma_flush_tx_fifo(ioaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = -1;
|
ret = tx_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(tdes0 & ETDES0_DEFERRED))
|
if (unlikely(tdes0 & ETDES0_DEFERRED))
|
||||||
|
@ -31,7 +31,16 @@ static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
|
|||||||
{
|
{
|
||||||
struct net_device_stats *stats = (struct net_device_stats *)data;
|
struct net_device_stats *stats = (struct net_device_stats *)data;
|
||||||
unsigned int tdes0 = p->des0;
|
unsigned int tdes0 = p->des0;
|
||||||
int ret = 0;
|
unsigned int tdes1 = p->des1;
|
||||||
|
int ret = tx_done;
|
||||||
|
|
||||||
|
/* Get tx owner first */
|
||||||
|
if (unlikely(tdes0 & TDES0_OWN))
|
||||||
|
return tx_dma_own;
|
||||||
|
|
||||||
|
/* Verify tx error by looking at the last segment. */
|
||||||
|
if (likely(!(tdes1 & TDES1_LAST_SEGMENT)))
|
||||||
|
return tx_not_ls;
|
||||||
|
|
||||||
if (unlikely(tdes0 & TDES0_ERROR_SUMMARY)) {
|
if (unlikely(tdes0 & TDES0_ERROR_SUMMARY)) {
|
||||||
if (unlikely(tdes0 & TDES0_UNDERFLOW_ERROR)) {
|
if (unlikely(tdes0 & TDES0_UNDERFLOW_ERROR)) {
|
||||||
@ -54,7 +63,7 @@ static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
|
|||||||
collisions = (tdes0 & TDES0_COLLISION_COUNT_MASK) >> 3;
|
collisions = (tdes0 & TDES0_COLLISION_COUNT_MASK) >> 3;
|
||||||
stats->collisions += collisions;
|
stats->collisions += collisions;
|
||||||
}
|
}
|
||||||
ret = -1;
|
ret = tx_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tdes0 & TDES0_VLAN_FRAME)
|
if (tdes0 & TDES0_VLAN_FRAME)
|
||||||
|
@ -1313,32 +1313,31 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
|
|||||||
priv->xstats.tx_clean++;
|
priv->xstats.tx_clean++;
|
||||||
|
|
||||||
while (entry != priv->cur_tx) {
|
while (entry != priv->cur_tx) {
|
||||||
int last;
|
|
||||||
struct sk_buff *skb = priv->tx_skbuff[entry];
|
struct sk_buff *skb = priv->tx_skbuff[entry];
|
||||||
struct dma_desc *p;
|
struct dma_desc *p;
|
||||||
|
int status;
|
||||||
|
|
||||||
if (priv->extend_desc)
|
if (priv->extend_desc)
|
||||||
p = (struct dma_desc *)(priv->dma_etx + entry);
|
p = (struct dma_desc *)(priv->dma_etx + entry);
|
||||||
else
|
else
|
||||||
p = priv->dma_tx + entry;
|
p = priv->dma_tx + entry;
|
||||||
|
|
||||||
/* Check if the descriptor is owned by the DMA. */
|
status = priv->hw->desc->tx_status(&priv->dev->stats,
|
||||||
if (priv->hw->desc->get_tx_owner(p))
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Verify tx error by looking at the last segment. */
|
|
||||||
last = priv->tx_skbuff_dma[entry].last_segment;
|
|
||||||
if (likely(last)) {
|
|
||||||
int tx_error =
|
|
||||||
priv->hw->desc->tx_status(&priv->dev->stats,
|
|
||||||
&priv->xstats, p,
|
&priv->xstats, p,
|
||||||
priv->ioaddr);
|
priv->ioaddr);
|
||||||
if (likely(tx_error == 0)) {
|
/* Check if the descriptor is owned by the DMA */
|
||||||
|
if (unlikely(status & tx_dma_own))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Just consider the last segment and ...*/
|
||||||
|
if (likely(!(status & tx_not_ls))) {
|
||||||
|
/* ... verify the status error condition */
|
||||||
|
if (unlikely(status & tx_err)) {
|
||||||
|
priv->dev->stats.tx_errors++;
|
||||||
|
} else {
|
||||||
priv->dev->stats.tx_packets++;
|
priv->dev->stats.tx_packets++;
|
||||||
priv->xstats.tx_pkt_n++;
|
priv->xstats.tx_pkt_n++;
|
||||||
} else
|
}
|
||||||
priv->dev->stats.tx_errors++;
|
|
||||||
|
|
||||||
stmmac_get_tx_hwtstamp(priv, entry, skb);
|
stmmac_get_tx_hwtstamp(priv, entry, skb);
|
||||||
}
|
}
|
||||||
if (netif_msg_tx_done(priv))
|
if (netif_msg_tx_done(priv))
|
||||||
|
Loading…
Reference in New Issue
Block a user