Stefan Rompf wrote: >Am Dienstag 24 Januar 2006 09:36 schrieb Zhu Yi: > > >>Two problems in ipw2200: >>1. We now have the ieee_device->is_queue_full interface, and it will be >> called at the beginning of ieee80211_xmit function. So no need to call >> it at the driver xmit function. >> >> > >This interface is totally broken. Actually this happens in ipw2200 since >version 1.0.8: > >-dev->hard_start_xmit() calls ieee80211_xmit() >-ieee80211_xmit() calls into ieee->is_queue_full() which is >ipw_net_is_queue_full() for the ipw2200 driver. If this function indicates >that the queue is full, ieee80211_xmit() returns NETDEV_TX_BUSY. >-On this return code, qdisc_restart() requeues the packet at the tail of leaf >qdisc and immediatly reschedules output via netif_schedule(dev), effectivly >busy polling for the queue becoming empty. > > The purpose for this code ever coming into existence within ieee80211 was based on discussions at OLS this past year in how to support for the ability to start/stop independent Tx queues within a single net device in order to support 802.11e QoS. We need to be able to indicate to the upper layers that packets of a given priority can not be sent any more with out halting transmission of all packets, and without rescheduling high priority packets down to the next priority level.
Jamal indicated we should just return NETDEV_TX_BUSY and the stack would take care of rescheduling... which it apparently does immediately and consumes the CPU. Can the qdisc interface do this correctly somehow, and if so, how do we signal to those layers to reschedule that packet for a later time? To put the code back to the way it was before we made these changes we can put the call netif_queue_stop back in ipw_tx_skb. This effectively disables multiple priority based transmit queues for 802.11e, but given that its broken anyway... diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 819be2b..24b762a 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -9815,6 +9815,10 @@ static int ipw_tx_skb(struct ipw_priv *p q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); ipw_write32(priv, q->reg_w, q->first_empty); + + if (ipw_queue_space(q) < q->high_mark) + netif_stop_queue(priv->net_dev); + return NETDEV_TX_OK; drop: >This is what leads to the high ksoftirqd usage I reported October 2005 into >the ipw bugzilla (http://www.bughost.org/bugzilla/show_bug.cgi?id=825). > >Please consider the workaround I posted there. > > Calling netif_stop_queue in ipw_tx_skb (vs. in is_queue_full) should keep is_queue_full() ever from returning 1 as the driver will stop being fed packets. If QoS is enabled, however, the interface will be stopped as soon as *any* of the transmit queues fill up. Transmit will only be reenabled when the currently full queue has an empty slot. This could dramatically impact throughput as a full low priority queue will block high priority packets from going out... James - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html