Messages in this thread | | | Subject | Re: Stalls on sync PPP transmission (new card) | From | Henner Eisen <> | Date | 14 Oct 1999 23:22:03 +0200 |
| |
Hi,
>>>>> Linux Lists <lists@cyclades.com> writes:
>Ok, let's see if this e-mail provides more useful info. This is the >skeleton of cpc_queue_xmit: > >static int cpc_queue_xmit(struct sk_buff *skb, struct device *dev) >{ > if (dev->tbusy) { > if (time_before(jiffies, dev->trans_start + PC300_TX_TIMEOUT)) > return 1; > > stats->tx_dropped++; > dev->tbusy=0; This should be followed by a mark_bh(NET_BH).
This code part is only reached when an xmit timeout condition is detected (tbusy was set for a too long time, e.g. because a tx interrupt got lost). This should be a rare case. If this occurs frequently, then there is probably a bug. You might insert a printk() for debugging purpose here as well in order to detect if this is reached too frequently.
> } > > if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { > return 1; > This kind of locking is legacy code (still present in lots of drivers, it was necessary before linux 1.2.9, but strictly depraced now as it might be subject to race conditions with linux 2.3.x multithreaded linux network core).
Leave it out. tbusy should only be set in the dev->hard_start_xmit() thread when an xmitter-busy condition is detected (in your driver, this is probably at those location where your cpc_queue_xmit() returns 1). Other threads (e.g. interrupt handlers) are only allowed to clear tbusy.
tbusy is only to tell the upper layer whether the device is willing to accept more data for output. It should not be [ab]used for setting driver-internal locking state.
> > /* Write buffer to on-board DMA buffers */ > CPC_LOCK(card, flags); > if(dma_buf_write(card, chan, (ucchar *)skb->data, skb->len) != 0) { > CPC_UNLOCK(card, flags); > stats->tx_dropped++; > dev_kfree_skb(skb); > return 1; > } > CPC_UNLOCK(card, flags); > > stats->tx_bytes += skb->len; > dev_kfree_skb(skb); > stats->tx_packets++; > dev->trans_start = jiffies; > dev->tbusy = 0; > mark_bh(NET_BH); > > /* Start transmission */ > tx_dma_start(card, chan); > > return 0; >} > >Note that mark_bh is called just after dev->tbusy is set to 0 (before you >ask, there are no dropped packets, so I know that the other places where >tbusy could be set to 0 are not reached). > >Furthermore, the only other places where the tbusy value is changed are >the open (tbusy = 0) and close (tbusy = 1) functions. > Tbusy usually should be cleared whenever the driver detects that the device has become ready to accept a new frame for transmission. This usually occurs in the driverŽs interrupt handler when it detects that the last frame has successfully been send out because after that, the device is usually willing to accept the next frame for transmission. (some other code parts, e.g. error recovery and initialization routines, might do so as well).
>Do you know of anything else that might cause this?? Do you have any >suggestion on where to look (or what to use to debug it) in order to find >the culprit?? > >Thanks for your help. > >Regards, >Ivan
Henner
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |