Commit 2ffa5fed authored by Christian Lamparter's avatar Christian Lamparter Committed by John W. Linville

p54: fix queue stall due to underrun

Larry Finger discovered a weird behavior under load.
In essence, the queue's length count under runs,
which in turn renders the associated ac queue unusable.
Reported-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarChristian Lamparter <chunkeey@web.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6d541a68
...@@ -199,7 +199,7 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv, ...@@ -199,7 +199,7 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv,
queue = &priv->tx_stats[p54_queue]; queue = &priv->tx_stats[p54_queue];
spin_lock_irqsave(&priv->tx_stats_lock, flags); spin_lock_irqsave(&priv->tx_stats_lock, flags);
if (unlikely(queue->len > queue->limit && IS_QOS_QUEUE(p54_queue))) { if (unlikely(queue->len >= queue->limit && IS_QOS_QUEUE(p54_queue))) {
spin_unlock_irqrestore(&priv->tx_stats_lock, flags); spin_unlock_irqrestore(&priv->tx_stats_lock, flags);
return -ENOSPC; return -ENOSPC;
} }
...@@ -222,8 +222,11 @@ static void p54_tx_qos_accounting_free(struct p54_common *priv, ...@@ -222,8 +222,11 @@ static void p54_tx_qos_accounting_free(struct p54_common *priv,
if (skb && IS_DATA_FRAME(skb)) { if (skb && IS_DATA_FRAME(skb)) {
struct p54_hdr *hdr = (void *) skb->data; struct p54_hdr *hdr = (void *) skb->data;
struct p54_tx_data *data = (void *) hdr->data; struct p54_tx_data *data = (void *) hdr->data;
unsigned long flags;
spin_lock_irqsave(&priv->tx_stats_lock, flags);
priv->tx_stats[data->hw_queue].len--; priv->tx_stats[data->hw_queue].len--;
spin_unlock_irqrestore(&priv->tx_stats_lock, flags);
} }
p54_wake_queues(priv); p54_wake_queues(priv);
} }
...@@ -462,7 +465,6 @@ static void p54_rx_eeprom_readback(struct p54_common *priv, ...@@ -462,7 +465,6 @@ static void p54_rx_eeprom_readback(struct p54_common *priv,
priv->eeprom = NULL; priv->eeprom = NULL;
tmp = p54_find_and_unlink_skb(priv, hdr->req_id); tmp = p54_find_and_unlink_skb(priv, hdr->req_id);
p54_tx_qos_accounting_free(priv, tmp);
dev_kfree_skb_any(tmp); dev_kfree_skb_any(tmp);
complete(&priv->eeprom_comp); complete(&priv->eeprom_comp);
} }
...@@ -489,7 +491,6 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) ...@@ -489,7 +491,6 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)
priv->noise = p54_rssi_to_dbm(priv, le32_to_cpu(stats->noise)); priv->noise = p54_rssi_to_dbm(priv, le32_to_cpu(stats->noise));
tmp = p54_find_and_unlink_skb(priv, hdr->req_id); tmp = p54_find_and_unlink_skb(priv, hdr->req_id);
p54_tx_qos_accounting_free(priv, tmp);
dev_kfree_skb_any(tmp); dev_kfree_skb_any(tmp);
} }
......
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