summaryrefslogtreecommitdiff
path: root/cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c
diff options
context:
space:
mode:
Diffstat (limited to 'cleopatre/linux-2.6.25.10-spc300/drivers/net/arm/synop3504.c')
-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);
}