summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsave2010-02-25 14:37:46 +0000
committersave2010-02-25 14:37:46 +0000
commit34402f8c28f73a8d3d30d891ae5289b869516199 (patch)
tree672c5857c75c0821ba7ab774de5f34f769d08462
parent024d4d7c4f489c80aae37a5dbb67fd624f0b9b5d (diff)
cleo/linux/eth: Release TX buffers on Xmit procedure, closes #1305
When there isn't any buffer for a transmission, we check if there is some buffers released by the DMA. In this case, we call tx_done procedure that will give it to transmission. This correction will be used if polling is not enough reactive. git-svn-id: svn+ssh://pessac/svn/cesar/trunk@6790 017c9cb6-072f-447c-8318-d5b54f68fe89
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c
index 44ac6a703e..ef39ec59ba 100644
--- a/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c
+++ b/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c
@@ -122,6 +122,15 @@ struct net_priv
struct platform_device *pdev;
};
+/** How many Tx buffers to clean */
+enum tx_clean_buff
+{
+ ONE,
+ ALL
+};
+
+static void synop3504_tx_done(struct net_device *dev, enum tx_clean_buff clean);
+
#ifdef TRACE_FRAME
static const unsigned char __hexdigits[] = "0123456789ABCDEF";
static void sprintf_hex(unsigned char * str, const unsigned char * ptr, int len, unsigned char delim)
@@ -986,7 +995,8 @@ static int synop3504_tx(struct sk_buff *skb, struct net_device *dev)
}
//Check a free descriptor
- if((tx->skbs[n] != NULL) || (tx->ring[n].status.bf.dma_own))
+ //No free buffer found : DMA use all the ring
+ if(tx->ring[n].status.bf.dma_own)
{
netif_stop_queue(dev);
printk(KERN_WARNING DRV_NAME "%s: TX dropped DMA Queue full\n", dev->name);
@@ -994,6 +1004,12 @@ static int synop3504_tx(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb_any(skb);
return 0;
}
+ //No free buffer found but DMA has just finish some previous transfers
+ //so recover these buffers
+ if(tx->skbs[n] != NULL)
+ {
+ synop3504_tx_done(dev, ONE);
+ }
tx->skbs[n] = skb;
@@ -1142,8 +1158,9 @@ reuse_buffer:
/**
* finish the transmit frame procedure.
* \param dev device structure.
+ * \param clean how many buffers to clean.
*/
-static void synop3504_tx_done(struct net_device *dev)
+static void synop3504_tx_done(struct net_device *dev, enum tx_clean_buff clean)
{
struct net_priv *priv = (struct net_priv*)dev->priv;
struct dma_tx *tx = (struct dma_tx*)&priv->tx;
@@ -1198,6 +1215,10 @@ static void synop3504_tx_done(struct net_device *dev)
//Increase tail pointer and check end of ring
if(++(tx->tail_ptr) >= TX_RING_SIZE)
tx->tail_ptr = 0;
+
+ //Called for only one buffer
+ if(clean == ONE)
+ break;
}
}// synop3504_tx_done
@@ -1232,7 +1253,7 @@ static int synop3504_poll(struct napi_struct *napi, int budget)
//TX completed
if(status.bf.intTxCompleted)
{
- synop3504_tx_done(dev);
+ synop3504_tx_done(dev, ALL);
//Check the TX queue and re-enable it
if(netif_queue_stopped(dev))
@@ -1261,7 +1282,7 @@ static int synop3504_poll(struct napi_struct *napi, int budget)
if(status.bf.intTxUnderflow)
{
//Remove old buffers from TX descriptors
- synop3504_tx_done(dev);
+ synop3504_tx_done(dev, ALL);
netif_start_queue(dev);
printk(KERN_ERR DRV_NAME ": %s: TX FIFO Error\n", dev->name);
}