From 82d5f4aaf182c306d2c2ef4d3a89d0fb8e386aa8 Mon Sep 17 00:00:00 2001
From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Date: Wed, 3 May 2006 23:42:04 +0900
Subject: [PATCH] [PATCH] shpchp: Create shpchpd at controller probe time

The workqueue thread of shpchp driver should be created only when SHPC
based hotplug slots are detected on the system.

Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Cc: Kristen Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/pci/hotplug/shpchp_core.c |  8 --------
 drivers/pci/hotplug/shpchp_hpc.c  | 19 +++++++++++++++++++
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 3be4d492ccc2..a14e7de19846 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -491,16 +491,9 @@ static int __init shpcd_init(void)
 	shpchp_poll_mode = 1;
 #endif
 
-	shpchp_wq = create_singlethread_workqueue("shpchpd");
-	if (!shpchp_wq)
-		return -ENOMEM;
-
 	retval = pci_register_driver(&shpc_driver);
 	dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	if (retval) {
-		destroy_workqueue(shpchp_wq);
-	}
 	return retval;
 }
 
@@ -508,7 +501,6 @@ static void __exit shpcd_cleanup(void)
 {
 	dbg("unload_shpchpd()\n");
 	pci_unregister_driver(&shpc_driver);
-	destroy_workqueue(shpchp_wq);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 8b63f772a6f2..5e8f589d0b64 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -216,6 +216,8 @@ static struct php_ctlr_state_s *php_ctlr_list_head;	/* HPC state linked list */
 static int ctlr_seq_num = 0;	/* Controller sequenc # */
 static spinlock_t list_lock;
 
+static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
+
 static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs);
 
 static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
@@ -866,6 +868,13 @@ static void hpc_release_ctlr(struct controller *ctrl)
 
 	kfree(php_ctlr);
 
+	/*
+	 * If this is the last controller to be released, destroy the
+	 * shpchpd work queue
+	 */
+	if (atomic_dec_and_test(&shpchp_num_controllers))
+		destroy_workqueue(shpchp_wq);
+
 DBG_LEAVE_ROUTINE
 			  
 }
@@ -1460,6 +1469,16 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 
 	ctlr_seq_num++;
 
+	/*
+	 * If this is the first controller to be initialized,
+	 * initialize the shpchpd work queue
+	 */
+	if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
+		shpchp_wq = create_singlethread_workqueue("shpchpd");
+		if (!shpchp_wq)
+			return -ENOMEM;
+	}
+
 	/*
 	 * Unmask all event interrupts of all slots
 	 */
-- 
GitLab