wireless/ipw2x00: use system_wq instead of dedicated workqueues

With cmwq, there's no reason to use separate workqueues in ipw2x00
drivers.  Drop them and use system_wq instead.  All used work items
are sync canceled on driver detach.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: "John W. Linville" <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index ae438ed..160881f 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -894,9 +894,8 @@
 
 		/* 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 @@
 		 * 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 @@
 		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);
 	}
 }
 
@@ -1795,13 +1792,11 @@
 	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 @@
 					  "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 @@
 		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 @@
 		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 @@
 	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 @@
 		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);
 	}
 }
 
@@ -3943,7 +3933,7 @@
 
 	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 @@
 
 	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 @@
 			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 @@
 		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 @@
 		 * 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 @@
 	/* 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 @@
 
 						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 @@
 #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 @@
 	/* 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)
@@ -6133,8 +6112,8 @@
 		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 @@
 	} 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 @@
 				    !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 @@
 	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 @@
 
 		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;
@@ -8899,7 +8874,7 @@
 
 	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 @@
 
 	IPW_DEBUG_WX("Start scan\n");
 
-	queue_delayed_work(priv->workqueue, work, 0);
+	schedule_delayed_work(work, 0);
 
 	return 0;
 }
@@ -9937,7 +9912,7 @@
 #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 @@
 			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 @@
 {
 	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;
 }
 
@@ -10551,7 +10526,7 @@
 	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 @@
 
 	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 @@
 				  "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 @@
 	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 @@
 
 	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 @@
 {
 	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 @@
 			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 @@
 
 			/* 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 @@
 	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 @@
 	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 @@
 		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 @@
 	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;
 }