Commit e9b1f1cc authored by Jochen Friedrich's avatar Jochen Friedrich Committed by Jeff Garzik

[PATCH] tms380tr patch 2/3 (queue fix)

Hi Jeff,

this one removes the internal queue of tms380tr. It was racy, anyways.

--jochen

 tms380tr.c |  178 +++++++++++++++++++++++--------------------------------------
 tms380tr.h |    4 -
 2 files changed, 70 insertions(+), 112 deletions(-)
parent c44253ad
...@@ -143,8 +143,8 @@ static void tms380tr_exec_sifcmd(struct net_device *dev, unsigned int WriteValu ...@@ -143,8 +143,8 @@ static void tms380tr_exec_sifcmd(struct net_device *dev, unsigned int WriteValu
/* "G" */ /* "G" */
static struct net_device_stats *tms380tr_get_stats(struct net_device *dev); static struct net_device_stats *tms380tr_get_stats(struct net_device *dev);
/* "H" */ /* "H" */
static void tms380tr_hardware_send_packet(struct net_device *dev, static int tms380tr_hardware_send_packet(struct sk_buff *skb,
struct net_local* tp); struct net_device *dev);
/* "I" */ /* "I" */
static int tms380tr_init_adapter(struct net_device *dev); static int tms380tr_init_adapter(struct net_device *dev);
static void tms380tr_init_ipb(struct net_local *tp); static void tms380tr_init_ipb(struct net_local *tp);
...@@ -388,9 +388,6 @@ static void tms380tr_init_net_local(struct net_device *dev) ...@@ -388,9 +388,6 @@ static void tms380tr_init_net_local(struct net_device *dev)
tp->LastOpenStatus = 0; tp->LastOpenStatus = 0;
tp->MaxPacketSize = DEFAULT_PACKET_SIZE; tp->MaxPacketSize = DEFAULT_PACKET_SIZE;
skb_queue_head_init(&tp->SendSkbQueue);
tp->QueueSkb = MAX_TX_QUEUE;
/* Create circular chain of transmit lists */ /* Create circular chain of transmit lists */
for (i = 0; i < TPL_NUM; i++) for (i = 0; i < TPL_NUM; i++)
{ {
...@@ -598,111 +595,87 @@ static void tms380tr_timeout(struct net_device *dev) ...@@ -598,111 +595,87 @@ static void tms380tr_timeout(struct net_device *dev)
static int tms380tr_send_packet(struct sk_buff *skb, struct net_device *dev) static int tms380tr_send_packet(struct sk_buff *skb, struct net_device *dev)
{ {
struct net_local *tp = (struct net_local *)dev->priv; struct net_local *tp = (struct net_local *)dev->priv;
int err;
/* err = tms380tr_hardware_send_packet(skb, dev);
* Block transmits from overlapping. if(tp->TplFree->NextTPLPtr->BusyFlag)
*/ netif_stop_queue(dev);
return (err);
netif_stop_queue(dev);
if(tp->QueueSkb == 0)
return (1); /* Return with tbusy set: queue full */
tp->QueueSkb--;
skb_queue_tail(&tp->SendSkbQueue, skb);
tms380tr_hardware_send_packet(dev, tp);
if(tp->QueueSkb > 0)
netif_wake_queue(dev);
return (0);
} }
/* /*
* Move frames from internal skb queue into adapter tx queue * Move frames into adapter tx queue
*/ */
static void tms380tr_hardware_send_packet(struct net_device *dev, struct net_local* tp) static int tms380tr_hardware_send_packet(struct sk_buff *skb, struct net_device *dev)
{ {
TPL *tpl; TPL *tpl;
short length; short length;
unsigned char *buf; unsigned char *buf;
unsigned long flags; unsigned long flags;
struct sk_buff *skb;
int i; int i;
dma_addr_t dmabuf, newbuf; dma_addr_t dmabuf, newbuf;
struct net_local *tp = (struct net_local *)dev->priv;
for(;;) /* Try to get a free TPL from the chain.
{ *
/* Try to get a free TPL from the chain. * NOTE: We *must* always leave one unused TPL in the chain,
* * because otherwise the adapter might send frames twice.
* NOTE: We *must* always leave one unused TPL in the chain, */
* because otherwise the adapter might send frames twice. spin_lock_irqsave(&tp->lock, flags);
*/ if(tp->TplFree->NextTPLPtr->BusyFlag) { /* No free TPL */
spin_lock_irqsave(&tp->lock, flags); if (tms380tr_debug > 0)
if(tp->TplFree->NextTPLPtr->BusyFlag) /* No free TPL */ printk(KERN_DEBUG "%s: No free TPL\n", dev->name);
{ spin_unlock_irqrestore(&tp->lock, flags);
if (tms380tr_debug > 0) return 1;
printk(KERN_DEBUG "%s: No free TPL\n", dev->name); }
spin_unlock_irqrestore(&tp->lock, flags);
return;
}
/* Send first buffer from queue */ dmabuf = 0;
skb = skb_dequeue(&tp->SendSkbQueue);
if(skb == NULL)
{
spin_unlock_irqrestore(&tp->lock, flags);
return;
}
tp->QueueSkb++;
dmabuf = 0;
/* Is buffer reachable for Busmaster-DMA? */ /* Is buffer reachable for Busmaster-DMA? */
length = skb->len; length = skb->len;
dmabuf = pci_map_single(tp->pdev, skb->data, length, PCI_DMA_TODEVICE); dmabuf = pci_map_single(tp->pdev, skb->data, length, PCI_DMA_TODEVICE);
if(tp->dmalimit && (dmabuf + length > tp->dmalimit)) if(tp->dmalimit && (dmabuf + length > tp->dmalimit)) {
{ /* Copy frame to local buffer */
/* Copy frame to local buffer */ pci_unmap_single(tp->pdev, dmabuf, length, PCI_DMA_TODEVICE);
pci_unmap_single(tp->pdev, dmabuf, length, PCI_DMA_TODEVICE); dmabuf = 0;
dmabuf = 0; i = tp->TplFree->TPLIndex;
i = tp->TplFree->TPLIndex; buf = tp->LocalTxBuffers[i];
buf = tp->LocalTxBuffers[i]; memcpy(buf, skb->data, length);
memcpy(buf, skb->data, length); newbuf = ((char *)buf - (char *)tp) + tp->dmabuffer;
newbuf = ((char *)buf - (char *)tp) + tp->dmabuffer; }
} else {
else /* Send direct from skb->data */
{ newbuf = dmabuf;
/* Send direct from skb->data */ buf = skb->data;
newbuf = dmabuf;
buf = skb->data;
}
/* Source address in packet? */
tms380tr_chk_src_addr(buf, dev->dev_addr);
tp->LastSendTime = jiffies;
tpl = tp->TplFree; /* Get the "free" TPL */
tpl->BusyFlag = 1; /* Mark TPL as busy */
tp->TplFree = tpl->NextTPLPtr;
/* Save the skb for delayed return of skb to system */
tpl->Skb = skb;
tpl->DMABuff = dmabuf;
tpl->FragList[0].DataCount = cpu_to_be16((unsigned short)length);
tpl->FragList[0].DataAddr = htonl(newbuf);
/* Write the data length in the transmit list. */
tpl->FrameSize = cpu_to_be16((unsigned short)length);
tpl->MData = buf;
/* Transmit the frame and set the status values. */
tms380tr_write_tpl_status(tpl, TX_VALID | TX_START_FRAME
| TX_END_FRAME | TX_PASS_SRC_ADDR
| TX_FRAME_IRQ);
/* Let adapter send the frame. */
tms380tr_exec_sifcmd(dev, CMD_TX_VALID);
spin_unlock_irqrestore(&tp->lock, flags);
} }
/* Source address in packet? */
tms380tr_chk_src_addr(buf, dev->dev_addr);
tp->LastSendTime = jiffies;
tpl = tp->TplFree; /* Get the "free" TPL */
tpl->BusyFlag = 1; /* Mark TPL as busy */
tp->TplFree = tpl->NextTPLPtr;
/* Save the skb for delayed return of skb to system */
tpl->Skb = skb;
tpl->DMABuff = dmabuf;
tpl->FragList[0].DataCount = cpu_to_be16((unsigned short)length);
tpl->FragList[0].DataAddr = htonl(newbuf);
return; /* Write the data length in the transmit list. */
tpl->FrameSize = cpu_to_be16((unsigned short)length);
tpl->MData = buf;
/* Transmit the frame and set the status values. */
tms380tr_write_tpl_status(tpl, TX_VALID | TX_START_FRAME
| TX_END_FRAME | TX_PASS_SRC_ADDR
| TX_FRAME_IRQ);
/* Let adapter send the frame. */
tms380tr_exec_sifcmd(dev, CMD_TX_VALID);
spin_unlock_irqrestore(&tp->lock, flags);
return 0;
} }
/* /*
...@@ -747,7 +720,7 @@ static void tms380tr_timer_chk(unsigned long data) ...@@ -747,7 +720,7 @@ static void tms380tr_timer_chk(unsigned long data)
tms380tr_chk_outstanding_cmds(dev); tms380tr_chk_outstanding_cmds(dev);
if(time_before(tp->LastSendTime + SEND_TIMEOUT, jiffies) if(time_before(tp->LastSendTime + SEND_TIMEOUT, jiffies)
&& (tp->QueueSkb < MAX_TX_QUEUE || tp->TplFree != tp->TplBusy)) && (tp->TplFree != tp->TplBusy))
{ {
/* Anything to send, but stalled too long */ /* Anything to send, but stalled too long */
tp->LastSendTime = jiffies; tp->LastSendTime = jiffies;
...@@ -1769,8 +1742,8 @@ static void tms380tr_ring_status_irq(struct net_device *dev) ...@@ -1769,8 +1742,8 @@ static void tms380tr_ring_status_irq(struct net_device *dev)
if(tp->ssb.Parm[0] & ADAPTER_CLOSED) if(tp->ssb.Parm[0] & ADAPTER_CLOSED)
{ {
printk(KERN_INFO "%s: Adapter closed (Reopening)," printk(KERN_INFO "%s: Adapter closed (Reopening),"
"QueueSkb %d, CurrentRingStat %x\n", "CurrentRingStat %x\n",
dev->name, tp->QueueSkb, tp->CurrentRingStatus); dev->name, tp->CurrentRingStatus);
tp->AdapterOpenFlag = 0; tp->AdapterOpenFlag = 0;
tms380tr_open_adapter(dev); tms380tr_open_adapter(dev);
} }
...@@ -1998,7 +1971,6 @@ static void tms380tr_read_ram(struct net_device *dev, unsigned char *Data, ...@@ -1998,7 +1971,6 @@ static void tms380tr_read_ram(struct net_device *dev, unsigned char *Data,
static void tms380tr_cancel_tx_queue(struct net_local* tp) static void tms380tr_cancel_tx_queue(struct net_local* tp)
{ {
TPL *tpl; TPL *tpl;
struct sk_buff *skb;
/* /*
* NOTE: There must not be an active TRANSMIT command pending, when * NOTE: There must not be an active TRANSMIT command pending, when
...@@ -2023,15 +1995,6 @@ static void tms380tr_cancel_tx_queue(struct net_local* tp) ...@@ -2023,15 +1995,6 @@ static void tms380tr_cancel_tx_queue(struct net_local* tp)
dev_kfree_skb_any(tpl->Skb); dev_kfree_skb_any(tpl->Skb);
} }
for(;;)
{
skb = skb_dequeue(&tp->SendSkbQueue);
if(skb == NULL)
break;
tp->QueueSkb++;
dev_kfree_skb_any(skb);
}
return; return;
} }
...@@ -2102,9 +2065,8 @@ static void tms380tr_tx_status_irq(struct net_device *dev) ...@@ -2102,9 +2065,8 @@ static void tms380tr_tx_status_irq(struct net_device *dev)
tpl->BusyFlag = 0; /* "free" TPL */ tpl->BusyFlag = 0; /* "free" TPL */
} }
netif_wake_queue(dev); if(!tp->TplFree->NextTPLPtr->BusyFlag)
if(tp->QueueSkb < MAX_TX_QUEUE) netif_wake_queue(dev);
tms380tr_hardware_send_packet(dev, tp);
return; return;
} }
......
...@@ -598,7 +598,6 @@ typedef struct { ...@@ -598,7 +598,6 @@ typedef struct {
* in one RPL/TPL. (depending on TI firmware * in one RPL/TPL. (depending on TI firmware
* version) * version)
*/ */
#define MAX_TX_QUEUE 10 /* Maximal number of skb's queued in driver. */
/* /*
* AC (1), FC (1), Dst (6), Src (6), RIF (18), Data (4472) = 4504 * AC (1), FC (1), Dst (6), Src (6), RIF (18), Data (4472) = 4504
...@@ -1114,9 +1113,6 @@ typedef struct net_local { ...@@ -1114,9 +1113,6 @@ typedef struct net_local {
unsigned long StartTime; unsigned long StartTime;
unsigned long LastSendTime; unsigned long LastSendTime;
struct sk_buff_head SendSkbQueue;
unsigned short QueueSkb;
struct tr_statistics MacStat; /* MAC statistics structure */ struct tr_statistics MacStat; /* MAC statistics structure */
unsigned long dmalimit; /* the max DMA address (ie, ISA) */ unsigned long dmalimit; /* the max DMA address (ie, ISA) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment