libertas: use private SDIO workqueue to avoid scheduling latency
authorDan Williams <dcbw@redhat.com>
Fri, 20 Feb 2009 17:27:38 +0000 (12:27 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 27 Feb 2009 19:52:51 +0000 (14:52 -0500)
The libertas SDIO interface scheduled the packet worker, resulting in
unwanted latency for every data packet or command sent to the firmware.
Fix a bug on the SDIO probe error path too.

Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/libertas/if_sdio.c

index 9878368..76f4c65 100644 (file)
@@ -95,6 +95,8 @@ struct if_sdio_card {
 
        spinlock_t              lock;
        struct if_sdio_packet   *packets;
+
+       struct workqueue_struct *workqueue;
        struct work_struct      packet_worker;
 };
 
@@ -746,7 +748,7 @@ static int if_sdio_host_to_card(struct lbs_private *priv,
 
        spin_unlock_irqrestore(&card->lock, flags);
 
-       schedule_work(&card->packet_worker);
+       queue_work(card->workqueue, &card->packet_worker);
 
        ret = 0;
 
@@ -836,6 +838,7 @@ static int if_sdio_probe(struct sdio_func *func,
        card->func = func;
        card->model = model;
        spin_lock_init(&card->lock);
+       card->workqueue = create_workqueue("libertas_sdio");
        INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
 
        for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) {
@@ -933,9 +936,8 @@ out:
        return ret;
 
 err_activate_card:
-       flush_scheduled_work();
-       free_netdev(priv->dev);
-       kfree(priv);
+       flush_workqueue(card->workqueue);
+       lbs_remove_card(priv);
 reclaim:
        sdio_claim_host(func);
 release_int:
@@ -945,6 +947,7 @@ disable:
 release:
        sdio_release_host(func);
 free:
+       destroy_workqueue(card->workqueue);
        while (card->packets) {
                packet = card->packets;
                card->packets = card->packets->next;
@@ -971,7 +974,8 @@ static void if_sdio_remove(struct sdio_func *func)
        lbs_stop_card(card->priv);
        lbs_remove_card(card->priv);
 
-       flush_scheduled_work();
+       flush_workqueue(card->workqueue);
+       destroy_workqueue(card->workqueue);
 
        sdio_claim_host(func);
        sdio_release_irq(func);