summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/libertas/main.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-12-09 23:54:27 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 15:06:30 -0800
commit2eb188a1c57ae79283cee951c317bd191cf1ca56 (patch)
tree6fa459e2d171f035c97af88bfa5957dd544b4413 /drivers/net/wireless/libertas/main.c
parentb8d40bc9c9099943cbcf18d285bf241f1f080a44 (diff)
libertas: Move actual transmission to main thread
The locking issues with TX, especially TX from multiple netdevs, get _so_ much easier if you do it like this. Signed-off-by: David Woodhouse <dwmw2@infradead.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r--drivers/net/wireless/libertas/main.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 42b64b5ad083..f16c93ba6efd 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -739,6 +739,8 @@ static int lbs_thread(void *data)
shouldsleep = 0; /* Interrupt pending. Deal with it now */
else if (priv->dnld_sent)
shouldsleep = 1; /* Something is en route to the device already */
+ else if (priv->tx_pending_len > 0)
+ shouldsleep = 0; /* We've a packet to send */
else if (priv->cur_cmd)
shouldsleep = 1; /* Can't send a command; one already running */
else if (!list_empty(&priv->cmdpendingq))
@@ -852,6 +854,28 @@ static int lbs_thread(void *data)
*/
if (!list_empty(&priv->cmdpendingq))
wake_up_all(&priv->cmd_pending);
+
+ spin_lock_irq(&priv->driver_lock);
+ if (!priv->dnld_sent && priv->tx_pending_len > 0) {
+ int ret = priv->hw_host_to_card(priv, MVMS_DAT,
+ priv->tx_pending_buf,
+ priv->tx_pending_len);
+ if (ret) {
+ lbs_deb_tx("host_to_card failed %d\n", ret);
+ priv->dnld_sent = DNLD_RES_RECEIVED;
+ }
+ priv->tx_pending_len = 0;
+ if (!priv->currenttxskb) {
+ /* We can wake the queues immediately if we aren't
+ waiting for TX feedback */
+ if (priv->connect_status == LBS_CONNECTED)
+ netif_wake_queue(priv->dev);
+ if (priv->mesh_dev &&
+ priv->mesh_connect_status == LBS_CONNECTED)
+ netif_wake_queue(priv->mesh_dev);
+ }
+ }
+ spin_unlock_irq(&priv->driver_lock);
}
del_timer(&priv->command_timer);