summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2011-10-26 18:58:14 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2011-10-26 18:58:14 +0000
commit003582d221276735233c1155d5d64e3ee7eec4ac (patch)
tree66494feaba4f8cec822069d61c1ff46f136764ca
parent2ee9529e22a0c0ba57f01afebe86cdf2e6c72566 (diff)
dahdi: Register devices instead of individual spans.
Increasingly, spans are implemented by devices that support more than a single span. Introduce a 'struct dahdi_device' object which explicitly contains multiple spans. This will allow a cleaner representation of spans and devices in sysfs since order of arrival will not determine the layout of the devices. This also gives the core of dahdi a way to know the relationship between spans. This generalizes similar concepts that were previously xpp specific. The conversion of the xpp code was almost entirely done by Oron and Tzafrir. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Signed-off-by: Oron Peled <oron.peled@xorcom.com> Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10273 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/dahdi-base.c229
-rw-r--r--drivers/dahdi/dahdi_dynamic.c10
-rw-r--r--drivers/dahdi/pciradio.c7
-rw-r--r--drivers/dahdi/tor2.c42
-rw-r--r--drivers/dahdi/voicebus/voicebus.c2
-rw-r--r--drivers/dahdi/wcb4xxp/base.c44
-rw-r--r--drivers/dahdi/wcb4xxp/wcb4xxp.h1
-rw-r--r--drivers/dahdi/wcfxo.c26
-rw-r--r--drivers/dahdi/wct1xxp.c22
-rw-r--r--drivers/dahdi/wct4xxp/base.c124
-rw-r--r--drivers/dahdi/wctdm.c38
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c116
-rw-r--r--drivers/dahdi/wctdm24xxp/wctdm24xxp.h1
-rw-r--r--drivers/dahdi/wcte11xp.c23
-rw-r--r--drivers/dahdi/wcte12xp/base.c121
-rw-r--r--drivers/dahdi/wcte12xp/wcte12xp.h8
-rw-r--r--drivers/dahdi/xpp/xbus-core.c87
-rw-r--r--drivers/dahdi/xpp/xbus-core.h1
-rw-r--r--drivers/dahdi/xpp/xbus-sysfs.c25
-rw-r--r--drivers/dahdi/xpp/xpp_dahdi.c230
-rw-r--r--drivers/dahdi/xpp/xpp_dahdi.h7
-rw-r--r--include/dahdi/kernel.h44
22 files changed, 725 insertions, 483 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c
index 80eea41..825d1c4 100644
--- a/drivers/dahdi/dahdi-base.c
+++ b/drivers/dahdi/dahdi-base.c
@@ -108,8 +108,6 @@
EXPORT_SYMBOL(dahdi_transcode_fops);
EXPORT_SYMBOL(dahdi_init_tone_state);
EXPORT_SYMBOL(dahdi_mf_tone);
-EXPORT_SYMBOL(dahdi_register);
-EXPORT_SYMBOL(dahdi_unregister);
EXPORT_SYMBOL(__dahdi_mulaw);
EXPORT_SYMBOL(__dahdi_alaw);
#ifdef CONFIG_CALC_XLAW
@@ -399,7 +397,7 @@ __for_each_channel(unsigned long (*func)(struct dahdi_chan *chan,
struct dahdi_span *s;
struct pseudo_chan *pseudo;
- list_for_each_entry(s, &span_list, node) {
+ list_for_each_entry(s, &span_list, spans_node) {
unsigned long x;
for (x = 0; x < s->channels; x++) {
struct dahdi_chan *const chan = s->chans[x];
@@ -439,7 +437,7 @@ static struct dahdi_chan *_chan_from_num(unsigned int channo)
/* When searching for the channel amongst the spans, we can use the
* fact that channels on a span must be numbered consecutively to skip
* checking each individual channel. */
- list_for_each_entry(s, &span_list, node) {
+ list_for_each_entry(s, &span_list, spans_node) {
unsigned int basechan;
struct dahdi_chan *chan;
@@ -488,7 +486,7 @@ static inline struct dahdi_chan *chan_from_file(struct file *file)
static struct dahdi_span *_find_span(int spanno)
{
struct dahdi_span *s;
- list_for_each_entry(s, &span_list, node) {
+ list_for_each_entry(s, &span_list, spans_node) {
if (s->spanno == spanno) {
return s;
}
@@ -526,7 +524,7 @@ static unsigned int span_count(void)
struct dahdi_span *s;
unsigned long flags;
spin_lock_irqsave(&chan_lock, flags);
- list_for_each_entry(s, &span_list, node)
+ list_for_each_entry(s, &span_list, spans_node)
++count;
spin_unlock_irqrestore(&chan_lock, flags);
return count;
@@ -3043,6 +3041,16 @@ static int can_open_timer(void)
static unsigned int max_pseudo_channels = 512;
static unsigned int num_pseudo_channels;
+static int pinned_spans = 1;
+
+/**
+ * dahdi_alloc_pseudo() - Returns a new pseudo channel.
+ *
+ * Call with the registration_mutex held since this function will determine a
+ * channel number, and must be protected from additional registrations while
+ * that is happening.
+ *
+ */
static struct dahdi_chan *dahdi_alloc_pseudo(struct file *file)
{
struct pseudo_chan *pseudo;
@@ -3068,8 +3076,6 @@ static struct dahdi_chan *dahdi_alloc_pseudo(struct file *file)
pseudo->chan.flags = DAHDI_FLAG_AUDIO;
pseudo->chan.span = NULL; /* No span == psuedo channel */
- mutex_lock(&registration_mutex);
-
channo = FIRST_PSEUDO_CHANNEL;
list_for_each_entry(p, &pseudo_chans, node) {
if (channo != p->chan.channo)
@@ -3094,8 +3100,6 @@ static struct dahdi_chan *dahdi_alloc_pseudo(struct file *file)
list_add(&pseudo->node, pos);
spin_unlock_irqrestore(&chan_lock, flags);
- mutex_unlock(&registration_mutex);
-
return &pseudo->chan;
}
@@ -3159,7 +3163,9 @@ static int dahdi_open(struct inode *inode, struct file *file)
if (unit == DAHDI_CHANNEL)
return dahdi_chan_open(file);
if (unit == DAHDI_PSEUDO) {
+ mutex_lock(&registration_mutex);
chan = dahdi_alloc_pseudo(file);
+ mutex_unlock(&registration_mutex);
if (unlikely(!chan))
return -ENOMEM;
return dahdi_specchan_open(file);
@@ -3719,7 +3725,7 @@ static void __dahdi_find_master_span(void)
spin_lock_irqsave(&chan_lock, flags);
old_master = master;
- list_for_each_entry(s, &span_list, node) {
+ list_for_each_entry(s, &span_list, spans_node) {
if (s->alarms)
continue;
if (dahdi_is_digital_span(s) &&
@@ -4241,16 +4247,18 @@ static int dahdi_ioctl_spanstat(struct file *file, unsigned long data)
spaninfo.linecompat = s->linecompat;
strlcpy(spaninfo.lboname, dahdi_lboname(s->lbo),
sizeof(spaninfo.lboname));
- if (s->manufacturer) {
- strlcpy(spaninfo.manufacturer, s->manufacturer,
- sizeof(spaninfo.manufacturer));
+ if (s->parent->manufacturer) {
+ strlcpy(spaninfo.manufacturer, s->parent->manufacturer,
+ sizeof(spaninfo.manufacturer));
+ }
+ if (s->parent->devicetype) {
+ strlcpy(spaninfo.devicetype, s->parent->devicetype,
+ sizeof(spaninfo.devicetype));
}
- if (s->devicetype) {
- strlcpy(spaninfo.devicetype, s->devicetype,
- sizeof(spaninfo.devicetype));
+ if (s->parent->location) {
+ strlcpy(spaninfo.location, s->parent->location,
+ sizeof(spaninfo.location));
}
- strlcpy(spaninfo.location, s->location,
- sizeof(spaninfo.location));
if (s->spantype) {
strlcpy(spaninfo.spantype, s->spantype,
sizeof(spaninfo.spantype));
@@ -4328,21 +4336,18 @@ static int dahdi_ioctl_spanstat_v1(struct file *file, unsigned long data)
dahdi_lboname(s->lbo),
sizeof(spaninfo_v1.lboname));
- if (s->manufacturer) {
- strlcpy(spaninfo_v1.manufacturer,
- s->manufacturer,
+ if (s->parent->manufacturer) {
+ strlcpy(spaninfo_v1.manufacturer, s->parent->manufacturer,
sizeof(spaninfo_v1.manufacturer));
}
- if (s->devicetype) {
- strlcpy(spaninfo_v1.devicetype,
- s->devicetype,
- sizeof(spaninfo_v1.devicetype));
+ if (s->parent->devicetype) {
+ strlcpy(spaninfo_v1.devicetype, s->parent->devicetype,
+ sizeof(spaninfo_v1.devicetype));
}
- strlcpy(spaninfo_v1.location,
- s->location,
- sizeof(spaninfo_v1.location));
+ strlcpy(spaninfo_v1.location, s->parent->location,
+ sizeof(spaninfo_v1.location));
if (s->spantype) {
strlcpy(spaninfo_v1.spantype,
@@ -5399,7 +5404,7 @@ static int dahdi_ioctl_confdiag(struct file *file, unsigned long data)
struct pseudo_chan *pseudo;
c = 0;
spin_lock_irqsave(&chan_lock, flags);
- list_for_each_entry(s, &span_list, node) {
+ list_for_each_entry(s, &span_list, spans_node) {
int k;
for (k = 0; k < s->channels; k++) {
chan = s->chans[k];
@@ -6610,9 +6615,9 @@ static long dahdi_ioctl_compat(struct file *file, unsigned int cmd,
*/
static int _get_next_channo(const struct dahdi_span *span)
{
- const struct list_head *pos = &span->node;
+ const struct list_head *pos = &span->spans_node;
while (pos != &span_list) {
- span = list_entry(pos, struct dahdi_span, node);
+ span = list_entry(pos, struct dahdi_span, spans_node);
if (span->channels)
return span->chans[0]->channo;
pos = pos->next;
@@ -6636,10 +6641,10 @@ static struct list_head *_find_spanno_and_channo(const struct dahdi_span *span,
*spanno = 1;
*channo = 1;
- list_for_each_entry(pos, &span_list, node) {
+ list_for_each_entry(pos, &span_list, spans_node) {
bool skip_span;
- loc = &pos->node;
+ loc = &pos->spans_node;
next_channo = _get_next_channo(pos);
skip_span = (pos->spanno == *spanno) ||
@@ -6658,13 +6663,39 @@ static struct list_head *_find_spanno_and_channo(const struct dahdi_span *span,
return loc;
}
+struct dahdi_device *dahdi_create_device(void)
+{
+ struct dahdi_device *ddev;
+ ddev = kzalloc(sizeof(*ddev), GFP_KERNEL);
+ if (!ddev)
+ return NULL;
+ return ddev;
+}
+EXPORT_SYMBOL(dahdi_create_device);
+
+void dahdi_free_device(struct dahdi_device *ddev)
+{
+ kfree(ddev);
+}
+EXPORT_SYMBOL(dahdi_free_device);
+
/**
- * _dahdi_register - Register the span.
+ * _dahdi_register_span() - Register a new DAHDI span
+ * @span: the DAHDI span
+ * @prefmaster: will the new span be preferred as a master?
+ *
+ * Registers a span for usage with DAHDI. All the channel numbers in it
+ * will get the lowest available channel numbers.
+ *
+ * If prefmaster is set to anything > 0, span will attempt to become the
+ * master DAHDI span at registration time. If 0: it will only become
+ * master if no other span is currently the master (i.e.: it is the
+ * first one).
*
- * NOTE: Must be called with the registration_mutex held.
+ * Must be called with registration_mutex held.
*
*/
-static int _dahdi_register(struct dahdi_span *span, int prefmaster)
+static int _dahdi_register_span(struct dahdi_span *span, int prefmaster)
{
unsigned int spanno;
unsigned int x;
@@ -6689,7 +6720,7 @@ static int _dahdi_register(struct dahdi_span *span, int prefmaster)
span->deflaw = DAHDI_LAW_MULAW;
}
-
+ INIT_LIST_HEAD(&span->spans_node);
spin_lock_init(&span->lock);
/* Look through the span list to find the first available span number.
@@ -6735,9 +6766,9 @@ static int _dahdi_register(struct dahdi_span *span, int prefmaster)
spin_lock_irqsave(&chan_lock, flags);
if (loc == &span_list)
- list_add_tail(&span->node, &span_list);
+ list_add_tail(&span->spans_node, &span_list);
else
- list_add(&span->node, loc);
+ list_add(&span->spans_node, loc);
spin_unlock_irqrestore(&chan_lock, flags);
set_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
__dahdi_find_master_span();
@@ -6762,30 +6793,71 @@ cleanup:
return res;
}
+static const char *UNKNOWN = "";
+
/**
- * dahdi_register() - unregister a new DAHDI span
- * @span: the DAHDI span
- * @prefmaster: will the new span be preferred as a master?
+ * _dahdi_register_device - Registers the spans of a DAHDI device.
+ * @ddev: the DAHDI device
*
- * Registers a span for usage with DAHDI. All the channel numbers in it
- * will get the lowest available channel numbers.
+ * If pinned_spans is defined add the device to the device list and wait for
+ * userspace to finish registration. Otherwise, go ahead and register the
+ * spans in order as was done historically since the beginning of the zaptel
+ * days.
*
- * If prefmaster is set to anything > 0, span will attempt to become the
- * master DAHDI span at registration time. If 0: it will only become
- * master if no other span is currently the master (i.e.: it is the
- * first one).
+ * Must hold registration_mutex when this function is called.
+ *
+ */
+static int _dahdi_register_device(struct dahdi_device *ddev,
+ struct device *parent)
+{
+ struct dahdi_span *s;
+ int ret = 0;
+
+ ddev->manufacturer = (ddev->manufacturer) ?: UNKNOWN;
+ ddev->location = (ddev->location) ?: UNKNOWN;
+ ddev->devicetype = (ddev->devicetype) ?: UNKNOWN;
+
+ list_for_each_entry(s, &ddev->spans, device_node) {
+ s->parent = ddev;
+ ret = _dahdi_register_span(s, 1);
+ }
+
+ return ret;
+}
+
+/**
+ * dahdi_register_device() - unregister a new DAHDI device
+ * @ddev: the DAHDI device
+ *
+ * Registers a device for usage with DAHDI.
*
*/
-int dahdi_register(struct dahdi_span *span, int prefmaster)
+int dahdi_register_device(struct dahdi_device *ddev, struct device *parent)
{
int ret;
+
+ if (!ddev)
+ return -EINVAL;
+
mutex_lock(&registration_mutex);
- ret = _dahdi_register(span, prefmaster);
+ ret = _dahdi_register_device(ddev, parent);
mutex_unlock(&registration_mutex);
+
return ret;
}
+EXPORT_SYMBOL(dahdi_register_device);
-static int _dahdi_unregister(struct dahdi_span *span)
+/**
+ * _dahdi_unregister_span() - unregister a DAHDI span
+ * @span: the DAHDI span
+ *
+ * Unregisters a span that has been previously registered with
+ * dahdi_register_span().
+ *
+ * Must be called with the registration_mutex held.
+ *
+ */
+static int _dahdi_unregister_span(struct dahdi_span *span)
{
int x;
struct dahdi_span *new_master, *s;
@@ -6797,7 +6869,7 @@ static int _dahdi_unregister(struct dahdi_span *span)
}
spin_lock_irqsave(&chan_lock, flags);
- list_del_init(&span->node);
+ list_del_init(&span->spans_node);
spin_unlock_irqrestore(&chan_lock, flags);
span->spanno = 0;
clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
@@ -6822,7 +6894,7 @@ static int _dahdi_unregister(struct dahdi_span *span)
new_master = NULL;
spin_lock_irqsave(&chan_lock, flags);
- list_for_each_entry(s, &span_list, node) {
+ list_for_each_entry(s, &span_list, spans_node) {
if ((s == new_master) || !can_provide_timing(s))
continue;
new_master = s;
@@ -6839,21 +6911,45 @@ static int _dahdi_unregister(struct dahdi_span *span)
return 0;
}
+int dahdi_unregister_span(struct dahdi_span *span)
+{
+ module_printk(KERN_NOTICE, "%s: %s\n", __func__, span->name);
+ mutex_lock(&registration_mutex);
+ _dahdi_unregister_span(span);
+ list_del_init(&span->device_node);
+ mutex_unlock(&registration_mutex);
+ return 0;
+}
+
/**
- * dahdi_unregister() - unregister a DAHDI span
+ * dahdi_unregister_device() - unregister a DAHDI device
* @span: the DAHDI span
*
- * Unregisters a span that has been previously registered with
- * dahdi_register().
+ * Unregisters a device that has been previously registered with
+ * dahdi_register_device().
+ *
*/
-int dahdi_unregister(struct dahdi_span *span)
+void dahdi_unregister_device(struct dahdi_device *ddev)
{
- int ret;
+ struct dahdi_span *s;
+ WARN_ON(!ddev);
+ might_sleep();
+ if (unlikely(!ddev))
+ return;
+
mutex_lock(&registration_mutex);
- ret = _dahdi_unregister(span);
+ list_for_each_entry(s, &ddev->spans, device_node)
+ _dahdi_unregister_span(s);
mutex_unlock(&registration_mutex);
- return ret;
+
+ if (UNKNOWN == ddev->location)
+ ddev->location = NULL;
+ if (UNKNOWN == ddev->manufacturer)
+ ddev->manufacturer = NULL;
+ if (UNKNOWN == ddev->devicetype)
+ ddev->devicetype = NULL;
}
+EXPORT_SYMBOL(dahdi_unregister_device);
/*
** This routine converts from linear to ulaw
@@ -9152,7 +9248,7 @@ static void _process_masterspan(void)
/* Process any timers */
process_timers();
- list_for_each_entry(s, &span_list, node) {
+ list_for_each_entry(s, &span_list, spans_node) {
for (x = 0; x < s->channels; ++x) {
struct dahdi_chan *const chan = s->chans[x];
if (!chan->confmode)
@@ -9181,7 +9277,7 @@ static void _process_masterspan(void)
pseudo_rx_audio(&pseudo->chan);
}
- list_for_each_entry(s, &span_list, node) {
+ list_for_each_entry(s, &span_list, spans_node) {
for (x = 0; x < s->channels; x++) {
struct dahdi_chan *const chan = s->chans[x];
if (!chan->confmode)
@@ -9452,6 +9548,11 @@ MODULE_PARM_DESC(max_pseudo_channels, "Maximum number of pseudo channels.");
module_param(hwec_overrides_swec, int, 0644);
MODULE_PARM_DESC(hwec_overrides_swec, "When true, a hardware echo canceller is used instead of configured SWEC.");
+module_param(pinned_spans, int, 0644);
+MODULE_PARM_DESC(pinned_spans, "If 1, span/channel numbers can be statically "
+ "defined. If 0, spans/channels are numbered in first come "
+ "first serve order. Default 1");
+
static const struct file_operations dahdi_fops = {
.owner = THIS_MODULE,
.open = dahdi_open,
@@ -9494,7 +9595,7 @@ static void watchdog_check(unsigned long ignored)
struct dahdi_span *s;
spin_lock_irqsave(&span_list_lock, flags);
- list_for_each_entry(s, &span_list, node) {
+ list_for_each_entry(s, &span_list, spans_node) {
if (s->flags & DAHDI_FLAG_RUNNING) {
if (s->watchcounter == DAHDI_WATCHDOG_INIT) {
/* Whoops, dead card */
diff --git a/drivers/dahdi/dahdi_dynamic.c b/drivers/dahdi/dahdi_dynamic.c
index 20d7246..cbcdce7 100644
--- a/drivers/dahdi/dahdi_dynamic.c
+++ b/drivers/dahdi/dahdi_dynamic.c
@@ -400,6 +400,7 @@ static void dahdi_dynamic_release(struct kref *kref)
for (x = 0; x < d->span.channels; x++)
kfree(d->chans[x]);
+ dahdi_free_device(d->ddev);
kfree(d);
}
@@ -469,7 +470,7 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
return -EBUSY;
}
- dahdi_unregister(&d->span);
+ dahdi_unregister_device(d->ddev);
spin_lock_irqsave(&dspan_lock, flags);
list_del_rcu(&d->list);
@@ -578,8 +579,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
d = kzalloc(sizeof(*d), GFP_KERNEL);
if (!d)
return -ENOMEM;
-
kref_init(&d->kref);
+ d->ddev = dahdi_create_device();
for (x = 0; x < dds->numchans; x++) {
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
@@ -657,8 +658,9 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
return res;
}
+ list_add_tail(&d->span.device_node, &d->ddev->spans);
/* Whee! We're created. Now register the span */
- if (dahdi_register(&d->span, 0)) {
+ if (dahdi_register_device(d->ddev, d->dev)) {
printk(KERN_NOTICE "Unable to register span '%s'\n",
d->span.name);
dynamic_put(d);
@@ -769,7 +771,7 @@ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri)
WARN_ON(1);
}
}
- dahdi_unregister(&d->span);
+ dahdi_unregister_device(d->ddev);
spin_lock_irqsave(&dspan_lock, flags);
list_del_rcu(&d->list);
spin_unlock_irqrestore(&dspan_lock, flags);
diff --git a/drivers/dahdi/pciradio.c b/drivers/dahdi/pciradio.c
index e6ff52e..0384908 100644
--- a/drivers/dahdi/pciradio.c
+++ b/drivers/dahdi/pciradio.c
@@ -146,6 +146,7 @@ struct encdec
struct pciradio {
struct pci_dev *dev;
+ struct dahdi_device *ddev;
struct dahdi_span span;
unsigned char ios;
int usecount;
@@ -1488,7 +1489,7 @@ static int pciradio_initialize(struct pciradio *rad)
rad->span.flags = DAHDI_FLAG_RBS;
rad->span.ops = &pciradio_span_ops;
- if (dahdi_register(&rad->span, 0)) {
+ if (dahdi_register_device(rad->ddev, &rad->dev->dev)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
return -1;
}
@@ -1777,7 +1778,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
release_region(rad->ioaddr, 0xff);
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma);
pci_set_drvdata(pdev, NULL);
- dahdi_unregister(&rad->span);
+ dahdi_free_device(rad->ddev);
kfree(rad);
return -EIO;
@@ -1810,7 +1811,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
static void pciradio_release(struct pciradio *rad)
{
- dahdi_unregister(&rad->span);
+ dahdi_unregister_device(rad->ddev);
if (rad->freeregion)
release_region(rad->ioaddr, 0xff);
kfree(rad);
diff --git a/drivers/dahdi/tor2.c b/drivers/dahdi/tor2.c
index 969f569..6fc8930 100644
--- a/drivers/dahdi/tor2.c
+++ b/drivers/dahdi/tor2.c
@@ -97,6 +97,7 @@ struct tor2 {
unsigned long xilinx8_region; /* 8 bit Region allocated to Xilinx */
unsigned long xilinx8_len; /* Length of 8 bit Xilinx region */
__iomem volatile unsigned char *mem8; /* Virtual representation of 8 bit Xilinx memory area */
+ struct dahdi_device *ddev;
struct tor2_span tspans[SPANS_PER_CARD]; /* Span data */
struct dahdi_chan **chans[SPANS_PER_CARD]; /* Pointers to card channels */
struct tor2_chan tchans[32 * SPANS_PER_CARD]; /* Channel user data */
@@ -285,10 +286,6 @@ static void init_spans(struct tor2 *tor)
snprintf(s->desc, sizeof(s->desc) - 1,
"Tormenta 2 (PCI) Quad %s Card %d Span %d",
(tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1);
- s->manufacturer = "Digium";
- strlcpy(s->devicetype, tor->type, sizeof(s->devicetype));
- snprintf(s->location, sizeof(s->location) - 1,
- "PCI Bus %02d Slot %02d", tor->pci->bus->number, PCI_SLOT(tor->pci->devfn) + 1);
if (tor->cardtype == TYPE_T1) {
s->channels = 24;
s->deflaw = DAHDI_LAW_MULAW;
@@ -322,19 +319,31 @@ static void init_spans(struct tor2 *tor)
static int __devinit tor2_launch(struct tor2 *tor)
{
+ int res;
struct dahdi_span *s;
int i;
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &tor->tspans[0].dahdi_span.flags))
return 0;
+ tor->ddev = dahdi_create_device();
+ tor->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
+ tor->pci->bus->number,
+ PCI_SLOT(tor->pci->devfn) + 1);
+
+ if (!tor->ddev->location)
+ return -ENOMEM;
+
printk(KERN_INFO "Tor2: Launching card: %d\n", tor->order);
for (i = 0; i < SPANS_PER_CARD; ++i) {
s = &tor->tspans[i].dahdi_span;
- if (dahdi_register(s, 0)) {
- printk(KERN_ERR "Unable to register span %s\n", s->name);
- goto error_exit;
- }
+ list_add_tail(&s->device_node, &tor->ddev->spans);
+ }
+
+ res = dahdi_register_device(tor->ddev, &tor->pci->dev);
+ if (res) {
+ dev_err(&tor->pci->dev, "Unable to register with DAHDI.\n");
+ return res;
}
writew(PLX_INTENA, &tor->plx[INTCSR]); /* enable PLX interrupt */
@@ -342,14 +351,6 @@ static int __devinit tor2_launch(struct tor2 *tor)
tasklet_init(&tor->tor2_tlet, tor2_tasklet, (unsigned long)tor);
#endif
return 0;
-
-error_exit:
- for (i = 0; i < SPANS_PER_CARD; ++i) {
- s = &tor->tspans[i].dahdi_span;
- if (test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
- dahdi_unregister(s);
- }
- return -1;
}
static void free_tor(struct tor2 *tor)
@@ -365,6 +366,8 @@ static void free_tor(struct tor2 *tor)
if (tor->chans[x])
kfree(tor->chans[x]);
}
+ kfree(tor->ddev->location);
+ dahdi_free_device(tor->ddev);
kfree(tor);
}
@@ -631,7 +634,6 @@ static struct pci_driver tor2_driver;
static void __devexit tor2_remove(struct pci_dev *pdev)
{
struct tor2 *tor;
- int i;
tor = pci_get_drvdata(pdev);
if (!tor)
@@ -641,11 +643,7 @@ static void __devexit tor2_remove(struct pci_dev *pdev)
writeb(0, &tor->mem8[LEDREG]);
writew(0, &tor->plx[INTCSR]);
free_irq(tor->irq, tor);
- for (i = 0; i < SPANS_PER_CARD; ++i) {
- struct dahdi_span *s = &tor->tspans[i].dahdi_span;
- if (test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
- dahdi_unregister(s);
- }
+ dahdi_unregister_device(tor->ddev);
release_mem_region(tor->plx_region, tor->plx_len);
release_mem_region(tor->xilinx32_region, tor->xilinx32_len);
release_mem_region(tor->xilinx8_region, tor->xilinx8_len);
diff --git a/drivers/dahdi/voicebus/voicebus.c b/drivers/dahdi/voicebus/voicebus.c
index d11559a..28b8e32 100644
--- a/drivers/dahdi/voicebus/voicebus.c
+++ b/drivers/dahdi/voicebus/voicebus.c
@@ -2030,7 +2030,7 @@ static int __init voicebus_module_init(void)
* defined, but it will make sure that this module is a dependency of
* dahdi.ko, so that when it is being unloded, this module will be
* unloaded as well. */
- dahdi_register(NULL, 0);
+ dahdi_register_device(NULL, NULL);
spin_lock_init(&loader_list_lock);
return 0;
}
diff --git a/drivers/dahdi/wcb4xxp/base.c b/drivers/dahdi/wcb4xxp/base.c
index 3fb5647..72744f8 100644
--- a/drivers/dahdi/wcb4xxp/base.c
+++ b/drivers/dahdi/wcb4xxp/base.c
@@ -2494,11 +2494,6 @@ static void init_spans(struct b4xxp *b4)
sprintf(bspan->span.name, "B4/%d/%d", b4->cardno, i+1);
sprintf(bspan->span.desc, "B4XXP (PCI) Card %d Span %d", b4->cardno, i+1);
- bspan->span.manufacturer = "Digium";
- strlcpy(bspan->span.devicetype, b4->variety,
- sizeof(bspan->span.devicetype));
- sprintf(bspan->span.location, "PCI Bus %02d Slot %02d",
- b4->pdev->bus->number, PCI_SLOT(b4->pdev->devfn) + 1);
bspan->span.ops = &b4xxp_span_ops;
/* HDLC stuff */
@@ -2930,14 +2925,27 @@ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id
hfc_init_all_st(b4);
/* initialize the DAHDI structures, and let DAHDI know it has some new hardware to play with */
+ b4->ddev = dahdi_create_device();
init_spans(b4);
+
for (x=0; x < b4->numspans; x++) {
- if (dahdi_register(&b4->spans[x].span, 0)) {
- dev_err(&b4->pdev->dev,
- "Unable to register span %s\n",
- b4->spans[x].span.name);
- goto err_out_unreg_spans;
- }
+ struct dahdi_span *const s = &b4->spans[x].span;
+ list_add_tail(&s->device_node, &b4->ddev->spans);
+ }
+
+ b4->ddev->manufacturer = "Digium";
+ b4->ddev->devicetype = b4->variety;
+ b4->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
+ b4->pdev->bus->number,
+ PCI_SLOT(b4->pdev->devfn) + 1);
+ if (!b4->ddev->location) {
+ ret = -ENOMEM;
+ goto err_out_del_from_card_array;
+ }
+
+ if (dahdi_register_device(b4->ddev, &b4->pdev->dev)) {
+ dev_err(&b4->pdev->dev, "Unable to register device.\n");
+ goto err_out_unreg_spans;
}
@@ -2973,10 +2981,7 @@ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id
/* 'x' will have the failing span #. (0-3). We need to unregister everything before it. */
err_out_unreg_spans:
- while (x) {
- dahdi_unregister(&b4->spans[x].span);
- x--;
- };
+ dahdi_unregister_device(b4->ddev);
b4xxp_init_stage1(b4); /* full reset, re-init to "no-irq" state */
free_irq(pdev->irq, b4);
@@ -2997,6 +3002,8 @@ err_out_free_mem:
pci_set_drvdata(pdev, NULL);
pci_iounmap(pdev, b4->ioaddr);
pci_iounmap(pdev, b4->addr);
+ kfree(b4->ddev->location);
+ dahdi_free_device(b4->ddev);
kfree(b4);
err_out_release_regions:
@@ -3011,14 +3018,11 @@ err_out_disable_pdev:
static void __devexit b4xxp_remove(struct pci_dev *pdev)
{
struct b4xxp *b4 = pci_get_drvdata(pdev);
- int i;
if (b4) {
b4->shutdown = 1;
- for (i=b4->numspans - 1; i >= 0; i--) {
- dahdi_unregister(&b4->spans[i].span);
- }
+ dahdi_unregister_device(b4->ddev);
b4xxp_init_stage1(b4);
remove_sysfs_files(b4);
@@ -3033,6 +3037,8 @@ static void __devexit b4xxp_remove(struct pci_dev *pdev)
tasklet_kill(&b4->b4xxp_tlet);
+ kfree(b4->ddev->location);
+ dahdi_free_device(b4->ddev);
kfree(b4);
}
diff --git a/drivers/dahdi/wcb4xxp/wcb4xxp.h b/drivers/dahdi/wcb4xxp/wcb4xxp.h
index 56dc93b..80a28fe 100644
--- a/drivers/dahdi/wcb4xxp/wcb4xxp.h
+++ b/drivers/dahdi/wcb4xxp/wcb4xxp.h
@@ -474,6 +474,7 @@ struct b4xxp {
/* Flags for our bottom half */
unsigned int shutdown; /* 1=bottom half doesn't process anything, just returns */
struct tasklet_struct b4xxp_tlet;
+ struct dahdi_device *ddev;
};
/* CPLD access bits */
diff --git a/drivers/dahdi/wcfxo.c b/drivers/dahdi/wcfxo.c
index d206512..948d299 100644
--- a/drivers/dahdi/wcfxo.c
+++ b/drivers/dahdi/wcfxo.c
@@ -135,6 +135,7 @@ static int wecareregs[] =
struct wcfxo {
struct pci_dev *dev;
char *variety;
+ struct dahdi_device *ddev;
struct dahdi_span span;
struct dahdi_chan _chan;
struct dahdi_chan *chan;
@@ -647,14 +648,20 @@ static const struct dahdi_span_ops wcfxo_span_ops = {
static int wcfxo_initialize(struct wcfxo *wc)
{
+ wc->ddev = dahdi_create_device();
+
/* DAHDI stuff */
sprintf(wc->span.name, "WCFXO/%d", wc->pos);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
sprintf(wc->chan->name, "WCFXO/%d/%d", wc->pos, 0);
- snprintf(wc->span.location, sizeof(wc->span.location) - 1,
- "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
- wc->span.manufacturer = "Digium";
- strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
+ wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
+ wc->dev->bus->number,
+ PCI_SLOT(wc->dev->devfn) + 1);
+ if (!wc->ddev->location)
+ return -ENOMEM;
+
+ wc->ddev->manufacturer = "Digium";
+ wc->ddev->devicetype = wc->variety;
wc->chan->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF;
wc->chan->chanpos = 1;
wc->span.chans = &wc->chan;
@@ -668,7 +675,8 @@ static int wcfxo_initialize(struct wcfxo *wc)
wc->chan->pvt = wc;
wc->span.ops = &wcfxo_span_ops;
- if (dahdi_register(&wc->span, 0)) {
+ list_add_tail(&wc->span.device_node, &wc->ddev->spans);
+ if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
return -1;
}
@@ -976,7 +984,7 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
printk(KERN_NOTICE "Failed to initailize DAA, giving up...\n");
wcfxo_stop_dma(wc);
wcfxo_disable_interrupts(wc);
- dahdi_unregister(&wc->span);
+ dahdi_unregister_device(wc->ddev);
free_irq(pdev->irq, wc);
/* Reset PCI chip and registers */
@@ -984,6 +992,8 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
if (wc->freeregion)
release_region(wc->ioaddr, 0xff);
+ kfree(wc->ddev->location);
+ dahdi_free_device(wc->ddev);
kfree(wc);
return -EIO;
}
@@ -995,9 +1005,11 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
static void wcfxo_release(struct wcfxo *wc)
{
- dahdi_unregister(&wc->span);
+ dahdi_unregister_device(wc->ddev);
if (wc->freeregion)
release_region(wc->ioaddr, 0xff);
+ kfree(wc->ddev->location);
+ dahdi_free_device(wc->ddev);
kfree(wc);
printk(KERN_INFO "Freed a Wildcard\n");
}
diff --git a/drivers/dahdi/wct1xxp.c b/drivers/dahdi/wct1xxp.c
index fc8373e..686d0a7 100644
--- a/drivers/dahdi/wct1xxp.c
+++ b/drivers/dahdi/wct1xxp.c
@@ -159,6 +159,7 @@ struct t1xxp {
unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE];
unsigned char tempo[32];
struct dahdi_span span; /* Span */
+ struct dahdi_device *ddev;
struct dahdi_chan *chans[31]; /* Channels */
};
@@ -272,10 +273,11 @@ static void t1xxp_release(struct t1xxp *wc)
{
unsigned int x;
- dahdi_unregister(&wc->span);
+ dahdi_unregister_device(wc->ddev);
for (x = 0; x < (wc->ise1 ? 31 : 24); x++) {
kfree(wc->chans[x]);
}
+ dahdi_free_device(wc->ddev);
kfree(wc);
printk(KERN_INFO "Freed a Wildcard\n");
}
@@ -770,13 +772,20 @@ static int t1xxp_software_init(struct t1xxp *wc)
}
if (x >= WC_MAX_CARDS)
return -1;
+
+ wc->ddev = dahdi_create_device();
+
wc->num = x;
sprintf(wc->span.name, "WCT1/%d", wc->num);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
- wc->span.manufacturer = "Digium";
- strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
- snprintf(wc->span.location, sizeof(wc->span.location) - 1,
- "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
+ wc->ddev->manufacturer = "Digium";
+ wc->ddev->devicetype = wc->variety;
+ wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
+ wc->dev->bus->number,
+ PCI_SLOT(wc->dev->devfn) + 1);
+ if (!wc->ddev->location)
+ return -ENOMEM;
+
wc->span.irq = wc->dev->irq;
wc->span.chans = wc->chans;
wc->span.flags = DAHDI_FLAG_RBS;
@@ -801,7 +810,8 @@ static int t1xxp_software_init(struct t1xxp *wc)
wc->chans[x]->chanpos = x + 1;
}
wc->span.ops = &t1xxp_span_ops;
- if (dahdi_register(&wc->span, 0)) {
+ list_add_tail(&wc->span.device_node, &wc->ddev->spans);
+ if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
return -1;
}
diff --git a/drivers/dahdi/wct4xxp/base.c b/drivers/dahdi/wct4xxp/base.c
index dab436c..4bdea1f 100644
--- a/drivers/dahdi/wct4xxp/base.c
+++ b/drivers/dahdi/wct4xxp/base.c
@@ -325,6 +325,7 @@ struct t4 {
int num; /* Which card we are */
int t1e1; /* T1/E1 select pins */
int syncsrc; /* active sync source */
+ struct dahdi_device *ddev;
struct t4_span *tspans[4]; /* Individual spans */
int numspans; /* Number of spans on the card */
int blinktimer;
@@ -1698,34 +1699,30 @@ static int t4_close(struct dahdi_chan *chan)
return 0;
}
-#ifdef VPM_SUPPORT
-static void set_span_devicetype(struct t4 *wc)
+static int set_span_devicetype(struct t4 *wc)
{
- int x;
-
- for (x = 0; x < wc->numspans; x++) {
- struct t4_span *const ts = wc->tspans[x];
- strlcpy(ts->span.devicetype, wc->devtype->desc,
- sizeof(ts->span.devicetype));
+#ifdef VPM_SUPPORT
+ const char *vpmstring;
+ if (wc->vpm450m) {
+ if (wc->numspans > 2)
+ vpmstring = "OCT128";
+ else
+ vpmstring = "OCT064";
- if (wc->vpm450m) {
- strncat(ts->span.devicetype, (wc->numspans > 2) ? " (VPMOCT128)" : " (VPMOCT064)",
- sizeof(ts->span.devicetype) - 1);
- }
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (VPM%s)",
+ wc->devtype->desc, vpmstring);
+ } else {
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, wc->devtype->desc);
}
-}
#else
-static void set_span_devicetype(struct t4 *wc)
-{
- int x;
- for (x = 0; x < wc->numspans; x++) {
- struct t4_span *const ts = wc->tspans[x];
- strlcpy(ts->span.devicetype, wc->devtype->desc,
- sizeof(ts->span.devicetype));
- }
-}
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, wc->devtype->desc);
#endif
+ if (!wc->ddev->devicetype)
+ return -ENOMEM;
+ return 0;
+}
+
/* The number of cards we have seen with each
possible 'order' switch setting.
*/
@@ -1805,13 +1802,6 @@ static void init_spans(struct t4 *wc)
sprintf(ts->span.name, "TE%d/%d/%d", wc->numspans, wc->num, x + 1);
snprintf(ts->span.desc, sizeof(ts->span.desc) - 1,
"T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1);
- ts->span.manufacturer = "Digium";
- if (!ignore_rotary && (1 == order_index[wc->order]))
- snprintf(ts->span.location, sizeof(ts->span.location) - 1, "Board ID Switch %d", wc->order);
- else
- snprintf(ts->span.location, sizeof(ts->span.location) - 1,
- "PCI%s Bus %02d Slot %02d", (ts->spanflags & FLAG_EXPRESS) ? " Express" : " ",
- wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
switch (ts->linemode) {
case T1:
ts->span.spantype = "T1";
@@ -4043,7 +4033,10 @@ static int t4_hardware_init_2(struct t4 *wc)
static int __devinit t4_launch(struct t4 *wc)
{
+ int x;
+ int res;
unsigned long flags;
+
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags))
return 0;
@@ -4055,35 +4048,33 @@ static int __devinit t4_launch(struct t4 *wc)
t4_serial_setup(wc);
- if (dahdi_register(&wc->tspans[0]->span, 0)) {
- dev_err(&wc->dev->dev, "Unable to register span %s\n",
- wc->tspans[0]->span.name);
- return -1;
+ wc->ddev->manufacturer = "Digium";
+ if (!ignore_rotary && (1 == order_index[wc->order])) {
+ wc->ddev->location = kasprintf(GFP_KERNEL,
+ "Board ID Switch %d", wc->order);
+ } else {
+ bool express = ((wc->tspans[0]->spanflags & FLAG_EXPRESS) > 0);
+ wc->ddev->location = kasprintf(GFP_KERNEL,
+ "PCI%s Bus %02d Slot %02d",
+ (express) ? " Express" : "",
+ wc->dev->bus->number,
+ PCI_SLOT(wc->dev->devfn) + 1);
}
- if (dahdi_register(&wc->tspans[1]->span, 0)) {
- dev_err(&wc->dev->dev, "Unable to register span %s\n",
- wc->tspans[1]->span.name);
- dahdi_unregister(&wc->tspans[0]->span);
- return -1;
+
+ if (!wc->ddev->location)
+ return -ENOMEM;
+
+ for (x = 0; x < wc->numspans; ++x) {
+ list_add_tail(&wc->tspans[x]->span.device_node,
+ &wc->ddev->spans);
}
- if (wc->numspans == 4) {
- if (dahdi_register(&wc->tspans[2]->span, 0)) {
- dev_err(&wc->dev->dev, "Unable to register span %s\n",
- wc->tspans[2]->span.name);
- dahdi_unregister(&wc->tspans[0]->span);
- dahdi_unregister(&wc->tspans[1]->span);
- return -1;
- }
- if (dahdi_register(&wc->tspans[3]->span, 0)) {
- dev_err(&wc->dev->dev, "Unable to register span %s\n",
- wc->tspans[3]->span.name);
- dahdi_unregister(&wc->tspans[0]->span);
- dahdi_unregister(&wc->tspans[1]->span);
- dahdi_unregister(&wc->tspans[2]->span);
- return -1;
- }
+ res = dahdi_register_device(wc->ddev, &wc->dev->dev);
+ if (res) {
+ dev_err(&wc->dev->dev, "Failed to register with DAHDI.\n");
+ return res;
}
+
set_bit(T4_CHECK_TIMING, &wc->checkflag);
spin_lock_irqsave(&wc->reglock, flags);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
@@ -4105,6 +4096,10 @@ static void free_wc(struct t4 *wc)
}
kfree(wc->tspans[x]);
}
+
+ kfree(wc->ddev->devicetype);
+ kfree(wc->ddev->location);
+ dahdi_free_device(wc->ddev);
kfree(wc);
}
@@ -4146,11 +4141,16 @@ static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_i
return -EIO;
}
- if (!(wc = kmalloc(sizeof(*wc), GFP_KERNEL))) {
+ wc = kzalloc(sizeof(*wc), GFP_KERNEL);
+ if (!wc)
+ return -ENOMEM;
+
+ wc->ddev = dahdi_create_device();
+ if (!wc->ddev) {
+ kfree(wc);
return -ENOMEM;
}
- memset(wc, 0x0, sizeof(*wc));
spin_lock_init(&wc->reglock);
wc->devtype = (const struct devtype *)(ent->driver_data);
@@ -4355,9 +4355,12 @@ static int t4_hardware_stop(struct t4 *wc)
static void _t4_remove_one(struct t4 *wc)
{
- struct dahdi_span *span;
int basesize;
- int i;
+
+ if (!wc)
+ return;
+
+ dahdi_unregister_device(wc->ddev);
remove_sysfs_files(wc);
@@ -4376,11 +4379,6 @@ static void _t4_remove_one(struct t4 *wc)
if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN))
basesize = basesize * 2;
- for (i = 0; i < wc->numspans; ++i) {
- span = &wc->tspans[i]->span;
- if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
- dahdi_unregister(span);
- }
#ifdef ENABLE_WORKQUEUES
if (wc->workq) {
flush_workqueue(wc->workq);
diff --git a/drivers/dahdi/wctdm.c b/drivers/dahdi/wctdm.c
index 0e81c84..5b13fee 100644
--- a/drivers/dahdi/wctdm.c
+++ b/drivers/dahdi/wctdm.c
@@ -205,6 +205,7 @@ struct wctdm {
struct pci_dev *dev;
char *variety;
struct dahdi_span span;
+ struct dahdi_device *ddev;
unsigned char ios;
int usecount;
unsigned int intcount;
@@ -2362,13 +2363,26 @@ static int wctdm_initialize(struct wctdm *wc)
{
int x;
+ wc->ddev = dahdi_create_device();
+ if (!wc->ddev)
+ return -ENOMEM;
+
/* DAHDI stuff */
sprintf(wc->span.name, "WCTDM/%d", wc->pos);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
- snprintf(wc->span.location, sizeof(wc->span.location) - 1,
- "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
- wc->span.manufacturer = "Digium";
- strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
+ wc->ddev->location = kasprintf(GFP_KERNEL,
+ "PCI Bus %02d Slot %02d",
+ wc->dev->bus->number,
+ PCI_SLOT(wc->dev->devfn) + 1);
+ if (!wc->ddev->location) {
+ dahdi_free_device(wc->ddev);
+ wc->ddev = NULL;
+ return -ENOMEM;
+ }
+
+ wc->ddev->manufacturer = "Digium";
+ wc->ddev->devicetype = wc->variety;
+
if (alawoverride) {
printk(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n");
wc->span.deflaw = DAHDI_LAW_ALAW;
@@ -2388,8 +2402,12 @@ static int wctdm_initialize(struct wctdm *wc)
wc->span.flags = DAHDI_FLAG_RBS;
wc->span.ops = &wctdm_span_ops;
- if (dahdi_register(&wc->span, 0)) {
+ list_add_tail(&wc->span.device_node, &wc->ddev->spans);
+ if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
+ kfree(wc->ddev->location);
+ dahdi_free_device(wc->ddev);
+ wc->ddev = NULL;
return -1;
}
return 0;
@@ -2677,7 +2695,9 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
release_region(wc->ioaddr, 0xff);
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma);
pci_set_drvdata(pdev, NULL);
- dahdi_unregister(&wc->span);
+ dahdi_unregister_device(wc->ddev);
+ kfree(wc->ddev->location);
+ dahdi_free_device(wc->ddev);
kfree(wc);
return -EIO;
@@ -2708,10 +2728,14 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
static void wctdm_release(struct wctdm *wc)
{
- dahdi_unregister(&wc->span);
+ dahdi_unregister_device(wc->ddev);
if (wc->freeregion)
release_region(wc->ioaddr, 0xff);
+
+ kfree(wc->ddev->location);
+ dahdi_free_device(wc->ddev);
kfree(wc);
+
printk(KERN_INFO "Freed a Wildcard\n");
}
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index 034a908..aabee02 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -4366,6 +4366,32 @@ wctdm_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
return wctdm_wait_for_ready(wc);
}
+/*
+ * wctdm24xxp_assigned - Called when span is assigned.
+ * @span: The span that is now assigned.
+ *
+ * This function is called by the core of DAHDI after the span number and
+ * channel numbers have been assigned.
+ *
+ */
+static void wctdm24xxp_assigned(struct dahdi_span *span)
+{
+ struct dahdi_span *s;
+ struct dahdi_device *ddev = span->parent;
+ struct wctdm *wc = NULL;
+
+ list_for_each_entry(s, &ddev->spans, device_node) {
+ wc = (container_of(s, struct wctdm_span, span))->wc;
+ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
+ return;
+ }
+
+ if (wc) {
+ WARN_ON(0 == wc->not_ready);
+ --wc->not_ready;
+ }
+}
+
static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
.owner = THIS_MODULE,
.hooksig = wctdm_hooksig,
@@ -4375,6 +4401,7 @@ static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
.watchdog = wctdm_watchdog,
.chanconfig = wctdm_chanconfig,
.dacs = wctdm_dacs,
+ .assigned = wctdm24xxp_assigned,
#ifdef VPM_SUPPORT
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
@@ -4393,6 +4420,7 @@ static const struct dahdi_span_ops wctdm24xxp_digital_span_ops = {
.spanconfig = b400m_spanconfig,
.chanconfig = b400m_chanconfig,
.dacs = wctdm_dacs,
+ .assigned = wctdm24xxp_assigned,
#ifdef VPM_SUPPORT
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
@@ -4473,11 +4501,6 @@ wctdm_init_span(struct wctdm *wc, int spanno, int chanoffset, int chancount,
sprintf(s->span.name, "WCTDM/%d", card_position);
snprintf(s->span.desc, sizeof(s->span.desc) - 1, "%s", wc->desc->name);
- snprintf(s->span.location, sizeof(s->span.location) - 1,
- "PCI%s Bus %02d Slot %02d",
- (wc->desc->flags & FLAG_EXPRESS) ? " Express" : "",
- pdev->bus->number, PCI_SLOT(pdev->devfn) + 1);
- s->span.manufacturer = "Digium";
if (wc->companding == DAHDI_LAW_DEFAULT) {
if (wc->digi_mods || digital_span)
@@ -4966,9 +4989,10 @@ static void wctdm_back_out_gracefully(struct wctdm *wc)
kfree(frame);
}
-
-
kfree(wc->board_name);
+ kfree(wc->ddev->devicetype);
+ kfree(wc->ddev->location);
+ dahdi_free_device(wc->ddev);
kfree(wc);
}
@@ -5564,27 +5588,6 @@ static void wctdm_allocate_irq_commands(struct wctdm *wc, unsigned int count)
spin_unlock_irqrestore(&wc->reglock, flags);
}
-static void set_span_devicetype_string(struct wctdm *wc)
-{
- unsigned int x;
-
- for (x = 0; x < ARRAY_SIZE(wc->spans); x++) {
- struct dahdi_span *const s = &wc->spans[x]->span;
- if (!s)
- continue;
-
- strlcpy(s->devicetype, wc->desc->name, sizeof(s->devicetype));
-
- if (wc->vpmadt032) {
- strlcat(s->devicetype, " (VPMADT032)",
- sizeof(s->devicetype));
- } else if (wc->vpmoct) {
- strlcat(s->devicetype, " (VPMOCT032)",
- sizeof(s->devicetype));
- }
- }
-}
-
#ifdef USE_ASYNC_INIT
struct async_data {
struct pci_dev *pdev;
@@ -5852,27 +5855,56 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
wc->avchannels = curchan;
- set_span_devicetype_string(wc);
-
#ifdef USE_ASYNC_INIT
async_synchronize_cookie(cookie);
#endif
+ wc->ddev = dahdi_create_device();
+ wc->ddev->manufacturer = "Digium";
+ wc->ddev->location = kasprintf(GFP_KERNEL, "PCI%s Bus %02d Slot %02d",
+ (wc->desc->flags & FLAG_EXPRESS) ?
+ " Express" : "",
+ pdev->bus->number,
+ PCI_SLOT(pdev->devfn) + 1);
+ if (!wc->ddev->location) {
+ wctdm_back_out_gracefully(wc);
+ return -ENOMEM;
+ }
+
+ if (wc->vpmadt032) {
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (VPMADT032)",
+ wc->desc->name);
+ } else if (wc->vpmoct) {
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (VPMOCT032)",
+ wc->desc->name);
+ } else {
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s",
+ wc->desc->name);
+ }
+
+ if (!wc->ddev->devicetype) {
+ wctdm_back_out_gracefully(wc);
+ return -ENOMEM;
+ }
+
/* We should be ready for DAHDI to come in now. */
for (i = 0; i < MAX_SPANS; ++i) {
+ struct dahdi_span *span;
+
if (!wc->spans[i])
continue;
- if (dahdi_register(&wc->spans[i]->span, 0)) {
- dev_notice(&wc->vb.pdev->dev, "Unable to register span %d with DAHDI\n", i);
- while (i)
- dahdi_unregister(&wc->spans[i--]->span);
- wctdm_back_out_gracefully(wc);
- return -1;
- }
+ span = &wc->spans[i]->span;
+
+ list_add_tail(&span->device_node, &wc->ddev->spans);
}
wctdm_allocate_irq_commands(wc, anamods * latency * 4);
- wc->not_ready--;
+
+ if (dahdi_register_device(wc->ddev, &wc->vb.pdev->dev)) {
+ dev_notice(&wc->vb.pdev->dev, "Unable to register device with DAHDI\n");
+ wctdm_back_out_gracefully(wc);
+ return -1;
+ }
dev_info(&wc->vb.pdev->dev,
"Found a %s: %s (%d BRI spans, %d analog %s)\n",
@@ -5924,12 +5956,8 @@ static void wctdm_release(struct wctdm *wc)
{
int i;
- if (is_initialized(wc)) {
- for (i = 0; i < MAX_SPANS; i++) {
- if (wc->spans[i])
- dahdi_unregister(&wc->spans[i]->span);
- }
- }
+ if (is_initialized(wc))
+ dahdi_unregister_device(wc->ddev);
down(&ifacelock);
for (i = 0; i < WC_MAX_IFACES; i++)
diff --git a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
index c9ae58b..78e555c 100644
--- a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
+++ b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
@@ -297,6 +297,7 @@ struct wctdm {
int not_ready; /* 0 when the entire card is ready to go */
unsigned long checkflag; /* Internal state flags and task bits */
int companding;
+ struct dahdi_device *ddev;
};
static inline bool is_initialized(struct wctdm *wc)
diff --git a/drivers/dahdi/wcte11xp.c b/drivers/dahdi/wcte11xp.c
index c8067c7..b2eab8d 100644
--- a/drivers/dahdi/wcte11xp.c
+++ b/drivers/dahdi/wcte11xp.c
@@ -174,6 +174,7 @@ struct t1 {
unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE];
unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE];
unsigned char tempo[33];
+ struct dahdi_device *ddev;
struct dahdi_span span; /* Span */
struct dahdi_chan *chans[32]; /* Channels */
};
@@ -340,10 +341,12 @@ static void t1xxp_release(struct t1 *wc)
{
unsigned int x;
- dahdi_unregister(&wc->span);
+ dahdi_unregister_device(wc->ddev);
for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
kfree(wc->chans[x]);
}
+ kfree(wc->ddev->location);
+ dahdi_free_device(wc->ddev);
kfree(wc);
printk(KERN_INFO "Freed a Wildcard\n");
}
@@ -976,14 +979,21 @@ static int t1xxp_software_init(struct t1 *wc)
}
if (x >= WC_MAX_CARDS)
return -1;
+
+ wc->ddev = dahdi_create_device();
+
t4_serial_setup(wc);
wc->num = x;
sprintf(wc->span.name, "WCT1/%d", wc->num);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
- wc->span.manufacturer = "Digium";
- strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
- snprintf(wc->span.location, sizeof(wc->span.location) - 1,
- "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
+ wc->ddev->manufacturer = "Digium";
+ wc->ddev->devicetype = wc->variety;
+ wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
+ wc->dev->bus->number,
+ PCI_SLOT(wc->dev->devfn) + 1);
+ if (!wc->ddev->location)
+ return -ENOMEM;
+
wc->span.irq = wc->dev->irq;
if (wc->spantype == TYPE_E1) {
if (unchannelized)
@@ -1011,7 +1021,8 @@ static int t1xxp_software_init(struct t1 *wc)
wc->chans[x]->chanpos = x + 1;
}
wc->span.ops = &t1xxp_span_ops;
- if (dahdi_register(&wc->span, 0)) {
+ list_add_tail(&wc->span.device_node, &wc->ddev->spans);
+ if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
return -1;
}
diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c
index 6a6bf24..f6b2a48 100644
--- a/drivers/dahdi/wcte12xp/base.c
+++ b/drivers/dahdi/wcte12xp/base.c
@@ -755,7 +755,7 @@ static void __t1xxp_set_clear(struct t1 *wc)
/* Calculate all states on all 24 channels using the channel
flags, then write all 3 clear channel registers at once */
- for (i = 0; i < 24; i++) {
+ for (i = 0; i < wc->span.channels; i++) {
offset = i/8;
if (wc->span.chans[i]->flags & DAHDI_FLAG_CLEAR)
reg[offset] |= 1 << (7 - (i % 8));
@@ -783,7 +783,7 @@ static void free_wc(struct t1 *wc)
struct command *cmd;
LIST_HEAD(list);
- for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
+ for (x = 0; x < ARRAY_SIZE(wc->chans); x++) {
kfree(wc->chans[x]);
kfree(wc->ec[x]);
}
@@ -808,14 +808,14 @@ static void free_wc(struct t1 *wc)
}
#endif
+ kfree(wc->ddev->location);
+ kfree(wc->ddev->devicetype);
+ dahdi_free_device(wc->ddev);
kfree(wc);
}
static void t4_serial_setup(struct t1 *wc)
{
- t1_info(wc, "Setting up global serial parameters for %s\n",
- ((wc->spantype == TYPE_E1) ? "E1" : "T1"));
-
t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */
t1_setreg(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */
@@ -1009,12 +1009,12 @@ static void t1_configure_e1(struct t1 *wc, int lineconfig)
t1_info(wc, "Span configured for %s/%s%s\n", framing, line, crc4);
}
-static void t1xxp_framer_start(struct t1 *wc, struct dahdi_span *span)
+static void t1xxp_framer_start(struct t1 *wc)
{
- if (wc->spantype == TYPE_E1) { /* if this is an E1 card */
- t1_configure_e1(wc, span->lineconfig);
+ if (dahdi_is_e1_span(&wc->span)) {
+ t1_configure_e1(wc, wc->span.lineconfig);
} else { /* is a T1 card */
- t1_configure_t1(wc, span->lineconfig, span->txlevel);
+ t1_configure_t1(wc, wc->span.lineconfig, wc->span.txlevel);
__t1xxp_set_clear(wc);
}
@@ -1023,18 +1023,28 @@ static void t1xxp_framer_start(struct t1 *wc, struct dahdi_span *span)
static void set_span_devicetype(struct t1 *wc)
{
- strncpy(wc->span.devicetype, wc->variety,
- sizeof(wc->span.devicetype) - 1);
+ const char *olddevicetype;
+ olddevicetype = wc->ddev->devicetype;
#if defined(VPM_SUPPORT)
if (wc->vpmadt032) {
- strncat(wc->span.devicetype, " (VPMADT032)",
- sizeof(wc->span.devicetype) - 1);
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL,
+ "%s (VPMADT032)", wc->variety);
} else if (wc->vpmoct) {
- strncat(wc->span.devicetype, " (VPMOCT032)",
- sizeof(wc->span.devicetype) - 1);
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL,
+ "%s (VPMOCT032)", wc->variety);
+ } else {
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", wc->variety);
}
+#else
+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", wc->variety);
#endif
+
+ /* On the off chance that we were able to allocate it previously. */
+ if (!wc->ddev->devicetype)
+ wc->ddev->devicetype = olddevicetype;
+ else
+ kfree(olddevicetype);
}
static int t1xxp_startup(struct file *file, struct dahdi_span *span)
@@ -1055,7 +1065,7 @@ static int t1xxp_startup(struct file *file, struct dahdi_span *span)
#endif
/* Reset framer with proper parameters and start */
- t1xxp_framer_start(wc, span);
+ t1xxp_framer_start(wc);
debug_printk(wc, 1, "Calling startup (flags is %lu)\n", span->flags);
return 0;
@@ -1095,7 +1105,7 @@ static int t1xxp_chanconfig(struct file *file,
}
if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags) &&
- (wc->spantype != TYPE_E1)) {
+ dahdi_is_t1_span(&wc->span)) {
__t1xxp_set_clear(wc);
}
return 0;
@@ -1110,7 +1120,7 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits)
debug_printk(wc, 2, "Setting bits to %d on channel %s\n",
bits, chan->name);
- if (wc->spantype == TYPE_E1) { /* do it E1 way */
+ if (dahdi_is_e1_span(&wc->span)) { /* do it E1 way */
if (chan->chanpos == 16)
return 0;
@@ -1163,7 +1173,7 @@ static inline void t1_check_sigbits(struct t1 *wc)
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
return;
- if (wc->spantype == TYPE_E1) {
+ if (dahdi_is_e1_span(&wc->span)) {
for (i = 0; i < 15; i++) {
a = t1_getreg(wc, 0x71 + i);
if (a > -1) {
@@ -1258,7 +1268,7 @@ static void t1xxp_maint_work(struct work_struct *work)
int reg = 0;
int cmd = w->cmd;
- if (wc->spantype == TYPE_E1) {
+ if (dahdi_is_e1_span(&wc->span)) {
switch (cmd) {
case DAHDI_MAINT_NONE:
t1_info(wc, "Clearing all maint modes\n");
@@ -1330,7 +1340,7 @@ static int t1xxp_maint(struct dahdi_span *span, int cmd)
struct maint_work_struct *work;
struct t1 *wc = container_of(span, struct t1, span);
- if (wc->spantype == TYPE_E1) {
+ if (dahdi_is_e1_span(&wc->span)) {
switch (cmd) {
case DAHDI_MAINT_NONE:
case DAHDI_MAINT_LOCALLOOP:
@@ -1625,7 +1635,7 @@ static void check_and_load_vpm(struct t1 *wc)
options.vpmnlptype = vpmnlptype;
options.vpmnlpthresh = vpmnlpthresh;
options.vpmnlpmaxsupp = vpmnlpmaxsupp;
- options.channels = (TYPE_T1 == wc->spantype) ? 24 : 32;
+ options.channels = dahdi_is_t1_span(&wc->span) ? 24 : 32;
/* We do not want to check that the VPM is alive until after we're
* done setting it up here, an hour should cover it... */
@@ -1685,7 +1695,7 @@ static void t1_chan_set_sigcap(struct dahdi_span *span, int x)
struct dahdi_chan *chan = wc->chans[x];
chan->sigcap = DAHDI_SIG_CLEAR;
/* E&M variant supported depends on span type */
- if (wc->spantype == TYPE_E1) {
+ if (dahdi_is_e1_span(&wc->span)) {
/* E1 sigcap setup */
if (span->lineconfig & DAHDI_CONFIG_CCS) {
/* CCS setup */
@@ -1784,9 +1794,19 @@ static const struct dahdi_span_ops t1_span_ops = {
#endif
};
-static int t1_software_init(struct t1 *wc)
+/**
+ * t1_software_init - Initialize the board for the given type.
+ * @wc: The board to initialize.
+ * @type: The type of board we are, T1 / E1
+ *
+ * This function is called at startup and when the type of the span is changed
+ * via the dahdi_device before the span is assigned a number.
+ *
+ */
+static int t1_software_init(struct t1 *wc, enum linemode type)
{
int x;
+ int res;
int num;
struct pci_dev *pdev = wc->vb.pdev;
@@ -1801,21 +1821,23 @@ static int t1_software_init(struct t1 *wc)
if (x == ARRAY_SIZE(ifaces))
return -1;
- t4_serial_setup(wc);
num = x;
sprintf(wc->span.name, "WCT1/%d", num);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, num);
- wc->span.manufacturer = "Digium";
+ wc->ddev->manufacturer = "Digium";
set_span_devicetype(wc);
- snprintf(wc->span.location, sizeof(wc->span.location) - 1,
- "PCI Bus %02d Slot %02d", pdev->bus->number,
- PCI_SLOT(pdev->devfn) + 1);
+ wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
+ pdev->bus->number,
+ PCI_SLOT(pdev->devfn) + 1);
+
+ if (!wc->ddev->location)
+ return -ENOMEM;
wc->span.irq = pdev->irq;
- if (wc->spantype == TYPE_E1) {
+ if (type == E1) {
wc->span.channels = 31;
wc->span.spantype = "E1";
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3 |
@@ -1828,6 +1850,11 @@ static int t1_software_init(struct t1 *wc)
DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
wc->span.deflaw = DAHDI_LAW_MULAW;
}
+
+ t1_info(wc, "Setting up global serial parameters for %s\n",
+ (dahdi_is_e1_span(&wc->span) ? "E1" : "T1"));
+
+ t4_serial_setup(wc);
wc->span.chans = wc->chans;
set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags);
for (x = 0; x < wc->span.channels; x++) {
@@ -1840,9 +1867,11 @@ static int t1_software_init(struct t1 *wc)
check_and_load_vpm(wc);
wc->span.ops = &t1_span_ops;
- if (dahdi_register(&wc->span, 0)) {
- t1_info(wc, "Unable to register span with DAHDI\n");
- return -1;
+ list_add_tail(&wc->span.device_node, &wc->ddev->spans);
+ res = dahdi_register_device(wc->ddev, &wc->vb.pdev->dev);
+ if (res) {
+ t1_info(wc, "Unable to register with DAHDI\n");
+ return res;
}
return 0;
@@ -1864,7 +1893,7 @@ static inline unsigned char t1_vpm_out(struct t1 *wc, int unit, const unsigned i
#endif
#endif
-static int t1_hardware_post_init(struct t1 *wc)
+static int t1_hardware_post_init(struct t1 *wc, enum linemode *type)
{
int res;
int reg;
@@ -1872,22 +1901,22 @@ static int t1_hardware_post_init(struct t1 *wc)
/* T1 or E1 */
if (-1 != t1e1override) {
- pr_info("t1e1override is deprecated. Please use 'spantype'.\n");
- wc->spantype = (t1e1override) ? TYPE_E1 : TYPE_T1;
+ pr_info("t1e1override is deprecated. Please use 'default_linemode'.\n");
+ *type = (t1e1override) ? E1 : T1;
} else {
if (!strcasecmp(default_linemode, "e1")) {
- wc->spantype = TYPE_E1;
+ *type = E1;
} else if (!strcasecmp(default_linemode, "t1")) {
- wc->spantype = TYPE_T1;
+ *type = T1;
} else {
u8 pins;
res = t1_getpins(wc, &pins);
if (res)
return res;
- wc->spantype = (pins & 0x01) ? TYPE_T1 : TYPE_E1;
+ *type = (pins & 0x01) ? T1 : E1;
}
}
- debug_printk(wc, 1, "linemode: %s\n", 1 == wc->spantype ? "T1" : "E1");
+ debug_printk(wc, 1, "linemode: %s\n", (*type == T1) ? "T1" : "E1");
/* what version of the FALC are we using? */
reg = t1_setreg(wc, 0x4a, 0xaa);
@@ -1938,7 +1967,7 @@ static inline void t1_check_alarms(struct t1 *wc)
/* And consider only carrier alarms */
wc->span.alarms &= (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_NOTOPEN);
- if (wc->spantype == TYPE_E1) {
+ if (dahdi_is_e1_span(&wc->span)) {
if (c & 0x04) {
/* No multiframe found, force RAI high after 400ms only if
we haven't found a multiframe since last loss
@@ -2555,6 +2584,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
unsigned int x;
int res;
unsigned int index = -1;
+ enum linemode type;
for (x = 0; x < ARRAY_SIZE(ifaces); x++) {
if (!ifaces[x]) {
@@ -2582,6 +2612,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
ifaces[index] = wc;
wc->ledstate = -1;
+ wc->ddev = dahdi_create_device();
spin_lock_init(&wc->reglock);
INIT_LIST_HEAD(&wc->active_cmds);
INIT_LIST_HEAD(&wc->pending_cmds);
@@ -2656,14 +2687,14 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
return -EIO;
}
- res = t1_hardware_post_init(wc);
+ res = t1_hardware_post_init(wc, &type);
if (res) {
voicebus_release(&wc->vb);
free_wc(wc);
return res;
}
- for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
+ for (x = 0; x < ((E1 == type) ? 31 : 24); x++) {
wc->chans[x] = kzalloc(sizeof(*wc->chans[x]), GFP_KERNEL);
if (!wc->chans[x]) {
free_wc(wc);
@@ -2679,7 +2710,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
}
}
- res = t1_software_init(wc);
+ res = t1_software_init(wc, type);
if (res) {
voicebus_release(&wc->vb);
free_wc(wc);
@@ -2710,7 +2741,7 @@ static void __devexit te12xp_remove_one(struct pci_dev *pdev)
if (!wc)
return;
- dahdi_unregister(&wc->span);
+ dahdi_unregister_device(wc->ddev);
remove_sysfs_files(wc);
diff --git a/drivers/dahdi/wcte12xp/wcte12xp.h b/drivers/dahdi/wcte12xp/wcte12xp.h
index 507a43e..8ef4753 100644
--- a/drivers/dahdi/wcte12xp/wcte12xp.h
+++ b/drivers/dahdi/wcte12xp/wcte12xp.h
@@ -74,8 +74,10 @@
#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */
//TODO: make a separate macro
-#define TYPE_T1 1
-#define TYPE_E1 2
+enum linemode {
+ T1 = 1,
+ E1,
+};
struct command {
struct list_head node;
@@ -94,7 +96,6 @@ struct t1 {
unsigned char txident;
unsigned char rxident;
unsigned char statreg; /* bit 0 = vpmadt032 int */
- int spantype;
struct {
unsigned int nmf:1;
unsigned int sendingyellow:1;
@@ -116,6 +117,7 @@ struct t1 {
unsigned long alarmtimer;
unsigned char ledstate;
unsigned char vpm_check_count;
+ struct dahdi_device *ddev;
struct dahdi_span span; /* Span */
struct dahdi_chan *chans[32]; /* Channels */
struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */
diff --git a/drivers/dahdi/xpp/xbus-core.c b/drivers/dahdi/xpp/xbus-core.c
index 0734892..39fe67c 100644
--- a/drivers/dahdi/xpp/xbus-core.c
+++ b/drivers/dahdi/xpp/xbus-core.c
@@ -871,6 +871,86 @@ err:
goto out;
}
+static int xbus_register_dahdi_device(xbus_t *xbus)
+{
+ int i;
+ int offset = 0;
+
+ XBUS_NOTICE(xbus, "Entering %s\n", __func__);
+ xbus->ddev = dahdi_create_device();
+ /*
+ * This actually describe the dahdi_spaninfo version 3
+ * A bunch of unrelated data exported via a modified ioctl()
+ * What a bummer...
+ */
+ xbus->ddev->manufacturer = "Xorcom Inc."; /* OK, that's obvious */
+ /* span->spantype = "...."; set in card_dahdi_preregistration() */
+ /*
+ * Yes, this basically duplicates information available
+ * from the description field. If some more is needed
+ * why not add it there?
+ * OK, let's add to the kernel more useless info.
+ */
+ xbus->ddev->devicetype = kasprintf(GFP_KERNEL, "Astribank2");
+ if (!xbus->ddev->devicetype)
+ return -ENOMEM;
+
+ /*
+ * location is the only usefull new data item.
+ * For our devices it was available for ages via:
+ * - The legacy "/proc/xpp/XBUS-??/summary" (CONNECTOR=...)
+ * - The same info in "/proc/xpp/xbuses"
+ * - The modern "/sys/bus/astribanks/devices/xbus-??/connector" attribute
+ * So let's also export it via the newfangled "location" field.
+ */
+ xbus->ddev->location = xbus->connector;
+
+ /*
+ * Prepare the span list
+ */
+ for (i = 0; i < MAX_XPDS; i++) {
+ xpd_t *xpd = xpd_of(xbus, i);
+ if (xpd && IS_PHONEDEV(xpd)) {
+ XPD_DBG(DEVICES, xpd, "offset=%d\n", offset);
+ xpd_dahdi_preregister(xpd, offset++);
+ }
+ }
+ if (dahdi_register_device(xbus->ddev, &xbus->astribank)) {
+ XBUS_ERR(xbus, "Failed to dahdi_register_device()\n");
+ return -ENODEV;
+ }
+ for (i = 0; i < MAX_XPDS; i++) {
+ xpd_t *xpd = xpd_of(xbus, i);
+ if (xpd && IS_PHONEDEV(xpd)) {
+ XPD_DBG(DEVICES, xpd, "\n");
+ xpd_dahdi_postregister(xpd);
+ }
+ }
+ return 0;
+}
+
+static void xbus_unregister_dahdi_device(xbus_t *xbus)
+{
+ int i;
+
+ XBUS_NOTICE(xbus, "%s\n", __func__);
+ for(i = 0; i < MAX_XPDS; i++) {
+ xpd_t *xpd = xpd_of(xbus, i);
+ xpd_dahdi_preunregister(xpd);
+ }
+ dahdi_unregister_device(xbus->ddev);
+ XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n", __func__);
+ kfree(xbus->ddev->devicetype);
+ xbus->ddev->devicetype = NULL;
+ xbus->ddev->location = NULL;
+ dahdi_free_device(xbus->ddev);
+ xbus->ddev = NULL;
+ for(i = 0; i < MAX_XPDS; i++) {
+ xpd_t *xpd = xpd_of(xbus, i);
+ xpd_dahdi_postunregister(xpd);
+ }
+}
+
/*
* This must be called from synchronous (non-interrupt) context
* it returns only when all XPD's on the bus are detected and
@@ -934,6 +1014,7 @@ void xbus_populate(void *data)
*/
xbus_request_sync(xbus, SYNC_MODE_PLL);
elect_syncer("xbus_populate(end)"); /* FIXME: try to do it later */
+ xbus_register_dahdi_device(xbus);
out:
XBUS_DBG(DEVICES, xbus, "Leaving\n");
wake_up_interruptible_all(&worker->wait_for_xpd_initialization);
@@ -1206,12 +1287,12 @@ void xbus_deactivate(xbus_t *xbus)
xbus_request_sync(xbus, SYNC_MODE_NONE); /* no more ticks */
elect_syncer("deactivate");
xbus_echocancel(xbus, 0);
- xbus_request_removal(xbus);
XBUS_DBG(DEVICES, xbus, "[%s] Waiting for queues\n", xbus->label);
xbus_command_queue_clean(xbus);
xbus_command_queue_waitempty(xbus);
xbus_setstate(xbus, XBUS_STATE_DEACTIVATED);
worker_reset(xbus);
+ xbus_unregister_dahdi_device(xbus);
xbus_release_xpds(xbus); /* taken in xpd_alloc() [kref_init] */
}
@@ -1788,10 +1869,6 @@ err:
void xbus_core_shutdown(void)
{
- int i;
-
- for(i = 0; i < MAX_BUSES; i++)
- BUG_ON(xbus_num(i));
xbus_core_cleanup();
xpp_driver_exit();
}
diff --git a/drivers/dahdi/xpp/xbus-core.h b/drivers/dahdi/xpp/xbus-core.h
index 2149a38..6f4c672 100644
--- a/drivers/dahdi/xpp/xbus-core.h
+++ b/drivers/dahdi/xpp/xbus-core.h
@@ -188,6 +188,7 @@ struct xbus {
char label[LABEL_SIZE];
byte revision; /* Protocol revision */
struct xbus_transport transport;
+ struct dahdi_device *ddev;
int num;
struct xpd *xpds[MAX_XPDS];
diff --git a/drivers/dahdi/xpp/xbus-sysfs.c b/drivers/dahdi/xpp/xbus-sysfs.c
index daf16fc..c9f78f9 100644
--- a/drivers/dahdi/xpp/xbus-sysfs.c
+++ b/drivers/dahdi/xpp/xbus-sysfs.c
@@ -623,29 +623,6 @@ static DEVICE_ATTR_READER(span_show, dev, buf)
return len;
}
-static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
-{
- xpd_t *xpd;
- int dahdi_reg;
- int ret;
-
- BUG_ON(!dev);
- xpd = dev_to_xpd(dev);
- if(!xpd)
- return -ENODEV;
- ret = sscanf(buf, "%d", &dahdi_reg);
- if(ret != 1)
- return -EINVAL;
- if(!XBUS_IS(xpd->xbus, READY))
- return -ENODEV;
- XPD_DBG(GENERAL, xpd, "%s\n", (dahdi_reg) ? "register" : "unregister");
- if(dahdi_reg)
- ret = dahdi_register_xpd(xpd);
- else
- ret = dahdi_unregister_xpd(xpd);
- return (ret < 0) ? ret : count;
-}
-
static DEVICE_ATTR_READER(type_show, dev, buf)
{
xpd_t *xpd;
@@ -728,7 +705,7 @@ static int xpd_match(struct device *dev, struct device_driver *driver)
static struct device_attribute xpd_dev_attrs[] = {
__ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
__ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
- __ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store),
+ __ATTR_RO(span),
__ATTR_RO(type),
__ATTR_RO(offhook),
__ATTR_RO(timing_priority),
diff --git a/drivers/dahdi/xpp/xpp_dahdi.c b/drivers/dahdi/xpp/xpp_dahdi.c
index 0f186ef..f2c7314 100644
--- a/drivers/dahdi/xpp/xpp_dahdi.c
+++ b/drivers/dahdi/xpp/xpp_dahdi.c
@@ -256,8 +256,8 @@ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
void xpd_post_init(xpd_t *xpd)
{
XPD_DBG(DEVICES, xpd, "\n");
- if(dahdi_autoreg)
- dahdi_register_xpd(xpd);
+ /* DEBUG if(dahdi_autoreg) */
+ /* DEBUG dahdi_register_xpd(xpd); */
}
#ifdef CONFIG_PROC_FS
@@ -569,53 +569,12 @@ err:
}
/*
- * Try our best to make asterisk close all channels related to
- * this Astribank:
- * - Set span state to DAHDI_ALARM_NOTOPEN in all relevant spans.
- * - Notify dahdi afterwards about spans (so it can see all changes at once).
- * - Also send DAHDI_EVENT_REMOVED on all channels.
- */
-void xbus_request_removal(xbus_t *xbus)
-{
- unsigned long flags;
- int i;
-
- for(i = 0; i < MAX_XPDS; i++) {
- xpd_t *xpd = xpd_of(xbus, i);
- if(xpd) {
- XPD_DBG(DEVICES, xpd, "\n");
- spin_lock_irqsave(&xpd->lock, flags);
- xpd->card_present = 0;
- xpd_setstate(xpd, XPD_STATE_NOHW);
- PHONEDEV(xpd).span.alarms = DAHDI_ALARM_NOTOPEN;
- spin_unlock_irqrestore(&xpd->lock, flags);
- }
- }
- /* Now notify dahdi */
- for(i = 0; i < MAX_XPDS; i++) {
- xpd_t *xpd = xpd_of(xbus, i);
- if(xpd) {
- if(SPAN_REGISTERED(xpd)) {
- int j;
-
- dahdi_alarm_notify(&PHONEDEV(xpd).span);
- XPD_DBG(DEVICES, xpd, "Queuing DAHDI_EVENT_REMOVED on all channels to ask user to release them\n");
- for (j=0; j<PHONEDEV(xpd).span.channels; j++) {
- dahdi_qevent_lock(XPD_CHAN(xpd, j),DAHDI_EVENT_REMOVED);
- }
- }
- }
- }
-}
-
-/*
* The xpd isn't open by anyone, we can unregister it and free it
*/
void xpd_remove(xpd_t *xpd)
{
BUG_ON(!xpd);
XPD_INFO(xpd, "Remove\n");
- dahdi_unregister_xpd(xpd);
CALL_XMETHOD(card_remove, xpd);
xpd_free(xpd);
}
@@ -992,48 +951,6 @@ int xpp_echocan_create(struct dahdi_chan *chan,
}
EXPORT_SYMBOL(xpp_echocan_create);
-
-/**
- * Unregister an xpd from dahdi and release related resources
- * @xpd The xpd to be unregistered
- * @returns 0 on success, errno otherwise
- *
- * Checks that nobody holds an open channel.
- *
- * Called by:
- * - User action through /proc
- * - During xpd_remove()
- */
-int dahdi_unregister_xpd(xpd_t *xpd)
-{
- unsigned long flags;
-
- BUG_ON(!xpd);
- spin_lock_irqsave(&xpd->lock, flags);
-
- if (!IS_PHONEDEV(xpd)) {
- XPD_ERR(xpd, "Not a telephony device\n");
- spin_unlock_irqrestore(&xpd->lock, flags);
- return -EBADF;
- }
- if(!SPAN_REGISTERED(xpd)) {
- XPD_NOTICE(xpd, "Already unregistered\n");
- spin_unlock_irqrestore(&xpd->lock, flags);
- return -EIDRM;
- }
- update_xpd_status(xpd, DAHDI_ALARM_NOTOPEN);
- mdelay(2); // FIXME: This is to give chance for transmit/receiveprep to finish.
- spin_unlock_irqrestore(&xpd->lock, flags);
- if(xpd->card_present)
- CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 0);
- atomic_dec(&PHONEDEV(xpd).dahdi_registered);
- atomic_dec(&num_registered_spans);
- dahdi_unregister(&PHONEDEV(xpd).span);
- if(xpd->card_present)
- CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 0);
- return 0;
-}
-
static const struct dahdi_span_ops xpp_span_ops = {
.owner = THIS_MODULE,
.open = xpp_open,
@@ -1055,12 +972,39 @@ static const struct dahdi_span_ops xpp_rbs_span_ops = {
.echocan_name = xpp_echocan_name,
};
-int dahdi_register_xpd(xpd_t *xpd)
+static void xpd_init_span(xpd_t *xpd, unsigned offset, int cn)
{
struct dahdi_span *span;
+ int i;
+
+ XPD_NOTICE(xpd, "Initializing span(offset=%d): %d channels.\n", offset, cn);
+ memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
+ for (i = 0; i < cn; i++)
+ memset(XPD_CHAN(xpd, i), 0, sizeof(struct dahdi_chan));
+
+ span = &PHONEDEV(xpd).span;
+ snprintf(span->name, MAX_SPANNAME, "%s/%s", xpd->xbus->busname, xpd->xpdname);
+ span->deflaw = DAHDI_LAW_MULAW; /* default, may be overriden by card_* drivers */
+ span->channels = cn;
+ span->chans = PHONEDEV(xpd).chans;
+
+ span->flags = DAHDI_FLAG_RBS;
+ span->offset = offset;
+ if (PHONEDEV(xpd).phoneops->card_hooksig)
+ span->ops = &xpp_rbs_span_ops; /* Only with RBS bits */
+ else
+ span->ops = &xpp_span_ops;
+
+ snprintf(PHONEDEV(xpd).span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s",
+ xpd->xbus->num, xpd->addr.unit, xpd->addr.subunit, xpd->type_name);
+ list_add_tail(&span->device_node, &xpd->xbus->ddev->spans);
+}
+
+int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset)
+{
xbus_t *xbus;
int cn;
- int i;
+ struct phonedev *phonedev;
BUG_ON(!xpd);
@@ -1070,70 +1014,25 @@ int dahdi_register_xpd(xpd_t *xpd)
XPD_ERR(xpd, "Not a telephony device\n");
return -EBADF;
}
+
+ phonedev = &PHONEDEV(xpd);
+
if (SPAN_REGISTERED(xpd)) {
XPD_ERR(xpd, "Already registered\n");
return -EEXIST;
}
- cn = PHONEDEV(xpd).channels;
- XPD_DBG(DEVICES, xpd, "Initializing span: %d channels.\n", cn);
- memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
- for(i = 0; i < cn; i++) {
- memset(XPD_CHAN(xpd, i), 0, sizeof(struct dahdi_chan));
- }
- span = &PHONEDEV(xpd).span;
- snprintf(span->name, MAX_SPANNAME, "%s/%s", xbus->busname, xpd->xpdname);
- span->deflaw = DAHDI_LAW_MULAW; /* default, may be overriden by card_* drivers */
- span->channels = cn;
- span->chans = PHONEDEV(xpd).chans;
-
- span->flags = DAHDI_FLAG_RBS;
- if(PHONEDEV(xpd).phoneops->card_hooksig)
- span->ops = &xpp_rbs_span_ops; /* Only with RBS bits */
- else
- span->ops = &xpp_span_ops;
-
- /*
- * This actually describe the dahdi_spaninfo version 3
- * A bunch of unrelated data exported via a modified ioctl()
- * What a bummer...
- */
- span->manufacturer = "Xorcom Inc."; /* OK, that's obvious */
- /* span->spantype = "...."; set in card_dahdi_preregistration() */
- /*
- * Yes, this basically duplicates information available
- * from the description field. If some more is needed
- * why not add it there?
- * OK, let's add to the kernel more useless info.
- */
- snprintf(span->devicetype, sizeof(span->devicetype) - 1,
- "Astribank: Unit %x Subunit %x: %s",
- XBUS_UNIT(xpd->xbus_idx), XBUS_SUBUNIT(xpd->xbus_idx),
- xpd->type_name);
- /*
- * location is the only usefull new data item.
- * For our devices it was available for ages via:
- * - The legacy "/proc/xpp/XBUS-??/summary" (CONNECTOR=...)
- * - The same info in "/proc/xpp/xbuses"
- * - The modern "/sys/bus/astribanks/devices/xbus-??/connector" attribute
- * So let's also export it via the newfangled "location" field.
- */
- snprintf(span->location, sizeof(span->location) - 1, "%s", xbus->connector);
- /*
- * Who said a span and irq have 1-1 relationship?
- * Also exporting this low-level detail isn't too wise.
- * No irq's for you today!
- */
- span->irq = 0;
-
- snprintf(PHONEDEV(xpd).span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s",
- xbus->num, xpd->addr.unit, xpd->addr.subunit, xpd->type_name);
+ cn = PHONEDEV(xpd).channels;
+ xpd_init_span(xpd, offset, cn);
XPD_DBG(GENERAL, xpd, "Registering span '%s'\n", PHONEDEV(xpd).span.desc);
CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 1);
- if(dahdi_register(&PHONEDEV(xpd).span, prefmaster)) {
- XPD_ERR(xpd, "Failed to dahdi_register span\n");
- return -ENODEV;
- }
+ return 0;
+}
+
+int xpd_dahdi_postregister(xpd_t *xpd)
+{
+ int cn;
+
atomic_inc(&num_registered_spans);
atomic_inc(&PHONEDEV(xpd).dahdi_registered);
CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 1);
@@ -1153,6 +1052,48 @@ int dahdi_register_xpd(xpd_t *xpd)
return 0;
}
+/*
+ * Try our best to make asterisk close all channels related to
+ * this Astribank:
+ * - Set span state to DAHDI_ALARM_NOTOPEN in all relevant spans.
+ * - Notify dahdi afterwards about spans (so it can see all changes at once).
+ * - Also send DAHDI_EVENT_REMOVED on all channels.
+ */
+void xpd_dahdi_preunregister(xpd_t *xpd)
+{
+ unsigned long flags;
+ if (!xpd)
+ return;
+ XPD_DBG(DEVICES, xpd, "\n");
+ spin_lock_irqsave(&xpd->lock, flags);
+ xpd->card_present = 0;
+ xpd_setstate(xpd, XPD_STATE_NOHW);
+ spin_unlock_irqrestore(&xpd->lock, flags);
+ update_xpd_status(xpd, DAHDI_ALARM_NOTOPEN);
+ if(xpd->card_present)
+ CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 0);
+ /* Now notify dahdi */
+ if(SPAN_REGISTERED(xpd)) {
+ int j;
+
+ dahdi_alarm_notify(&PHONEDEV(xpd).span);
+ XPD_DBG(DEVICES, xpd, "Queuing DAHDI_EVENT_REMOVED on all channels to ask user to release them\n");
+ for (j=0; j<PHONEDEV(xpd).span.channels; j++) {
+ dahdi_qevent_lock(XPD_CHAN(xpd, j),DAHDI_EVENT_REMOVED);
+ }
+ }
+}
+
+void xpd_dahdi_postunregister(xpd_t *xpd)
+{
+ if (!xpd)
+ return;
+ atomic_dec(&PHONEDEV(xpd).dahdi_registered);
+ atomic_dec(&num_registered_spans);
+ if(xpd->card_present)
+ CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 0);
+}
+
/*------------------------- Initialization -------------------------*/
static void do_cleanup(void)
@@ -1217,7 +1158,6 @@ EXPORT_SYMBOL(get_xpd);
EXPORT_SYMBOL(put_xpd);
EXPORT_SYMBOL(xpd_alloc);
EXPORT_SYMBOL(xpd_free);
-EXPORT_SYMBOL(xbus_request_removal);
EXPORT_SYMBOL(update_xpd_status);
EXPORT_SYMBOL(oht_pcm);
EXPORT_SYMBOL(mark_offhook);
diff --git a/drivers/dahdi/xpp/xpp_dahdi.h b/drivers/dahdi/xpp/xpp_dahdi.h
index 01f4a24..cb76846 100644
--- a/drivers/dahdi/xpp/xpp_dahdi.h
+++ b/drivers/dahdi/xpp/xpp_dahdi.h
@@ -25,9 +25,10 @@
#include "xpd.h"
#include "xproto.h"
-int dahdi_register_xpd(xpd_t *xpd);
-int dahdi_unregister_xpd(xpd_t *xpd);
-void xbus_request_removal(xbus_t *xbus);
+int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset);
+int xpd_dahdi_postregister(xpd_t *xpd);
+void xpd_dahdi_preunregister(xpd_t *xpd);
+void xpd_dahdi_postunregister(xpd_t *xpd);
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
int unit, int subunit, byte type, byte subtype, int subunits, int subunit_ports, byte port_dir);
void xpd_post_init(xpd_t *xpd);
diff --git a/include/dahdi/kernel.h b/include/dahdi/kernel.h
index 9ae9d1e..9dec702 100644
--- a/include/dahdi/kernel.h
+++ b/include/dahdi/kernel.h
@@ -42,7 +42,7 @@
#include <linux/config.h>
#endif
#include <linux/fs.h>
-#include <linux/kobject.h>
+#include <linux/device.h>
#include <linux/ioctl.h>
#ifdef CONFIG_DAHDI_NET
@@ -885,6 +885,26 @@ struct dahdi_span_ops {
/*! Opt: Provide the name of the echo canceller on a channel */
const char *(*echocan_name)(const struct dahdi_chan *chan);
+
+ /*! When using "pinned_spans", this function is called back when this
+ * span has been assigned with the system. */
+ void (*assigned)(struct dahdi_span *span);
+};
+
+/**
+ * dahdi_device - Represents a device that can contain one or more spans.
+ *
+ * @spans: List of child spans.
+ * @manufacturer: Device manufacturer.
+ * @location: The location of this device
+ * @devicetype: What type of device this is.
+ *
+ */
+struct dahdi_device {
+ struct list_head spans;
+ const char *manufacturer;
+ const char *location;
+ const char *devicetype;
};
struct dahdi_span {
@@ -892,9 +912,6 @@ struct dahdi_span {
char name[40]; /*!< Span name */
char desc[80]; /*!< Span description */
const char *spantype; /*!< span type in text form */
- const char *manufacturer; /*!< span's device manufacturer */
- char devicetype[80]; /*!< span's device type */
- char location[40]; /*!< span device's location in system */
int deflaw; /*!< Default law (DAHDI_MULAW or DAHDI_ALAW) */
int alarms; /*!< Pending alarms on span */
unsigned long flags;
@@ -933,7 +950,10 @@ struct dahdi_span {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
#endif
- struct list_head node;
+ struct list_head spans_node;
+
+ struct dahdi_device *parent;
+ struct list_head device_node;
};
struct dahdi_transcoder_channel {
@@ -1031,6 +1051,7 @@ struct dahdi_dynamic {
long rxjif;
unsigned short txcnt;
unsigned short rxcnt;
+ struct dahdi_device *ddev;
struct dahdi_span span;
struct dahdi_chan *chans[256];
struct dahdi_dynamic_driver *driver;
@@ -1038,6 +1059,7 @@ struct dahdi_dynamic {
int timing;
int master;
unsigned char *msgbuf;
+ struct device *dev;
struct list_head list;
};
@@ -1131,10 +1153,11 @@ void dahdi_hdlc_putbuf(struct dahdi_chan *ss, unsigned char *rxb, int bytes);
* and 1 if the currently transmitted message is now done */
int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsigned int *size);
-
-/*! Register a span. Returns 0 on success, -1 on failure. Pref-master is non-zero if
- we should have preference in being the master device */
-int dahdi_register(struct dahdi_span *span, int prefmaster);
+/*! Register a device. Returns 0 on success, -1 on failure. */
+struct dahdi_device *dahdi_create_device(void);
+int dahdi_register_device(struct dahdi_device *ddev, struct device *parent);
+void dahdi_unregister_device(struct dahdi_device *ddev);
+void dahdi_free_device(struct dahdi_device *ddev);
/*! Allocate / free memory for a transcoder */
struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans);
@@ -1149,9 +1172,6 @@ int dahdi_transcoder_unregister(struct dahdi_transcoder *tc);
/*! \brief Alert a transcoder */
int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc);
-/*! \brief Unregister a span */
-int dahdi_unregister(struct dahdi_span *span);
-
/*! \brief Gives a name to an LBO */
const char *dahdi_lboname(int lbo);