summaryrefslogtreecommitdiff
path: root/drivers/dahdi/wcte12xp
diff options
context:
space:
mode:
authorRuss Meyerriecks <rmeyerreicks@digium.com>2011-06-28 22:29:00 +0000
committerRuss Meyerriecks <rmeyerreicks@digium.com>2011-06-28 22:29:00 +0000
commit608d6c66bc79ab57d2acf067ec7ed5d40b7d7749 (patch)
tree7e436a730202eb527cc319abfa2befecf1df40de /drivers/dahdi/wcte12xp
parentc7a4ca9241ab1774ef45e027afeb59573ee117c0 (diff)
wcte12xp, wctdm24xxp: Load VPMOCT032 firmware in background.
The firmware load has been moved into a workqueue to prevent the module load from blocking for the duration of the firmware upload. This could be up to 40 seconds. Driver prevents configuration until firmware load is finished and is_initialized() returns true. Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com> Signed-off-by: Shaun Ruffell <sruffell@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9998 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/wcte12xp')
-rw-r--r--drivers/dahdi/wcte12xp/base.c177
-rw-r--r--drivers/dahdi/wcte12xp/wcte12xp.h2
2 files changed, 97 insertions, 82 deletions
diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c
index 28afdf6..68fcd96 100644
--- a/drivers/dahdi/wcte12xp/base.c
+++ b/drivers/dahdi/wcte12xp/base.c
@@ -1054,8 +1054,24 @@ static int t1xxp_startup(struct file *file, struct dahdi_span *span)
static inline bool is_initialized(struct t1 *wc)
{
- WARN_ON(wc->initialized < 0);
- return (wc->initialized == 0);
+ WARN_ON(wc->not_ready < 0);
+ return (wc->not_ready == 0);
+}
+
+/**
+ * t1_wait_for_ready
+ *
+ * Check if the board has finished any setup and is ready to start processing
+ * calls.
+ */
+static int t1_wait_for_ready(struct t1 *wc)
+{
+ while (!is_initialized(wc)) {
+ if (fatal_signal_pending(current))
+ return -EIO;
+ msleep_interruptible(250);
+ }
+ return 0;
}
static int t1xxp_chanconfig(struct file *file,
@@ -1066,11 +1082,7 @@ static int t1xxp_chanconfig(struct file *file,
if (file->f_flags & O_NONBLOCK && !is_initialized(wc)) {
return -EAGAIN;
} else {
- while (!is_initialized(wc)) {
- if (fatal_signal_pending(current))
- return -EIO;
- msleep_interruptible(250);
- }
+ t1_wait_for_ready(wc);
}
if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags) &&
@@ -1539,7 +1551,7 @@ static void vpm_load_func(struct work_struct *work)
set_bit(0, &wc->ctlreg);
}
- wc->initialized--;
+ wc->not_ready--;
kfree(w);
}
@@ -1561,26 +1573,42 @@ static int vpm_start_load(struct t1 *wc)
return 0;
}
-static int check_and_load_vpm(struct t1 *wc)
+static void t1_vpm_load_complete(struct device *dev, bool operational)
{
- int res;
unsigned long flags;
- struct vpmadt032_options options;
- struct vpmadt032 *vpm = NULL;
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct t1 *wc = pci_get_drvdata(pdev);
+ struct vpmoct *vpm = NULL;
- if (!vpmsupport) {
- t1_info(wc, "VPM Support Disabled\n");
- vpmadt032_free(wc->vpmadt032);
- wc->vpmadt032 = NULL;
- return 0;
+ if (!wc || is_initialized(wc)) {
+ WARN_ON(!wc);
+ return;
}
- /* The firmware may already be loaded. */
- if (wc->vpmadt032) {
- u16 version;
- res = gpakPingDsp(wc->vpmadt032->dspid, &version);
- if (!res)
- return 0;
+ spin_lock_irqsave(&wc->reglock, flags);
+ wc->not_ready--;
+ if (operational) {
+ set_bit(VPM150M_ACTIVE, &wc->ctlreg);
+ } else {
+ clear_bit(VPM150M_ACTIVE, &wc->ctlreg);
+ vpm = wc->vpmoct;
+ wc->vpmoct = NULL;
+ }
+ spin_unlock_irqrestore(&wc->reglock, flags);
+
+ if (vpm)
+ vpmoct_free(vpm);
+}
+
+static void check_and_load_vpm(struct t1 *wc)
+{
+ unsigned long flags;
+ struct vpmadt032_options options;
+ struct vpmadt032 *vpmadt = NULL;
+
+ if (!vpmsupport) {
+ t1_info(wc, "VPM Support Disabled via module parameter\n");
+ return;
}
memset(&options, 0, sizeof(options));
@@ -1594,69 +1622,49 @@ static int check_and_load_vpm(struct t1 *wc)
* done setting it up here, an hour should cover it... */
wc->vpm_check = jiffies + HZ*3600;
- vpm = vpmadt032_alloc(&options);
- if (!vpm)
- return -ENOMEM;
+ vpmadt = vpmadt032_alloc(&options);
+ if (!vpmadt)
+ return;
- vpm->setchanconfig_from_state = setchanconfig_from_state;
+ vpmadt->setchanconfig_from_state = setchanconfig_from_state;
spin_lock_irqsave(&wc->reglock, flags);
- wc->vpmadt032 = vpm;
+ wc->vpmadt032 = vpmadt;
spin_unlock_irqrestore(&wc->reglock, flags);
- res = vpmadt032_test(vpm, &wc->vb);
- if (-ENODEV == res) {
- struct vpmoct *vpmoct;
-
+ /* Probe for and attempt to load a vpmadt032 module */
+ if (vpmadt032_test(vpmadt, &wc->vb) || vpm_start_load(wc)) {
/* There does not appear to be a VPMADT032 installed. */
clear_bit(VPM150M_ACTIVE, &wc->ctlreg);
spin_lock_irqsave(&wc->reglock, flags);
wc->vpmadt032 = NULL;
spin_unlock_irqrestore(&wc->reglock, flags);
- vpmadt032_free(vpm);
+ vpmadt032_free(vpmadt);
+ }
+
+ /* Probe for and attempt to load a vpmoct032 module */
+ if (NULL == wc->vpmadt032) {
+ struct vpmoct *vpmoct;
/* Check for vpmoct */
vpmoct = vpmoct_alloc();
if (!vpmoct)
- return -ENOMEM;
+ return;
vpmoct->dev = &wc->vb.pdev->dev;
spin_lock_irqsave(&wc->reglock, flags);
wc->vpmoct = vpmoct;
+ wc->not_ready++;
spin_unlock_irqrestore(&wc->reglock, flags);
- res = vpmoct_init(wc->vpmoct);
- if (res) {
- dev_info(&wc->vb.pdev->dev,
- "Unable to initialize vpmoct module\n");
- spin_lock_irqsave(&wc->reglock, flags);
- wc->vpmoct = NULL;
- spin_unlock_irqrestore(&wc->reglock, flags);
- vpmoct_free(vpmoct);
- } else {
- set_bit(VPM150M_ACTIVE, &wc->ctlreg);
- }
-
- return res;
- }
-
- res = vpm_start_load(wc);
- if (res) {
- /* There does not appear to be a VPMADT032 installed. */
- clear_bit(VPM150M_ACTIVE, &wc->ctlreg);
- spin_lock_irqsave(&wc->reglock, flags);
- wc->vpmadt032 = NULL;
- spin_unlock_irqrestore(&wc->reglock, flags);
- vpmadt032_free(vpm);
- return res;
+ vpmoct_init(vpmoct, t1_vpm_load_complete);
}
- return res;
}
#else
-static inline int check_and_load_vpm(const struct t1 *wc)
+static inline void check_and_load_vpm(const struct t1 *wc)
{
- return 0;
+ return;
}
#endif
@@ -1706,11 +1714,7 @@ t1xxp_spanconfig(struct file *file, struct dahdi_span *span,
if (!is_initialized(wc))
return -EAGAIN;
} else {
- while (!is_initialized(wc)) {
- if (fatal_signal_pending(current))
- return -EIO;
- msleep_interruptible(250);
- }
+ t1_wait_for_ready(wc);
}
/* Do we want to SYNC on receive or not */
@@ -2340,7 +2344,7 @@ static void vpm_check_func(struct work_struct *work)
/* If there is a failed VPM module, do not block dahdi_cfg
* indefinitely. */
if (++wc->vpm_check_count > MAX_CHECKS) {
- wc->initialized--;
+ wc->not_ready--;
wc->vpm_check = MAX_JIFFY_OFFSET;
t1_info(wc, "Disabling VPMADT032 Checking.\n");
return;
@@ -2395,7 +2399,7 @@ static void vpm_check_func(struct work_struct *work)
set_bit(VPM150M_ACTIVE, &wc->ctlreg);
t1_info(wc, "VPMADT032 is reenabled.\n");
wc->vpm_check = jiffies + HZ*5;
- wc->initialized--;
+ wc->not_ready--;
return;
}
@@ -2544,7 +2548,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
if (!wc)
return -ENOMEM;
- wc->initialized = 1;
+ wc->not_ready = 1;
ifaces[index] = wc;
@@ -2659,11 +2663,10 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
t1_info(wc, "Found a %s\n", wc->variety);
voicebus_unlock_latency(&wc->vb);
- /* If there is VPMADT032 or VPMOCT032 module attached to this device,
- * it will signal ready after the channels are configured and ready
- * for use. */
- if (!wc->vpmadt032 && !wc->vpmoct)
- wc->initialized--;
+ /* If there is VPMADT032 module attached to this device, it will
+ * signal ready after the channels are configured and ready for use. */
+ if (!wc->vpmadt032)
+ wc->not_ready--;
return 0;
}
@@ -2671,7 +2674,9 @@ static void __devexit te12xp_remove_one(struct pci_dev *pdev)
{
struct t1 *wc = pci_get_drvdata(pdev);
#ifdef VPM_SUPPORT
- struct vpmadt032 *vpm = wc->vpmadt032;
+ unsigned long flags;
+ struct vpmadt032 *vpmadt = wc->vpmadt032;
+ struct vpmoct *vpmoct = wc->vpmoct;
#endif
if (!wc)
return;
@@ -2685,20 +2690,30 @@ static void __devexit te12xp_remove_one(struct pci_dev *pdev)
del_timer_sync(&wc->timer);
flush_workqueue(wc->wq);
#ifdef VPM_SUPPORT
- if (vpm)
- flush_workqueue(vpm->wq);
+ if (vpmadt) {
+ clear_bit(VPM150M_ACTIVE, &vpmadt->control);
+ flush_workqueue(vpmadt->wq);
+ } else if (vpmoct) {
+ while (t1_wait_for_ready(wc))
+ schedule();
+ }
#endif
del_timer_sync(&wc->timer);
voicebus_release(&wc->vb);
#ifdef VPM_SUPPORT
- if(vpm) {
+ if (vpmadt) {
+ spin_lock_irqsave(&wc->reglock, flags);
wc->vpmadt032 = NULL;
- clear_bit(VPM150M_ACTIVE, &vpm->control);
- vpmadt032_free(vpm);
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ vpmadt032_free(vpmadt);
+ } else if (vpmoct) {
+ spin_lock_irqsave(&wc->reglock, flags);
+ wc->vpmoct = NULL;
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ vpmoct_free(vpmoct);
}
-
#endif
t1_info(wc, "Freed a Wildcard TE12xP.\n");
diff --git a/drivers/dahdi/wcte12xp/wcte12xp.h b/drivers/dahdi/wcte12xp/wcte12xp.h
index a927e07..507a43e 100644
--- a/drivers/dahdi/wcte12xp/wcte12xp.h
+++ b/drivers/dahdi/wcte12xp/wcte12xp.h
@@ -139,7 +139,7 @@ struct t1 {
struct timer_list timer;
struct work_struct timer_work;
struct workqueue_struct *wq;
- bool initialized; /* 0 when entire card is ready to go */
+ unsigned int not_ready; /* 0 when entire card is ready to go */
};
#define t1_info(t1, format, arg...) \