summaryrefslogtreecommitdiff
path: root/drivers/dahdi/wctdm24xxp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dahdi/wctdm24xxp')
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c112
-rw-r--r--drivers/dahdi/wctdm24xxp/wctdm24xxp.h8
-rw-r--r--drivers/dahdi/wctdm24xxp/xhfc.c10
3 files changed, 83 insertions, 47 deletions
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index 73bcae6..98c0f0e 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -309,12 +309,6 @@ static inline __attribute_const__ int VPM_CMD_BYTE(int timeslot, int bit)
return ((((timeslot) & 0x3) * 3 + (bit)) * 7) + ((timeslot) >> 2);
}
-static inline bool is_initialized(struct wctdm *wc)
-{
- WARN_ON(wc->initialized < 0);
- return (wc->initialized == 0);
-}
-
static void
setchanconfig_from_state(struct vpmadt032 *vpm, int channel,
GpakChannelConfig_t *chanconfig)
@@ -2131,6 +2125,7 @@ static const char *wctdm_echocan_name(const struct dahdi_chan *chan)
return vpmadt032_name;
else if (wc->vpmoct)
return vpmoct_name;
+
return NULL;
}
@@ -4374,12 +4369,37 @@ static int wctdm_initialize_vpmadt032(struct wctdm *wc)
return 0;
}
+static void wctdm_vpm_load_complete(struct device *dev, bool operational)
+{
+ unsigned long flags;
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct wctdm *wc = pci_get_drvdata(pdev);
+ struct vpmoct *vpm = NULL;
+
+ WARN_ON(!wc || !wc->not_ready);
+ if (!wc || !wc->not_ready)
+ return;
+
+ spin_lock_irqsave(&wc->reglock, flags);
+ wc->not_ready--;
+ if (operational) {
+ wc->ctlreg |= 0x10;
+ } else {
+ vpm = wc->vpmoct;
+ wc->vpmoct = NULL;
+ }
+ spin_unlock_irqrestore(&wc->reglock, flags);
+
+ if (vpm)
+ vpmoct_free(vpm);
+}
+
static void wctdm_initialize_vpm(struct wctdm *wc)
{
int res = 0;
if (!vpmsupport)
- goto cleanup;
+ return;
res = wctdm_initialize_vpmadt032(wc);
if (!res) {
@@ -4393,29 +4413,26 @@ static void wctdm_initialize_vpm(struct wctdm *wc)
if (!vpm) {
dev_info(&wc->vb.pdev->dev,
"Unable to allocate memory for struct vpmoct\n");
- goto cleanup;
+ return;
}
vpm->dev = &wc->vb.pdev->dev;
spin_lock_irqsave(&wc->reglock, flags);
wc->vpmoct = vpm;
+ wc->not_ready++;
spin_unlock_irqrestore(&wc->reglock, flags);
- if (!vpmoct_init(vpm)) {
- wc->ctlreg |= 0x10;
- return;
- } else {
+ res = vpmoct_init(vpm, wctdm_vpm_load_complete);
+ if (-EINVAL == res) {
spin_lock_irqsave(&wc->reglock, flags);
wc->vpmoct = NULL;
+ wc->not_ready--;
spin_unlock_irqrestore(&wc->reglock, flags);
vpmoct_free(vpm);
- goto cleanup;
}
}
-
-cleanup:
- dev_info(&wc->vb.pdev->dev, "VPM: Support Disabled\n");
+ return;
}
static void wctdm_identify_modules(struct wctdm *wc)
@@ -5214,7 +5231,7 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!wc)
return -ENOMEM;
- wc->initialized = 1;
+ wc->not_ready = 1;
down(&ifacelock);
/* \todo this is a candidate for removal... */
@@ -5460,7 +5477,7 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
- wc->initialized--;
+ wc->not_ready--;
dev_info(&wc->vb.pdev->dev,
"Found a %s: %s (%d BRI spans, %d analog %s)\n",
@@ -5531,38 +5548,51 @@ static void wctdm_release(struct wctdm *wc)
static void __devexit wctdm_remove_one(struct pci_dev *pdev)
{
- struct wctdm *wc = pci_get_drvdata(pdev);
- struct vpmadt032 *vpm = wc->vpmadt032;
int i;
+ unsigned long flags;
+ struct wctdm *wc = pci_get_drvdata(pdev);
+ struct vpmadt032 *vpmadt032;
+ struct vpmoct *vpmoct;
+ if (!wc)
+ return;
- if (wc) {
-
- remove_sysfs_files(wc);
+ vpmadt032 = wc->vpmadt032;
+ vpmoct = wc->vpmoct;
- if (vpm) {
- clear_bit(VPM150M_ACTIVE, &vpm->control);
- flush_scheduled_work();
- }
+ remove_sysfs_files(wc);
- /* shut down any BRI modules */
- for (i = 0; i < wc->mods_per_board; i += 4) {
- if (wc->mods[i].type == BRI)
- wctdm_unload_b400m(wc, i);
- }
+ if (vpmadt032) {
+ clear_bit(VPM150M_ACTIVE, &vpmadt032->control);
+ flush_scheduled_work();
+ } else if (vpmoct) {
+ while (wctdm_wait_for_ready(wc))
+ schedule();
+ }
- voicebus_stop(&wc->vb);
+ /* shut down any BRI modules */
+ for (i = 0; i < wc->mods_per_board; i += 4) {
+ if (wc->mods[i].type == BRI)
+ wctdm_unload_b400m(wc, i);
+ }
- if (vpm) {
- vpmadt032_free(wc->vpmadt032);
- wc->vpmadt032 = NULL;
- }
+ voicebus_stop(&wc->vb);
- dev_info(&wc->vb.pdev->dev, "Freed a %s\n",
- (is_hx8(wc)) ? "Hybrid card" : "Wildcard");
- /* Release span */
- wctdm_release(wc);
+ if (vpmadt032) {
+ vpmadt032_free(vpmadt032);
+ wc->vpmadt032 = NULL;
+ } else if (vpmoct) {
+ spin_lock_irqsave(&wc->reglock, flags);
+ wc->vpmoct = NULL;
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ vpmoct_free(vpmoct);
}
+
+ dev_info(&wc->vb.pdev->dev, "Freed a %s\n",
+ (is_hx8(wc)) ? "Hybrid card" : "Wildcard");
+
+ /* Release span */
+ wctdm_release(wc);
}
static DEFINE_PCI_DEVICE_TABLE(wctdm_pci_tbl) = {
diff --git a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
index 0f497aa..4ab313d 100644
--- a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
+++ b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
@@ -273,11 +273,17 @@ struct wctdm {
struct semaphore syncsem;
int oldsync;
- int initialized; /* 0 when the entire card is ready to go */
+ int not_ready; /* 0 when the entire card is ready to go */
unsigned long checkflag; /* Internal state flags and task bits */
int companding;
};
+static inline bool is_initialized(struct wctdm *wc)
+{
+ WARN_ON(wc->not_ready < 0);
+ return (wc->not_ready == 0);
+}
+
/* Atomic flag bits for checkflag field */
#define WCTDM_CHECK_TIMING 0
diff --git a/drivers/dahdi/wctdm24xxp/xhfc.c b/drivers/dahdi/wctdm24xxp/xhfc.c
index de6ad89..c5eb5a6 100644
--- a/drivers/dahdi/wctdm24xxp/xhfc.c
+++ b/drivers/dahdi/wctdm24xxp/xhfc.c
@@ -1160,7 +1160,7 @@ static int xhfc_find_sync_with_timingcable(struct b400m *b4)
}
for (j = 0; j < WC_MAX_IFACES && ifaces[j]; j++) {
- if (!ifaces[j]->initialized) {
+ if (is_initialized(ifaces[j])) {
set_bit(WCTDM_CHECK_TIMING, &wc->checkflag);
osrc = -2;
goto out;
@@ -2194,7 +2194,7 @@ int b400m_spanconfig(struct file *file, struct dahdi_span *span,
b4 = bspan->parent;
wc = b4->wc;
- if ((file->f_flags & O_NONBLOCK) && !wc->initialized)
+ if ((file->f_flags & O_NONBLOCK) && !is_initialized(wc))
return -EAGAIN;
res = wctdm_wait_for_ready(wc);
@@ -2271,7 +2271,7 @@ int b400m_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
struct b400m *b4 = bspan->parent;
int res;
- if ((file->f_flags & O_NONBLOCK) && !b4->wc->initialized)
+ if ((file->f_flags & O_NONBLOCK) && !is_initialized(b4->wc))
return -EAGAIN;
res = wctdm_wait_for_ready(b4->wc);
@@ -2395,7 +2395,7 @@ static void xhfc_work(struct work_struct *work)
int i, j, k, fifo;
unsigned char b, b2;
- if (b4->shutdown || !b4->wc->initialized)
+ if (b4->shutdown || !is_initialized(b4->wc))
return;
b4->irq_oview = b400m_getreg(b4, R_IRQ_OVIEW);
@@ -2518,7 +2518,7 @@ void wctdm_bri_checkisr(struct wctdm *wc, struct wctdm_module *const mod,
return;
/* DEFINITELY don't do anything if our structures aren't ready! */
- if (!wc->initialized || !b4 || !b4->inited)
+ if (!is_initialized(wc) || !b4 || !b4->inited)
return;
if (offset == 0) {