summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2010-02-25 17:33:53 +0000
committerShaun Ruffell <sruffell@digium.com>2010-02-25 17:33:53 +0000
commit9a449e1df5edc16fda2c47afe68e8e5cf54026ee (patch)
tree50c40da59255ec49950e240526b57ae18ed4ac27
parent0df629312b8167561215d95773a2b7a7fdee0b40 (diff)
wctdm24xxp: Provide option to initialize boards in parallel on kernels > 2.6.30
The 2.6.30 kernel provides support for asynchronous initialization. If running on a kernel that supports this feature, let's add an option to use it in order to speed up driver load times. Keep it off by default. git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@8094 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/voicebus/voicebus.c17
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c66
2 files changed, 81 insertions, 2 deletions
diff --git a/drivers/dahdi/voicebus/voicebus.c b/drivers/dahdi/voicebus/voicebus.c
index 064e664..368060b 100644
--- a/drivers/dahdi/voicebus/voicebus.c
+++ b/drivers/dahdi/voicebus/voicebus.c
@@ -1656,6 +1656,7 @@ int vpmadtreg_loadfirmware(struct voicebus *vb)
struct vpmadt_loader *loader;
int ret = 0;
int loader_present = 0;
+ unsigned long stop;
might_sleep();
/* First check to see if a loader is already loaded into memory. */
@@ -1664,9 +1665,23 @@ int vpmadtreg_loadfirmware(struct voicebus *vb)
spin_unlock(&loader_list_lock);
if (!loader_present) {
- ret = request_module("dahdi_vpmadt032_loader");
+ /* If we use the blocking 'request_module' here and we are
+ * loading the client boards with async_schedule we will hang
+ * here. The module loader will wait for our asynchronous tasks
+ * to finish, but we can't because we're waiting for the load
+ * the finish. */
+ ret = request_module_nowait("dahdi_vpmadt032_loader");
if (ret)
return ret;
+ stop = jiffies + HZ;
+ while (time_after(stop, jiffies)) {
+ spin_lock(&loader_list_lock);
+ loader_present = !(list_empty(&binary_loader_list));
+ spin_unlock(&loader_list_lock);
+ if (loader_present)
+ break;
+ msleep(10);
+ }
}
spin_lock(&loader_list_lock);
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index cbe826e..8990d70 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -52,6 +52,16 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
#include <asm/semaphore.h>
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+/* Define this if you would like to load the modules in parallel. While this
+ * can speed up loads when multiple cards handled by this driver are installed,
+ * it also makes it impossible to abort module loads with ctrl-c */
+#undef USE_ASYNC_INIT
+#include <linux/async.h>
+#else
+#undef USE_ASYNC_INIT
+#endif
+
#include <dahdi/kernel.h>
#include <dahdi/wctdm_user.h>
@@ -3743,7 +3753,18 @@ static const struct voicebus_operations voicebus_operations = {
.handle_transmit = handle_transmit,
};
-static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+#ifdef USE_ASYNC_INIT
+struct async_data {
+ struct pci_dev *pdev;
+ const struct pci_device_id *ent;
+};
+static int __devinit
+__wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent,
+ async_cookie_t cookie)
+#else
+static int __devinit
+__wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+#endif
{
struct wctdm *wc;
int i;
@@ -3836,6 +3857,10 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
/* Final initialization */
wctdm_post_initialize(wc);
+#ifdef USE_ASYNC_INIT
+ async_synchronize_cookie(cookie);
+#endif
+
/* We should be ready for DAHDI to come in now. */
if (dahdi_register(&wc->span, 0)) {
dev_info(&wc->vb.pdev->dev,
@@ -3854,6 +3879,41 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
return 0;
}
+#ifdef USE_ASYNC_INIT
+static __devinit void
+wctdm_init_one_async(void *data, async_cookie_t cookie)
+{
+ struct async_data *dat = data;
+ __wctdm_init_one(dat->pdev, dat->ent, cookie);
+ kfree(dat);
+}
+
+static int __devinit
+wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct async_data *dat;
+
+ dat = kmalloc(sizeof(*dat), GFP_KERNEL);
+ /* If we can't allocate the memory for the async_data, odds are we won't
+ * be able to initialize the device either, but let's try synchronously
+ * anyway... */
+ if (!dat)
+ return __wctdm_init_one(pdev, ent, 0);
+
+ dat->pdev = pdev;
+ dat->ent = ent;
+ async_schedule(wctdm_init_one_async, dat);
+ return 0;
+}
+#else
+static int __devinit
+wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ return __wctdm_init_one(pdev, ent);
+}
+#endif
+
+
static void wctdm_release(struct wctdm *wc)
{
int i;
@@ -3965,6 +4025,10 @@ static int __init wctdm_init(void)
res = dahdi_pci_module(&wctdm_driver);
if (res)
return -ENODEV;
+
+#ifdef USE_ASYNC_INIT
+ async_synchronize_full();
+#endif
return 0;
}