Merge branches 'x86-fixes-for-linus', 'sched-fixes-for-linus', 'timers-fixes-for...
[pandora-kernel.git] / drivers / net / wireless / ipw2x00 / ipw2200.c
index ae438ed..42c3fe3 100644 (file)
@@ -894,9 +894,8 @@ static void ipw_led_link_on(struct ipw_priv *priv)
 
                /* If we aren't associated, schedule turning the LED off */
                if (!(priv->status & STATUS_ASSOCIATED))
-                       queue_delayed_work(priv->workqueue,
-                                          &priv->led_link_off,
-                                          LD_TIME_LINK_ON);
+                       schedule_delayed_work(&priv->led_link_off,
+                                             LD_TIME_LINK_ON);
        }
 
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -939,8 +938,8 @@ static void ipw_led_link_off(struct ipw_priv *priv)
                 * turning the LED on (blink while unassociated) */
                if (!(priv->status & STATUS_RF_KILL_MASK) &&
                    !(priv->status & STATUS_ASSOCIATED))
-                       queue_delayed_work(priv->workqueue, &priv->led_link_on,
-                                          LD_TIME_LINK_OFF);
+                       schedule_delayed_work(&priv->led_link_on,
+                                             LD_TIME_LINK_OFF);
 
        }
 
@@ -980,13 +979,11 @@ static void __ipw_led_activity_on(struct ipw_priv *priv)
                priv->status |= STATUS_LED_ACT_ON;
 
                cancel_delayed_work(&priv->led_act_off);
-               queue_delayed_work(priv->workqueue, &priv->led_act_off,
-                                  LD_TIME_ACT_ON);
+               schedule_delayed_work(&priv->led_act_off, LD_TIME_ACT_ON);
        } else {
                /* Reschedule LED off for full time period */
                cancel_delayed_work(&priv->led_act_off);
-               queue_delayed_work(priv->workqueue, &priv->led_act_off,
-                                  LD_TIME_ACT_ON);
+               schedule_delayed_work(&priv->led_act_off, LD_TIME_ACT_ON);
        }
 }
 
@@ -1184,7 +1181,7 @@ static void ipw_led_shutdown(struct ipw_priv *priv)
 /*
  * The following adds a new attribute to the sysfs representation
  * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/)
- * used for controling the debug level.
+ * used for controlling the debug level.
  *
  * See the level definitions in ipw for details.
  */
@@ -1795,13 +1792,11 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
        if (disable_radio) {
                priv->status |= STATUS_RF_KILL_SW;
 
-               if (priv->workqueue) {
-                       cancel_delayed_work(&priv->request_scan);
-                       cancel_delayed_work(&priv->request_direct_scan);
-                       cancel_delayed_work(&priv->request_passive_scan);
-                       cancel_delayed_work(&priv->scan_event);
-               }
-               queue_work(priv->workqueue, &priv->down);
+               cancel_delayed_work(&priv->request_scan);
+               cancel_delayed_work(&priv->request_direct_scan);
+               cancel_delayed_work(&priv->request_passive_scan);
+               cancel_delayed_work(&priv->scan_event);
+               schedule_work(&priv->down);
        } else {
                priv->status &= ~STATUS_RF_KILL_SW;
                if (rf_kill_active(priv)) {
@@ -1809,10 +1804,10 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
                                          "disabled by HW switch\n");
                        /* Make sure the RF_KILL check timer is running */
                        cancel_delayed_work(&priv->rf_kill);
-                       queue_delayed_work(priv->workqueue, &priv->rf_kill,
-                                          round_jiffies_relative(2 * HZ));
+                       schedule_delayed_work(&priv->rf_kill,
+                                             round_jiffies_relative(2 * HZ));
                } else
-                       queue_work(priv->workqueue, &priv->up);
+                       schedule_work(&priv->up);
        }
 
        return 1;
@@ -2063,7 +2058,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
                cancel_delayed_work(&priv->request_passive_scan);
                cancel_delayed_work(&priv->scan_event);
                schedule_work(&priv->link_down);
-               queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
+               schedule_delayed_work(&priv->rf_kill, 2 * HZ);
                handled |= IPW_INTA_BIT_RF_KILL_DONE;
        }
 
@@ -2103,7 +2098,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
                priv->status &= ~STATUS_HCMD_ACTIVE;
                wake_up_interruptible(&priv->wait_command_queue);
 
-               queue_work(priv->workqueue, &priv->adapter_restart);
+               schedule_work(&priv->adapter_restart);
                handled |= IPW_INTA_BIT_FATAL_ERROR;
        }
 
@@ -2323,11 +2318,6 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
        return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac);
 }
 
-/*
- * NOTE: This must be executed from our workqueue as it results in udelay
- * being called which may corrupt the keyboard if executed on default
- * workqueue
- */
 static void ipw_adapter_restart(void *adapter)
 {
        struct ipw_priv *priv = adapter;
@@ -2368,13 +2358,13 @@ static void ipw_scan_check(void *data)
                IPW_DEBUG_SCAN("Scan completion watchdog resetting "
                               "adapter after (%dms).\n",
                               jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
-               queue_work(priv->workqueue, &priv->adapter_restart);
+               schedule_work(&priv->adapter_restart);
        } else if (priv->status & STATUS_SCANNING) {
                IPW_DEBUG_SCAN("Scan completion watchdog aborting scan "
                               "after (%dms).\n",
                               jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
                ipw_abort_scan(priv);
-               queue_delayed_work(priv->workqueue, &priv->scan_check, HZ);
+               schedule_delayed_work(&priv->scan_check, HZ);
        }
 }
 
@@ -3773,7 +3763,7 @@ static int ipw_queue_tx_init(struct ipw_priv *priv,
 
        q->txb = kmalloc(sizeof(q->txb[0]) * count, GFP_KERNEL);
        if (!q->txb) {
-               IPW_ERROR("vmalloc for auxilary BD structures failed\n");
+               IPW_ERROR("vmalloc for auxiliary BD structures failed\n");
                return -ENOMEM;
        }
 
@@ -3943,7 +3933,7 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
 
        if (priv->status & STATUS_ASSOCIATING) {
                IPW_DEBUG_ASSOC("Disassociating while associating.\n");
-               queue_work(priv->workqueue, &priv->disassociate);
+               schedule_work(&priv->disassociate);
                return;
        }
 
@@ -4360,8 +4350,7 @@ static void ipw_gather_stats(struct ipw_priv *priv)
 
        priv->quality = quality;
 
-       queue_delayed_work(priv->workqueue, &priv->gather_stats,
-                          IPW_STATS_INTERVAL);
+       schedule_delayed_work(&priv->gather_stats, IPW_STATS_INTERVAL);
 }
 
 static void ipw_bg_gather_stats(struct work_struct *work)
@@ -4396,10 +4385,10 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
                        IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF |
                                  IPW_DL_STATE,
                                  "Aborting scan with missed beacon.\n");
-                       queue_work(priv->workqueue, &priv->abort_scan);
+                       schedule_work(&priv->abort_scan);
                }
 
-               queue_work(priv->workqueue, &priv->disassociate);
+               schedule_work(&priv->disassociate);
                return;
        }
 
@@ -4425,8 +4414,7 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
                if (!(priv->status & STATUS_ROAMING)) {
                        priv->status |= STATUS_ROAMING;
                        if (!(priv->status & STATUS_SCANNING))
-                               queue_delayed_work(priv->workqueue,
-                                                  &priv->request_scan, 0);
+                               schedule_delayed_work(&priv->request_scan, 0);
                }
                return;
        }
@@ -4439,7 +4427,7 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
                 * channels..) */
                IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | IPW_DL_STATE,
                          "Aborting scan with missed beacon.\n");
-               queue_work(priv->workqueue, &priv->abort_scan);
+               schedule_work(&priv->abort_scan);
        }
 
        IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count);
@@ -4462,8 +4450,8 @@ static void handle_scan_event(struct ipw_priv *priv)
        /* Only userspace-requested scan completion events go out immediately */
        if (!priv->user_requested_scan) {
                if (!delayed_work_pending(&priv->scan_event))
-                       queue_delayed_work(priv->workqueue, &priv->scan_event,
-                                        round_jiffies_relative(msecs_to_jiffies(4000)));
+                       schedule_delayed_work(&priv->scan_event,
+                                             round_jiffies_relative(msecs_to_jiffies(4000)));
        } else {
                union iwreq_data wrqu;
 
@@ -4516,20 +4504,17 @@ static void ipw_rx_notification(struct ipw_priv *priv,
 
                                                IPW_DEBUG_ASSOC
                                                    ("queueing adhoc check\n");
-                                               queue_delayed_work(priv->
-                                                                  workqueue,
-                                                                  &priv->
-                                                                  adhoc_check,
-                                                                  le16_to_cpu(priv->
-                                                                  assoc_request.
-                                                                  beacon_interval));
+                                               schedule_delayed_work(
+                                                       &priv->adhoc_check,
+                                                       le16_to_cpu(priv->
+                                                       assoc_request.
+                                                       beacon_interval));
                                                break;
                                        }
 
                                        priv->status &= ~STATUS_ASSOCIATING;
                                        priv->status |= STATUS_ASSOCIATED;
-                                       queue_work(priv->workqueue,
-                                                  &priv->system_config);
+                                       schedule_work(&priv->system_config);
 
 #ifdef CONFIG_IPW2200_QOS
 #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \
@@ -4792,43 +4777,37 @@ static void ipw_rx_notification(struct ipw_priv *priv,
 #ifdef CONFIG_IPW2200_MONITOR
                        if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
                                priv->status |= STATUS_SCAN_FORCED;
-                               queue_delayed_work(priv->workqueue,
-                                                  &priv->request_scan, 0);
+                               schedule_delayed_work(&priv->request_scan, 0);
                                break;
                        }
                        priv->status &= ~STATUS_SCAN_FORCED;
 #endif                         /* CONFIG_IPW2200_MONITOR */
 
                        /* Do queued direct scans first */
-                       if (priv->status & STATUS_DIRECT_SCAN_PENDING) {
-                               queue_delayed_work(priv->workqueue,
-                                                  &priv->request_direct_scan, 0);
-                       }
+                       if (priv->status & STATUS_DIRECT_SCAN_PENDING)
+                               schedule_delayed_work(&priv->request_direct_scan, 0);
 
                        if (!(priv->status & (STATUS_ASSOCIATED |
                                              STATUS_ASSOCIATING |
                                              STATUS_ROAMING |
                                              STATUS_DISASSOCIATING)))
-                               queue_work(priv->workqueue, &priv->associate);
+                               schedule_work(&priv->associate);
                        else if (priv->status & STATUS_ROAMING) {
                                if (x->status == SCAN_COMPLETED_STATUS_COMPLETE)
                                        /* If a scan completed and we are in roam mode, then
                                         * the scan that completed was the one requested as a
                                         * result of entering roam... so, schedule the
                                         * roam work */
-                                       queue_work(priv->workqueue,
-                                                  &priv->roam);
+                                       schedule_work(&priv->roam);
                                else
                                        /* Don't schedule if we aborted the scan */
                                        priv->status &= ~STATUS_ROAMING;
                        } else if (priv->status & STATUS_SCAN_PENDING)
-                               queue_delayed_work(priv->workqueue,
-                                                  &priv->request_scan, 0);
+                               schedule_delayed_work(&priv->request_scan, 0);
                        else if (priv->config & CFG_BACKGROUND_SCAN
                                 && priv->status & STATUS_ASSOCIATED)
-                               queue_delayed_work(priv->workqueue,
-                                                  &priv->request_scan,
-                                                  round_jiffies_relative(HZ));
+                               schedule_delayed_work(&priv->request_scan,
+                                                     round_jiffies_relative(HZ));
 
                        /* Send an empty event to user space.
                         * We don't send the received data on the event because
@@ -5192,7 +5171,7 @@ static void ipw_rx_queue_restock(struct ipw_priv *priv)
        /* If the pre-allocated buffer pool is dropping low, schedule to
         * refill it */
        if (rxq->free_count <= RX_LOW_WATERMARK)
-               queue_work(priv->workqueue, &priv->rx_replenish);
+               schedule_work(&priv->rx_replenish);
 
        /* If we've added more space for the firmware to place data, tell it */
        if (write != rxq->write)
@@ -5602,7 +5581,7 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
                return 0;
        }
 
-       /* Verify privacy compatability */
+       /* Verify privacy compatibility */
        if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
            ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
                IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
@@ -5829,7 +5808,7 @@ static int ipw_best_network(struct ipw_priv *priv,
                return 0;
        }
 
-       /* Verify privacy compatability */
+       /* Verify privacy compatibility */
        if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
            ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
                IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
@@ -6133,8 +6112,8 @@ static void ipw_adhoc_check(void *data)
                return;
        }
 
-       queue_delayed_work(priv->workqueue, &priv->adhoc_check,
-                          le16_to_cpu(priv->assoc_request.beacon_interval));
+       schedule_delayed_work(&priv->adhoc_check,
+                             le16_to_cpu(priv->assoc_request.beacon_interval));
 }
 
 static void ipw_bg_adhoc_check(struct work_struct *work)
@@ -6523,8 +6502,7 @@ send_request:
        } else
                priv->status &= ~STATUS_SCAN_PENDING;
 
-       queue_delayed_work(priv->workqueue, &priv->scan_check,
-                          IPW_SCAN_CHECK_WATCHDOG);
+       schedule_delayed_work(&priv->scan_check, IPW_SCAN_CHECK_WATCHDOG);
 done:
        mutex_unlock(&priv->mutex);
        return err;
@@ -6994,8 +6972,7 @@ static int ipw_qos_handle_probe_response(struct ipw_priv *priv,
                                    !memcmp(network->ssid,
                                            priv->assoc_network->ssid,
                                            network->ssid_len)) {
-                                       queue_work(priv->workqueue,
-                                                  &priv->merge_networks);
+                                       schedule_work(&priv->merge_networks);
                                }
        }
 
@@ -7663,7 +7640,7 @@ static int ipw_associate(void *data)
        if (priv->status & STATUS_DISASSOCIATING) {
                IPW_DEBUG_ASSOC("Not attempting association (in "
                                "disassociating)\n ");
-               queue_work(priv->workqueue, &priv->associate);
+               schedule_work(&priv->associate);
                return 0;
        }
 
@@ -7731,12 +7708,10 @@ static int ipw_associate(void *data)
 
                if (!(priv->status & STATUS_SCANNING)) {
                        if (!(priv->config & CFG_SPEED_SCAN))
-                               queue_delayed_work(priv->workqueue,
-                                                  &priv->request_scan,
-                                                  SCAN_INTERVAL);
+                               schedule_delayed_work(&priv->request_scan,
+                                                     SCAN_INTERVAL);
                        else
-                               queue_delayed_work(priv->workqueue,
-                                                  &priv->request_scan, 0);
+                               schedule_delayed_work(&priv->request_scan, 0);
                }
 
                return 0;
@@ -8209,7 +8184,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
 static int is_network_packet(struct ipw_priv *priv,
                                    struct libipw_hdr_4addr *header)
 {
-       /* Filter incoming packets to determine if they are targetted toward
+       /* Filter incoming packets to determine if they are targeted toward
         * this network, discarding packets coming from ourselves */
        switch (priv->ieee->iw_mode) {
        case IW_MODE_ADHOC:     /* Header: Dest. | Source    | BSSID */
@@ -8365,9 +8340,9 @@ static void ipw_handle_mgmt_packet(struct ipw_priv *priv,
 }
 
 /*
- * Main entry function for recieving a packet with 80211 headers.  This
+ * Main entry function for receiving a packet with 80211 headers.  This
  * should be called when ever the FW has notified us that there is a new
- * skb in the recieve queue.
+ * skb in the receive queue.
  */
 static void ipw_rx(struct ipw_priv *priv)
 {
@@ -8708,7 +8683,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
  * functions defined in ipw_main to provide the HW interaction.
  *
  * The exception to this is the use of the ipw_get_ordinal()
- * function used to poll the hardware vs. making unecessary calls.
+ * function used to poll the hardware vs. making unnecessary calls.
  *
  */
 
@@ -8899,7 +8874,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
 
        priv->ieee->iw_mode = wrqu->mode;
 
-       queue_work(priv->workqueue, &priv->adapter_restart);
+       schedule_work(&priv->adapter_restart);
        mutex_unlock(&priv->mutex);
        return err;
 }
@@ -9598,7 +9573,7 @@ static int ipw_wx_set_scan(struct net_device *dev,
 
        IPW_DEBUG_WX("Start scan\n");
 
-       queue_delayed_work(priv->workqueue, work, 0);
+       schedule_delayed_work(work, 0);
 
        return 0;
 }
@@ -9937,7 +9912,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
 #else
                        priv->net_dev->type = ARPHRD_IEEE80211;
 #endif
-                       queue_work(priv->workqueue, &priv->adapter_restart);
+                       schedule_work(&priv->adapter_restart);
                }
 
                ipw_set_channel(priv, parms[1]);
@@ -9947,7 +9922,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
                        return 0;
                }
                priv->net_dev->type = ARPHRD_ETHER;
-               queue_work(priv->workqueue, &priv->adapter_restart);
+               schedule_work(&priv->adapter_restart);
        }
        mutex_unlock(&priv->mutex);
        return 0;
@@ -9961,7 +9936,7 @@ static int ipw_wx_reset(struct net_device *dev,
 {
        struct ipw_priv *priv = libipw_priv(dev);
        IPW_DEBUG_WX("RESET\n");
-       queue_work(priv->workqueue, &priv->adapter_restart);
+       schedule_work(&priv->adapter_restart);
        return 0;
 }
 
@@ -10444,7 +10419,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
 
        memset(&dummystats, 0, sizeof(dummystats));
 
-       /* Filtering of fragment chains is done agains the first fragment */
+       /* Filtering of fragment chains is done against the first fragment */
        hdr = (void *)txb->fragments[0]->data;
        if (libipw_is_management(le16_to_cpu(hdr->frame_control))) {
                if (filter & IPW_PROM_NO_MGMT)
@@ -10551,7 +10526,7 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p)
        memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
        printk(KERN_INFO "%s: Setting MAC to %pM\n",
               priv->net_dev->name, priv->mac_addr);
-       queue_work(priv->workqueue, &priv->adapter_restart);
+       schedule_work(&priv->adapter_restart);
        mutex_unlock(&priv->mutex);
        return 0;
 }
@@ -10684,9 +10659,7 @@ static void ipw_rf_kill(void *adapter)
 
        if (rf_kill_active(priv)) {
                IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
-               if (priv->workqueue)
-                       queue_delayed_work(priv->workqueue,
-                                          &priv->rf_kill, 2 * HZ);
+               schedule_delayed_work(&priv->rf_kill, 2 * HZ);
                goto exit_unlock;
        }
 
@@ -10697,7 +10670,7 @@ static void ipw_rf_kill(void *adapter)
                                  "device\n");
 
                /* we can not do an adapter restart while inside an irq lock */
-               queue_work(priv->workqueue, &priv->adapter_restart);
+               schedule_work(&priv->adapter_restart);
        } else
                IPW_DEBUG_RF_KILL("HW RF Kill deactivated.  SW RF Kill still "
                                  "enabled\n");
@@ -10735,7 +10708,7 @@ static void ipw_link_up(struct ipw_priv *priv)
        notify_wx_assoc_event(priv);
 
        if (priv->config & CFG_BACKGROUND_SCAN)
-               queue_delayed_work(priv->workqueue, &priv->request_scan, HZ);
+               schedule_delayed_work(&priv->request_scan, HZ);
 }
 
 static void ipw_bg_link_up(struct work_struct *work)
@@ -10764,7 +10737,7 @@ static void ipw_link_down(struct ipw_priv *priv)
 
        if (!(priv->status & STATUS_EXIT_PENDING)) {
                /* Queue up another scan... */
-               queue_delayed_work(priv->workqueue, &priv->request_scan, 0);
+               schedule_delayed_work(&priv->request_scan, 0);
        } else
                cancel_delayed_work(&priv->scan_event);
 }
@@ -10782,7 +10755,6 @@ static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv)
 {
        int ret = 0;
 
-       priv->workqueue = create_workqueue(DRV_NAME);
        init_waitqueue_head(&priv->wait_command_queue);
        init_waitqueue_head(&priv->wait_state);
 
@@ -11339,8 +11311,7 @@ static int ipw_up(struct ipw_priv *priv)
                        IPW_WARNING("Radio Frequency Kill Switch is On:\n"
                                    "Kill switch must be turned off for "
                                    "wireless networking to work.\n");
-                       queue_delayed_work(priv->workqueue, &priv->rf_kill,
-                                          2 * HZ);
+                       schedule_delayed_work(&priv->rf_kill, 2 * HZ);
                        return 0;
                }
 
@@ -11350,8 +11321,7 @@ static int ipw_up(struct ipw_priv *priv)
 
                        /* If configure to try and auto-associate, kick
                         * off a scan. */
-                       queue_delayed_work(priv->workqueue,
-                                          &priv->request_scan, 0);
+                       schedule_delayed_work(&priv->request_scan, 0);
 
                        return 0;
                }
@@ -11817,7 +11787,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
        err = request_irq(pdev->irq, ipw_isr, IRQF_SHARED, DRV_NAME, priv);
        if (err) {
                IPW_ERROR("Error allocating IRQ %d\n", pdev->irq);
-               goto out_destroy_workqueue;
+               goto out_iounmap;
        }
 
        SET_NETDEV_DEV(net_dev, &pdev->dev);
@@ -11885,9 +11855,6 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
        sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
       out_release_irq:
        free_irq(pdev->irq, priv);
-      out_destroy_workqueue:
-       destroy_workqueue(priv->workqueue);
-       priv->workqueue = NULL;
       out_iounmap:
        iounmap(priv->hw_base);
       out_pci_release_regions:
@@ -11930,18 +11897,31 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
                kfree(priv->cmdlog);
                priv->cmdlog = NULL;
        }
-       /* ipw_down will ensure that there is no more pending work
-        * in the workqueue's, so we can safely remove them now. */
-       cancel_delayed_work(&priv->adhoc_check);
-       cancel_delayed_work(&priv->gather_stats);
-       cancel_delayed_work(&priv->request_scan);
-       cancel_delayed_work(&priv->request_direct_scan);
-       cancel_delayed_work(&priv->request_passive_scan);
-       cancel_delayed_work(&priv->scan_event);
-       cancel_delayed_work(&priv->rf_kill);
-       cancel_delayed_work(&priv->scan_check);
-       destroy_workqueue(priv->workqueue);
-       priv->workqueue = NULL;
+
+       /* make sure all works are inactive */
+       cancel_delayed_work_sync(&priv->adhoc_check);
+       cancel_work_sync(&priv->associate);
+       cancel_work_sync(&priv->disassociate);
+       cancel_work_sync(&priv->system_config);
+       cancel_work_sync(&priv->rx_replenish);
+       cancel_work_sync(&priv->adapter_restart);
+       cancel_delayed_work_sync(&priv->rf_kill);
+       cancel_work_sync(&priv->up);
+       cancel_work_sync(&priv->down);
+       cancel_delayed_work_sync(&priv->request_scan);
+       cancel_delayed_work_sync(&priv->request_direct_scan);
+       cancel_delayed_work_sync(&priv->request_passive_scan);
+       cancel_delayed_work_sync(&priv->scan_event);
+       cancel_delayed_work_sync(&priv->gather_stats);
+       cancel_work_sync(&priv->abort_scan);
+       cancel_work_sync(&priv->roam);
+       cancel_delayed_work_sync(&priv->scan_check);
+       cancel_work_sync(&priv->link_up);
+       cancel_work_sync(&priv->link_down);
+       cancel_delayed_work_sync(&priv->led_link_on);
+       cancel_delayed_work_sync(&priv->led_link_off);
+       cancel_delayed_work_sync(&priv->led_act_off);
+       cancel_work_sync(&priv->merge_networks);
 
        /* Free MAC hash list for ADHOC */
        for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) {
@@ -12029,7 +12009,7 @@ static int ipw_pci_resume(struct pci_dev *pdev)
        priv->suspend_time = get_seconds() - priv->suspend_at;
 
        /* Bring the device back up */
-       queue_work(priv->workqueue, &priv->up);
+       schedule_work(&priv->up);
 
        return 0;
 }