Re: ipw2200 stalls on high load
"Chatre, Reinette" <[email protected]> Mon, 4 Feb 2008 10:23:49 -0800
| Newsgroups | gmane.linux.drivers.ipw2100.devel,gmane.linux.kernel.wireless.general |
|---|---|
| Message-ID | <D936D925018D154694D8A362EEB0892003947453@orsmsx416.amr.corp.intel.com> |
On Monday, February 04, 2008 4:37 AM, Dan Williams wrote:
> Something like the following? Turns out the rxq->processed
> isn't really
> used that much, and 3945/4965 don't use that field at all (but use
> ->read exclusively instead). And since it appears that the replenish
> function is simpler in the 2200, it doesn't need to be split like
> 3945/4965. I haven't been able to stress my 2200 enough to trigger
> the new codepath though.
Thank you very much!
Sebastian, does this change work for you?
Reinette
(patch kept below ...)
>
>
> diff --git a/drivers/net/wireless/ipw2200.c
> b/drivers/net/wireless/ipw2200.c
> index 3e6ad7b..8856eea 100644
> --- a/drivers/net/wireless/ipw2200.c
> +++ b/drivers/net/wireless/ipw2200.c
> @@ -3365,7 +3365,6 @@ static void ipw_rx_queue_reset(struct
> ipw_priv *priv,
> /* Set us so that we have processed and used all
> buffers, but have
> * not restocked the Rx queue with fresh buffers */
rxq->read =
> rxq->write = 0; - rxq->processed = RX_QUEUE_SIZE - 1;
> rxq->free_count = 0;
> spin_unlock_irqrestore(&rxq->lock, flags);
> }
> @@ -3607,7 +3606,22 @@ static int ipw_load(struct ipw_priv *priv)
> * Driver allocates buffers of this size for Rx
> */
>
> -static inline int ipw_queue_space(const struct clx2_queue *q) +/**
> + * ipw_rx_queue_space - Return number of free slots available
> in queue.
> + */
> +static int ipw_rx_queue_space(const struct ipw_rx_queue *q) +{
> + int s = q->read - q->write;
> + if (s <= 0)
> + s += RX_QUEUE_SIZE;
> + /* keep some buffer to not confuse full and empty queue */ +
s -= 2;
> + if (s < 0)
> + s = 0;
> + return s;
> +}
> +
> +static inline int ipw_tx_queue_space(const struct clx2_queue *q) {
> int s = q->last_used - q->first_empty;
> if (s <= 0)
> @@ -4947,7 +4961,7 @@ static int ipw_queue_tx_reclaim(struct
> ipw_priv *priv,
> priv->tx_packets++;
> }
> done:
> - if ((ipw_queue_space(q) > q->low_mark) &&
> + if ((ipw_tx_queue_space(q) > q->low_mark) &&
> (qindex >= 0) &&
> (priv->status & STATUS_ASSOCIATED) &&
> netif_running(priv->net_dev))
> netif_wake_queue(priv->net_dev);
> @@ -4965,7 +4979,7 @@ static int ipw_queue_tx_hcmd(struct
> ipw_priv *priv, int hcmd, void *buf,
> struct clx2_queue *q = &txq->q;
> struct tfd_frame *tfd;
>
> - if (ipw_queue_space(q) < (sync ? 1 : 2)) {
> + if (ipw_tx_queue_space(q) < (sync ? 1 : 2)) {
> IPW_ERROR("No space for Tx\n");
> return -EBUSY;
> }
> @@ -5070,7 +5084,7 @@ static void ipw_rx_queue_restock(struct
> ipw_priv *priv)
>
> spin_lock_irqsave(&rxq->lock, flags);
> write = rxq->write;
> - while ((rxq->write != rxq->processed) && (rxq->free_count)) {
> + while ((ipw_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
> element = rxq->rx_free.next;
> rxb = list_entry(element, struct
> ipw_rx_mem_buffer, list);
> list_del(element);
> @@ -5187,7 +5201,6 @@ static struct ipw_rx_queue
> *ipw_rx_queue_alloc(struct ipw_priv *priv)
> /* Set us so that we have processed and used all
> buffers, but have
> * not restocked the Rx queue with fresh buffers */
rxq->read =
> rxq->write = 0; - rxq->processed = RX_QUEUE_SIZE - 1;
> rxq->free_count = 0;
>
> return rxq;
> @@ -8223,13 +8236,18 @@ static void ipw_rx(struct ipw_priv *priv)
> struct ieee80211_hdr_4addr *header;
> u32 r, w, i;
> u8 network_packet;
> + u8 fill_rx = 0;
> + u32 count = 0;
> DECLARE_MAC_BUF(mac);
> DECLARE_MAC_BUF(mac2);
> DECLARE_MAC_BUF(mac3);
>
> r = ipw_read32(priv, IPW_RX_READ_INDEX);
> w = ipw_read32(priv, IPW_RX_WRITE_INDEX);
> - i = (priv->rxq->processed + 1) % RX_QUEUE_SIZE;
> + i = priv->rxq->read;
> +
> + if (ipw_rx_queue_space (priv->rxq) > (RX_QUEUE_SIZE / 2))
> + fill_rx = 1;
>
> while (i != r) {
> rxb = priv->rxq->queue[i];
> @@ -8404,11 +8422,21 @@ static void ipw_rx(struct ipw_priv *priv)
> list_add_tail(&rxb->list, &priv->rxq->rx_used);
>
> i = (i + 1) % RX_QUEUE_SIZE;
> +
> + /* If there are a lot of unsued frames, restock
> the Rx queue
> + * so the ucode won't assert */
> + if (fill_rx) {
> + count++;
> + if (count >= 8) {
> + priv->rxq->read = i;
> + ipw_rx_queue_replenish(priv);
> + count = 0;
> + }
> + }
> }
>
> /* Backtrack one entry */
> - priv->rxq->processed = (i ? i : RX_QUEUE_SIZE) - 1; -
> + priv->rxq->read = i;
> ipw_rx_queue_restock(priv);
> }
>
> @@ -10336,7 +10364,7 @@ static int ipw_tx_skb(struct ipw_priv
> *priv, struct ieee80211_txb *txb,
> 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)
> + if (ipw_tx_queue_space(q) < q->high_mark)
> netif_stop_queue(priv->net_dev);
>
> return NETDEV_TX_OK;
> @@ -10357,7 +10385,7 @@ static int
> ipw_net_is_queue_full(struct net_device *dev, int pri)
> struct clx2_tx_queue *txq = &priv->txq[0];
> #endif /* CONFIG_IPW2200_QOS */
>
> - if (ipw_queue_space(&txq->q) < txq->q.high_mark)
> + if (ipw_tx_queue_space(&txq->q) < txq->q.high_mark)
return 1;
>
> return 0;
> diff --git a/drivers/net/wireless/ipw2200.h
> b/drivers/net/wireless/ipw2200.h
> index fdc187e..72884e2 100644
> --- a/drivers/net/wireless/ipw2200.h
> +++ b/drivers/net/wireless/ipw2200.h
> @@ -719,7 +719,6 @@ struct ipw_rx_mem_buffer {
> struct ipw_rx_queue {
> struct ipw_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
> struct ipw_rx_mem_buffer *queue[RX_QUEUE_SIZE];
> - u32 processed; /* Internal index to last
> handled Rx packet */
> u32 read; /* Shared index to newest
> available Rx buffer */
> u32 write; /* Shared index to oldest
> written Rx packet */
> u32 free_count; /* Number of pre-allocated
> buffers in rx_free */
>
> -
> To unsubscribe from this list: send the line "unsubscribe
> linux-wireless" in the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/