summaryrefslogtreecommitdiff
path: root/wctdm24xxp
diff options
context:
space:
mode:
authorkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-12-11 17:33:06 +0000
committerkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-12-11 17:33:06 +0000
commit4a14fd8f758435794c0d2487ef4939df2408e2f8 (patch)
treec9ca40e99dd405f8054af9297655ddc5d1559556 /wctdm24xxp
parent82c5ab2efe8798a7d54b5dd0fe44fbc1391d7e73 (diff)
Merged revisions 3430 via svnmerge from
https://origsvn.digium.com/svn/zaptel/branches/1.2 ........ r3430 | kpfleming | 2007-12-11 11:27:00 -0600 (Tue, 11 Dec 2007) | 4 lines coding guidelines cleanup report results of failure to initialize a VPMADT032 module all the way up the process, so that a card with a failed VPM won't be left in a partially-operational state clean up early exits from wctdm_init_one() to undo all previously completed steps ........ git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@3431 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wctdm24xxp')
-rw-r--r--wctdm24xxp/base.c275
1 files changed, 153 insertions, 122 deletions
diff --git a/wctdm24xxp/base.c b/wctdm24xxp/base.c
index 1b6a20e..14dabe3 100644
--- a/wctdm24xxp/base.c
+++ b/wctdm24xxp/base.c
@@ -3595,12 +3595,20 @@ static int vpm150m_config_hw(struct wctdm *wc)
}
#endif /* VPM150M_SUPPORT */
-static void wctdm_vpm150m_init(struct wctdm *wc)
+enum vpmadt032_init_result {
+ VPMADT032_SUCCESS,
+ VPMADT032_NOT_FOUND,
+ VPMADT032_FAILED,
+ VPMADT032_DISABLED,
+};
+
+static enum vpmadt032_init_result wctdm_vpm150m_init(struct wctdm *wc)
{
unsigned short i;
struct vpm150m *vpm150m;
unsigned short reg;
unsigned long flags;
+ enum vpmadt032_init_result res = VPMADT032_FAILED;
#ifdef VPM150M_SUPPORT
struct wctdm_firmware fw;
@@ -3619,14 +3627,14 @@ static void wctdm_vpm150m_init(struct wctdm *wc)
if (!vpmsupport) {
printk("VPM: Support Disabled\n");
wc->vpm150m = NULL;
- return;
+ return VPMADT032_DISABLED;
}
vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL);
if (!vpm150m) {
printk("Unable to allocate VPM150M!\n");
- return;
+ return VPMADT032_FAILED;
}
memset(vpm150m, 0, sizeof(struct vpm150m));
@@ -3660,6 +3668,7 @@ static void wctdm_vpm150m_init(struct wctdm *wc)
if (reg != i) {
if (debug & DEBUG_ECHOCAN)
printk("Failed: Sent %x != %x VPMADT032 Failed HI page test\n", i, reg);
+ res = VPMADT032_NOT_FOUND;
goto failed_exit;
}
}
@@ -3707,7 +3716,7 @@ static void wctdm_vpm150m_init(struct wctdm *wc)
if ((request_firmware(&firmware, vpmadt032_firmware, &wc->dev->dev) != 0) ||
!firmware) {
printk("VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware);
- return;
+ goto failed_exit;
}
#else
embedded_firmware.data = _binary_zaptel_fw_vpmadt032_bin_start;
@@ -3760,7 +3769,7 @@ static void wctdm_vpm150m_init(struct wctdm *wc)
goto failed_exit;
}
- return;
+ return VPMADT032_SUCCESS;
#endif /* VPM150M_SUPPORT */
failed_exit:
@@ -3769,7 +3778,7 @@ failed_exit:
spin_unlock_irqrestore(&wc->reglock, flags);
kfree(vpm150m);
- return;
+ return res;
}
static void wctdm_vpm_set_dtmf_threshold(struct wctdm *wc, unsigned int threshold)
@@ -3920,7 +3929,7 @@ static void wctdm_vpm_init(struct wctdm *wc)
#endif
-static void wctdm_locate_modules(struct wctdm *wc)
+static int wctdm_locate_modules(struct wctdm *wc)
{
int x;
unsigned long flags;
@@ -4040,138 +4049,160 @@ retry:
for (x = NUM_CARDS; x < NUM_CARDS + NUM_EC; x++)
wc->modtype[x] = MOD_TYPE_NONE;
spin_unlock_irqrestore(&wc->reglock, flags);
- wctdm_vpm150m_init(wc);
- if (wc->vpm150m) {
+ switch (wctdm_vpm150m_init(wc)) {
+ case VPMADT032_SUCCESS:
printk("VPMADT032: Present and operational (Firmware version %x)\n", wc->vpm150m->version);
wc->ctlreg |= 0x10;
+ break;
+ case VPMADT032_DISABLED:
+ case VPMADT032_NOT_FOUND:
+ /* nothing */
+ break;
+ default:
+ return -1;
}
}
#endif
+
+ return 0;
}
static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- int res;
struct wctdm *wc;
struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data;
int x;
int y;
- if (pci_enable_device(pdev)) {
- res = -EIO;
- } else {
- wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL);
- if (wc) {
- spin_lock(&ifacelock);
- for (x = 0; x < WC_MAX_IFACES; x++)
- if (!ifaces[x]) break;
-
- ifaces[x] = wc;
- spin_unlock(&ifacelock);
-
- memset(wc, 0, sizeof(struct wctdm));
- spin_lock_init(&wc->reglock);
- wc->curcard = -1;
- wc->cards = NUM_CARDS;
- wc->iobase = pci_resource_start(pdev, 0);
- wc->type = d->ports;
- wc->dev = pdev;
- wc->pos = x;
- wc->variety = d->name;
- for (y=0;y<NUM_CARDS;y++) {
- wc->flags[y] = d->flags;
- wc->dacssrc[y] = -1;
- }
- /* Keep track of whether we need to free the region */
- if (request_region(wc->iobase, 0xff, "wctdm24xxp"))
- wc->freeregion = 1;
-
- /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses
- 32 bits. Allocate an extra set just for control too */
- wc->writechunk = pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma);
- if (!wc->writechunk) {
- printk("wctdm: Unable to allocate DMA-able memory\n");
- if (wc->freeregion)
- release_region(wc->iobase, 0xff);
- return -ENOMEM;
- }
-
- wc->readchunk = wc->writechunk + SFRAME_SIZE / 2; /* in doublewords */
- wc->readdma = wc->writedma + SFRAME_SIZE * 2; /* in bytes */
-
- wc->descripchunk = wc->readchunk + SFRAME_SIZE / 2; /* in doublewords */
- wc->descripdma = wc->readdma + SFRAME_SIZE * 2; /* in bytes */
-
- /* Initialize Write/Buffers to all blank data */
- memset((void *)wc->writechunk,0x00, SFRAME_SIZE * 2);
- memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2);
-
- init_waitqueue_head(&wc->regq);
-
- if (wctdm_initialize(wc)) {
- printk("%s: Unable to register span with zaptel\n", wc->variety);
- /* Set Reset Low */
- wctdm_stop_dma(wc);
- /* Free Resources */
- free_irq(pdev->irq, wc);
- if (wc->freeregion)
- release_region(wc->iobase, 0xff);
- pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
- kfree(wc);
- return -EIO;
- }
-
- /* Enable bus mastering */
- pci_set_master(pdev);
-
- /* Keep track of which device we are */
- pci_set_drvdata(pdev, wc);
+ if (pci_enable_device(pdev))
+ return -EIO;
- if (request_irq(pdev->irq, wctdm_interrupt, ZAP_IRQ_SHARED, wc->variety, wc)) {
- printk("wctdm24xxp: Unable to request IRQ %d\n", pdev->irq);
- if (wc->freeregion)
- release_region(wc->iobase, 0xff);
- pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
- pci_set_drvdata(pdev, NULL);
- kfree(wc);
- return -EIO;
- }
-
-
- if (wctdm_hardware_init(wc)) {
- /* Set Reset Low */
- wctdm_stop_dma(wc);
- /* Free Resources */
- free_irq(pdev->irq, wc);
- if (wc->freeregion)
- release_region(wc->iobase, 0xff);
- pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
- pci_set_drvdata(pdev, NULL);
- zt_unregister(&wc->span);
- kfree(wc);
- return -EIO;
-
- }
+ if (!(wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL)))
+ return -ENOMEM;
-
- /* Enable interrupts */
- wctdm_enable_interrupts(wc);
-
- /* Start DMA */
- wctdm_start_dma(wc);
-
- /* Now track down what modules are installed */
- wctdm_locate_modules(wc);
-
- /* Final initialization */
- wctdm_post_initialize(wc);
-
- printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->type);
- res = 0;
- } else
- res = -ENOMEM;
+ spin_lock(&ifacelock);
+ for (x = 0; x < WC_MAX_IFACES; x++)
+ if (!ifaces[x]) break;
+
+ ifaces[x] = wc;
+ spin_unlock(&ifacelock);
+
+ memset(wc, 0, sizeof(struct wctdm));
+ spin_lock_init(&wc->reglock);
+ wc->curcard = -1;
+ wc->cards = NUM_CARDS;
+ wc->iobase = pci_resource_start(pdev, 0);
+ wc->type = d->ports;
+ wc->dev = pdev;
+ wc->pos = x;
+ wc->variety = d->name;
+ for (y=0;y<NUM_CARDS;y++) {
+ wc->flags[y] = d->flags;
+ wc->dacssrc[y] = -1;
}
- return res;
+ /* Keep track of whether we need to free the region */
+ if (request_region(wc->iobase, 0xff, "wctdm24xxp"))
+ wc->freeregion = 1;
+
+ /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses
+ 32 bits. Allocate an extra set just for control too */
+ wc->writechunk = pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma);
+ if (!wc->writechunk) {
+ printk("wctdm: Unable to allocate DMA-able memory\n");
+ if (wc->freeregion)
+ release_region(wc->iobase, 0xff);
+ return -ENOMEM;
+ }
+
+ wc->readchunk = wc->writechunk + SFRAME_SIZE / 2; /* in doublewords */
+ wc->readdma = wc->writedma + SFRAME_SIZE * 2; /* in bytes */
+
+ wc->descripchunk = wc->readchunk + SFRAME_SIZE / 2; /* in doublewords */
+ wc->descripdma = wc->readdma + SFRAME_SIZE * 2; /* in bytes */
+
+ /* Initialize Write/Buffers to all blank data */
+ memset((void *)wc->writechunk,0x00, SFRAME_SIZE * 2);
+ memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2);
+
+ init_waitqueue_head(&wc->regq);
+
+ if (wctdm_initialize(wc)) {
+ printk("%s: Unable to register span with zaptel\n", wc->variety);
+ /* Set Reset Low */
+ wctdm_stop_dma(wc);
+ /* Free Resources */
+ if (wc->freeregion)
+ release_region(wc->iobase, 0xff);
+ pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
+ zt_unregister(&wc->span);
+ kfree(wc);
+ return -EIO;
+ }
+
+ /* Enable bus mastering */
+ pci_set_master(pdev);
+
+ /* Keep track of which device we are */
+ pci_set_drvdata(pdev, wc);
+
+ if (request_irq(pdev->irq, wctdm_interrupt, ZAP_IRQ_SHARED, wc->variety, wc)) {
+ printk("wctdm24xxp: Unable to request IRQ %d\n", pdev->irq);
+ /* Set Reset Low */
+ wctdm_stop_dma(wc);
+ /* Free Resources */
+ if (wc->freeregion)
+ release_region(wc->iobase, 0xff);
+ pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
+ pci_set_drvdata(pdev, NULL);
+ zt_unregister(&wc->span);
+ kfree(wc);
+ return -EIO;
+ }
+
+
+ if (wctdm_hardware_init(wc)) {
+ /* Set Reset Low */
+ wctdm_stop_dma(wc);
+ /* Free Resources */
+ free_irq(pdev->irq, wc);
+ if (wc->freeregion)
+ release_region(wc->iobase, 0xff);
+ pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
+ pci_set_drvdata(pdev, NULL);
+ zt_unregister(&wc->span);
+ kfree(wc);
+ return -EIO;
+
+ }
+
+ /* Enable interrupts */
+ wctdm_enable_interrupts(wc);
+
+ /* Start DMA */
+ wctdm_start_dma(wc);
+
+ /* Now track down what modules are installed */
+ if (wctdm_locate_modules(wc)) {
+ wctdm_disable_interrupts(wc);
+ /* Set Reset Low */
+ wctdm_stop_dma(wc);
+ /* Free Resources */
+ free_irq(pdev->irq, wc);
+ if (wc->freeregion)
+ release_region(wc->iobase, 0xff);
+ pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
+ pci_set_drvdata(pdev, NULL);
+ zt_unregister(&wc->span);
+ kfree(wc);
+ return -EIO;
+ }
+
+ /* Final initialization */
+ wctdm_post_initialize(wc);
+
+ printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->type);
+
+ return 0;
}
static void wctdm_release(struct wctdm *wc)