Compare commits

..

23 Commits

Author SHA1 Message Date
Tzafrir Cohen
fdca6f36de sysfs: registration_time: use ktime_get_ts
A fix to 03b3ce1a10: use ktime_get_ts
instead of getnstimeofday to better handle system time changes.
(Shaun Ruffell)

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2014-01-28 20:39:21 +02:00
Tzafrir Cohen
02f6b4e7bd README: The sysfs class now includes no channels
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2014-01-28 20:24:40 +02:00
Tzafrir Cohen
701ed41adf README: the new registration_time device attribute
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2014-01-28 20:17:26 +02:00
Oron Peled
03b3ce1a10 sysfs: new device attribute: registration_time
Add a new sysfs attribute to dahdi_device: registration_time

* Records the time of the device's registration with DAHDI.
* Used by dahdi_auto_assign_compat to assign spans by device
  registration order when backward compatibility needed.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>
2014-01-28 20:04:22 +02:00
Tzafrir Cohen
2c4373972b README: xpp.dahdi_autoreg is deprecated
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-28 19:27:05 +02:00
Oron Peled
2ecf700dd8 xpp: continue xpp.dahdi_autoreg deprecation
* Set it to 0 by default (as we use dahdi.auto_assign_spans now)
* Make it readonly (no runtime changes)
* Warn during startup if it was forced to 1

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-28 19:24:27 +02:00
Oron Peled
74e949c33a xpp: deprecate dahdi_autoreg
Instead, use the inverse of dahdi.auto_assign_spans value.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-28 19:24:15 +02:00
Russ Meyerriecks
3efa9d8cd1 wcte13xp: wcxb: Add delayed reset firmware feature
Allow certain older firmwares to delay the hard reset until a full power cycle.
This way we can "preload" newer firmware images, without requiring the user to
physically power off/on their machine.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>
2014-01-24 13:14:14 -06:00
Shaun Ruffell
4cd09feb54 wcte43x, wcte13xp, wcaxx: Bump irqmisses counter when there are DMA underruns.
This makes the behavior of IRQ misses for these drivers behave the same as the
wcte12xp, wctdm24xxp, and wct4xxp drivers.

Previously irqmisses would never increase. The presence of underruns would still
show up in dmesg as latency bumps.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-22 18:04:47 -06:00
Shaun Ruffell
1f024713ed wct4xxp: Trivial drop of unnecessary local variables.
These were left over from when the VPM callbacks depended on the different VPM
installed. On the wcte43x this is unnecessary.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-22 18:04:47 -06:00
Shaun Ruffell
0b499d9566 wcte43x: Trivial drop of unnecessary local variables.
These were left over from when the VPM callbacks depended on the different VPM
installed. On the wcte43x this is unnecessary.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-22 18:04:47 -06:00
Russ Meyerriecks
438b2a36b3 wcte13xp: wcaxx: wcte43x: Remove VPM_SUPPORT compile option.
This was a legacy compile time option that is no longer necessary with the new
series of cards.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-22 13:40:27 -06:00
Russ Meyerriecks
be94aa11bb Revert "dahdi: Change auto_assign_spans default from 1 to 0."
This reverts commit c49a56c954.

Delaying this feature until after v2.9 release.
2014-01-21 16:36:44 -06:00
Russ Meyerriecks
1add33efe7 wcte13xp: Add support for te131 and te132 products
These are similar to te133 and te134 but without integrated echo cancel.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-17 15:43:06 -06:00
Russ Meyerriecks
094e30483d wcte13xp: Update firmware to 0x780017
This firmware adds support for the te131 and te132 products.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-17 15:33:25 -06:00
Russ Meyerriecks
e4ea886ee0 wcte13xp: wcaxx: Fix broken devicetype attributes
struct dahdi_device.devicetype was set incorrectly in both drivers. This caused
the vpm module to not show up after the device name when reading this field
from a spanstat.

Reported-by: Charles Moye <cmoye@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-17 15:30:38 -06:00
Shaun Ruffell
860eb4ab48 dahdi: Do not access invalid memory if invalid local span number is passed to spantype attribute.
This fixes potential kernel panic due to accessing invalid memory if passing
invalid local span number to 'spantype' attribute via sysfs.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2014-01-14 16:03:18 -06:00
Shaun Ruffell
47dcc9377c wcte43x, wcte13xp: Use MSI interrupts if possible.
It was an oversight to prevent the wcte43x and wcte13xp drivers from using
Message Signaled interrupts during the switch to the wcxb library.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-08 12:21:10 -06:00
Shaun Ruffell
f10eb3f547 wcte13xp: Export max_latency module parameter.
wcte13xp now has a max_latency module parameter like the wcaxx and wcte43x
drivers.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-08 12:21:10 -06:00
Shaun Ruffell
99de304d84 wcaxx, wcte13xp, wcte43x: Honor max_latency module parameter.
The wcxb library did not do actually use the max_latency member to limit the
maximum latency of the DMA engine.

Now it does.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-08 12:21:10 -06:00
Shaun Ruffell
c49a56c954 dahdi: Change auto_assign_spans default from 1 to 0.
The infrastructure has been put in place in 2.8.0 for fully dynamic device and
span configuration. This will be the default mode in DAHDI-Linux 2.9.0.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Acked-by: Oron Peled <oron.peled@xorcom.com>
2014-01-06 13:24:28 -06:00
Shaun Ruffell
e6b16eace1 dahdi: Move clearing of DAHDI_ALARM_NOTOPEN to __dahdi_assign_span().
Previously this was in __dahdi_init_span(). The problem was that
__dahdi_init_span() was only called when a spans' line mode was being changed.
Therefore it was possible to unassign and resassign an analog span and leave it
stuck in the 'NOP' alarm state.

It also make the setting / clearing of DAHDI_ALARM_NOTOPEN symetrical about span
unassignment / assignment in addition to updating the alarm states on all the
channels on the span via the dahdi_alarm_notify() function.

This is a better version of commit 496f817773.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-26 17:04:29 -06:00
Shaun Ruffell
3933ffd350 wctdm24xxp: Reset module specific type information on probe.
This fixes an issue that affects TDM410 modules when there is not a module
installed in the first port, but there is an FXO module installed in the third
port.

When scaning for QRV modules in the first port, the 3rd port will have the
'hook' struct.qrv set to 0xff. When a QRV module is  not detected, that value
will be left, which then maps to an invalid state for both fxo.ring_state and
fxo.battery_state.

The result would be that FXO ports would fail to run the ring detector state
machine since it did not know what the current state was.

Now we'll just reset all the values in struct fxo or struct fxs to the expected
init state.

Internal-Issue-ID: DAHLIN-332
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-20 14:15:26 -06:00
13 changed files with 245 additions and 157 deletions

26
README
View File

@@ -528,11 +528,12 @@ XPP (Astribank) module parameters
==== dahdi_autoreg
(xpp)
Register spans automatically (1) or not (0). Default: 0.
Setting it simplifies operations with a single Astribank and no other
DAHDI hardware. However if you have such systems, automatic
registration can cause the order of spans to be unpredictable.
The standard startup scripts use 'dahdi_registration on' instead of this.
Deprecated. See dahdi.<<_auto_assign_spans,auto_assign_spans>> above.
Originally had a somewhat similar (but xpp-specific and more limited)
role to auto_assign_spans. For backward compatibility this variable is
still kept, but its value is unused. Astribanks will auto-register
with dahdi if auto_assign_spans is not set.
==== tools_rootdir
(xpp)
@@ -896,11 +897,12 @@ to other nodes.
Class DAHDI
^^^^^^^^^^^
under /sys/class/dadhi there exists a node for each DAHDI device file
under /dev/dahdi. The name is 'dahdi!foo' for the file '/dev/dahdi/foo'
(udev translates exclamation marks to slashes). Those nodes are not, for
the most part, proper SysFS nodes, and don't include any interesting
properties.
Under /sys/class/dadhi there exists a node for the non-channel DAHDI
device file under /dev/dahdi. The name is 'dahdi!foo' for the file
'/dev/dahdi/foo' (udev translates exclamation marks to slashes). Those
nodes are not, for the most part, proper SysFS nodes, and don't include
any interesting properties. The files in this class `ctl`, `timer`,
`channel`, `pseudo` and (if exists) `transcode`.
Devices Bus
@@ -925,6 +927,10 @@ A unique hardware-level identifier (e.g. serial number), if available.
===== /sys/bus/dahdi_devices/devices/DEVICE/manufacturer
The name of the manufacturer. Freeform-string.
===== /sys/bus/dahdi_devices/devices/DEVICE/registration_time
The time at which the device registered with the DAHDI core. Example
value: "0005634136.941901429".
===== /sys/bus/dahdi_devices/devices/DEVICE/spantype
A line for each available span: <num>:<type>. This has to be provided
here as in the case of manual assignment, userspace may need to know

View File

@@ -50,6 +50,7 @@
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/ktime.h>
#if defined(HAVE_UNLOCKED_IOCTL) && defined(CONFIG_BKL)
#include <linux/smp_lock.h>
@@ -7188,13 +7189,6 @@ static void __dahdi_init_span(struct dahdi_span *span)
spin_lock_init(&span->lock);
clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
/* DAHDI_ALARM_NOTOPEN can be set when a span is disabled, i.e. via
* sysfs, so when the span is being initialized again before
* reassignment we should make sure it's cleared. This eliminates the
* need for board drivers to re-report their alarm states on span
* reassignment. */
span->alarms &= ~DAHDI_ALARM_NOTOPEN;
if (!span->deflaw) {
module_printk(KERN_NOTICE, "Span %s didn't specify default "
"law. Assuming mulaw, please fix driver!\n",
@@ -7255,6 +7249,7 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
{
int res = 0;
unsigned int x;
unsigned long flags;
if (!span || !span->ops || !span->ops->owner)
return -EFAULT;
@@ -7266,6 +7261,16 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
return -EINVAL;
}
/* DAHDI_ALARM_NOTOPEN can be set when a span is disabled, i.e. via
* sysfs, so when the span is being reassigned we should make sure it's
* cleared. This eliminates the need for board drivers to re-report
* their alarm states on span reassignment. */
spin_lock_irqsave(&span->lock, flags);
span->alarms &= ~DAHDI_ALARM_NOTOPEN;
dahdi_alarm_notify(span);
spin_unlock_irqrestore(&span->lock, flags);
if (span->ops->enable_hw_preechocan ||
span->ops->disable_hw_preechocan) {
if ((NULL == span->ops->enable_hw_preechocan) ||
@@ -7369,7 +7374,8 @@ int dahdi_assign_device_spans(struct dahdi_device *ddev)
return 0;
}
static int auto_assign_spans = 1;
int auto_assign_spans = 1;
EXPORT_SYMBOL(auto_assign_spans);
static const char *UNKNOWN = "";
/**
@@ -7399,6 +7405,7 @@ static int _dahdi_register_device(struct dahdi_device *ddev,
__dahdi_init_span(s);
}
ktime_get_ts(&ddev->registration_time);
ret = dahdi_sysfs_add_device(ddev, parent);
if (ret)
return ret;

View File

@@ -629,7 +629,8 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
{
struct dahdi_device *const ddev = to_ddev(dev);
int ret;
struct dahdi_span *span;
struct dahdi_span *span = NULL;
struct dahdi_span *cur;
unsigned int local_span_number;
char spantype_name[80];
enum spantypes spantype;
@@ -645,9 +646,18 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
list_for_each_entry(span, &ddev->spans, device_node) {
if (local_spanno(span) == local_span_number)
list_for_each_entry(cur, &ddev->spans, device_node) {
if (local_spanno(cur) == local_span_number) {
span = cur;
break;
}
}
if (!span || (local_spanno(span) != local_span_number)) {
module_printk(KERN_WARNING,
"%d is not a valid local span number "
"for this device.\n", local_span_number);
return -EINVAL;
}
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
@@ -656,12 +666,6 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
if (local_spanno(span) != local_span_number) {
module_printk(KERN_WARNING,
"%d is not a valid local span number "
"for this device.\n", local_span_number);
return -EINVAL;
}
if (!span->ops->set_spantype) {
module_printk(KERN_WARNING, "Span %s does not support "
@@ -673,6 +677,19 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return (ret < 0) ? ret : count;
}
static ssize_t
dahdi_registration_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
int count = 0;
count += sprintf(buf, "%010ld.%09ld\n",
ddev->registration_time.tv_sec,
ddev->registration_time.tv_nsec);
return count;
}
static struct device_attribute dahdi_device_attrs[] = {
__ATTR(manufacturer, S_IRUGO, dahdi_device_manufacturer_show, NULL),
__ATTR(type, S_IRUGO, dahdi_device_type_show, NULL),
@@ -684,6 +701,7 @@ static struct device_attribute dahdi_device_attrs[] = {
__ATTR(unassign_span, S_IWUSR, NULL, dahdi_device_unassign_span),
__ATTR(spantype, S_IWUSR | S_IRUGO, dahdi_spantype_show,
dahdi_spantype_store),
__ATTR(registration_time, S_IRUGO, dahdi_registration_time_show, NULL),
__ATTR_NULL,
};

View File

@@ -31,8 +31,8 @@ VPMADT032_VERSION:=1.25.0
HX8_VERSION:=2.06
VPMOCT032_VERSION:=1.12.0
WCT820_VERSION:=1.76
TE133_VERSION:=6f0017
TE134_VERSION:=6f0017
TE133_VERSION:=780017
TE134_VERSION:=780017
TE435_VERSION:=e0017
A8A_VERSION:=1d0017
A8B_VERSION:=1d0017

View File

@@ -75,8 +75,6 @@
#define NUM_MODULES 8
#define VPM_SUPPORT
#define CMD_WR(addr, val) (((addr<<8)&0xff00) | (val&0xff))
enum battery_state {
@@ -245,7 +243,6 @@ static inline bool is_four_port(const struct wcaxx *wc)
return (4 == wc->desc->ports);
}
#ifdef VPM_SUPPORT
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
@@ -728,7 +725,6 @@ static int wcaxx_vpm_init(struct wcaxx *wc)
return 0;
}
#endif /* VPM_SUPPORT */
static inline bool is_initialized(struct wcaxx *wc)
{
@@ -3084,11 +3080,9 @@ wcaxx_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data)
((hwgain.tx) ? "tx" : "rx"));
}
break;
#ifdef VPM_SUPPORT
case DAHDI_TONEDETECT:
/* Hardware DTMF detection is not supported. */
return -ENOSYS;
#endif
case DAHDI_SETPOLARITY:
if (get_user(x, (__user int *) data))
return -EFAULT;
@@ -3414,10 +3408,8 @@ static const struct dahdi_span_ops wcaxx_span_ops = {
.chanconfig = wcaxx_chanconfig,
.dacs = wcaxx_dacs,
.assigned = wcaxx_assigned,
#ifdef VPM_SUPPORT
.echocan_create = wcaxx_echocan_create,
.echocan_name = wcaxx_echocan_name,
#endif
};
static struct wcaxx_chan *
@@ -3872,9 +3864,16 @@ static void wcaxx_back_out_gracefully(struct wcaxx *wc)
kfree(wc);
}
static void wcaxx_handle_error(struct wcxb *xb)
{
struct wcaxx *wc = container_of(xb, struct wcaxx, xb);
wc->ddev->irqmisses++;
}
static const struct wcxb_operations wcxb_operations = {
.handle_receive = wcaxx_handle_receive,
.handle_transmit = wcaxx_handle_transmit,
.handle_error = wcaxx_handle_error,
};
struct cmd_results {
@@ -3910,7 +3909,7 @@ static int wcaxx_check_firmware(struct wcaxx *wc)
}
return wcxb_check_firmware(&wc->xb, firmware_version,
filename, force_firmware);
filename, force_firmware, WCXB_RESET_NOW);
}
static void wcaxx_check_sethook(struct wcaxx *wc, struct wcaxx_module *mod)
@@ -4299,7 +4298,12 @@ __wcaxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENOMEM;
}
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", wc->desc->name);
if (wc->vpm)
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (%s)",
wc->desc->name, "VPMOCT032");
else
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s",
wc->desc->name);
if (!wc->ddev->devicetype) {
wcaxx_back_out_gracefully(wc);
@@ -4379,11 +4383,9 @@ static void __devexit wcaxx_remove_one(struct pci_dev *pdev)
flush_scheduled_work();
wcxb_stop(&wc->xb);
#ifdef VPM_SUPPORT
if (wc->vpm)
release_vpm450m(wc->vpm);
wc->vpm = NULL;
#endif
wcaxx_release(wc);
}
@@ -4522,9 +4524,7 @@ module_param(neonmwi_monitor, int, 0600);
module_param(neonmwi_level, int, 0600);
module_param(neonmwi_envelope, int, 0600);
module_param(neonmwi_offlimit, int, 0600);
#ifdef VPM_SUPPORT
module_param(vpmsupport, int, 0400);
#endif
module_param(forceload, int, 0600);
MODULE_PARM_DESC(forceload,

View File

@@ -1121,16 +1121,11 @@ static int t4_echocan_create(struct dahdi_chan *chan,
struct t4 *wc = chan->pvt;
struct t4_span *tspan = container_of(chan->span, struct t4_span, span);
int channel;
const struct dahdi_echocan_ops *ops;
const struct dahdi_echocan_features *features;
const bool alaw = (chan->span->deflaw == 2);
if (!vpmsupport || !wc->vpm)
return -ENODEV;
ops = &vpm_ec_ops;
features = &vpm_ec_features;
if (ecp->param_count > 0) {
dev_warn(&wc->dev->dev, "%s echo canceller does not support "
"parameters; failing request\n",
@@ -1139,8 +1134,8 @@ static int t4_echocan_create(struct dahdi_chan *chan,
}
*ec = tspan->ec[chan->chanpos - 1];
(*ec)->ops = ops;
(*ec)->features = *features;
(*ec)->ops = &vpm_ec_ops;
(*ec)->features = vpm_ec_features;
channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;

View File

@@ -3100,6 +3100,8 @@ wctdm_init_voicedaa(struct wctdm *wc, struct wctdm_module *mod,
spin_unlock_irqrestore(&wc->reglock, flags);
msleep(20);
memset(&mod->mod.fxo, 0, sizeof(mod->mod.fxo));
if (!sane && wctdm_voicedaa_insane(wc, mod))
return -2;
@@ -3244,8 +3246,7 @@ wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod,
return -2;
/* Initialize VMWI settings */
memset(&(fxs->vmwisetting), 0, sizeof(fxs->vmwisetting));
fxs->vmwi_linereverse = 0;
memset(fxs, 0, sizeof(*fxs));
/* By default, don't send on hook */
if (!reversepolarity != !fxs->reversepolarity)

View File

@@ -45,9 +45,8 @@
static const char *TE133_FW_FILENAME = "dahdi-fw-te133.bin";
static const char *TE134_FW_FILENAME = "dahdi-fw-te134.bin";
static const u32 TE13X_FW_VERSION = 0x6f0017;
static const u32 TE13X_FW_VERSION = 0x780017;
#define VPM_SUPPORT
#define WC_MAX_IFACES 8
enum linemode {
@@ -107,9 +106,7 @@ struct t13x {
struct timer_list timer;
struct work_struct timer_work;
struct workqueue_struct *wq;
#ifdef VPM_SUPPORT
struct vpm450m *vpm;
#endif
struct mutex lock;
struct wcxb xb;
};
@@ -118,10 +115,17 @@ static void te13x_handle_transmit(struct wcxb *xb, void *vfp);
static void te13x_handle_receive(struct wcxb *xb, void *vfp);
static void te13x_handle_interrupt(struct wcxb *xb, u32 pending);
static void te13x_handle_error(struct wcxb *xb)
{
struct t13x *wc = container_of(xb, struct t13x, xb);
wc->ddev->irqmisses++;
}
static struct wcxb_operations xb_ops = {
.handle_receive = te13x_handle_receive,
.handle_transmit = te13x_handle_transmit,
.handle_interrupt = te13x_handle_interrupt,
.handle_error = te13x_handle_error,
};
/* Maintenance Mode Registers */
@@ -178,6 +182,7 @@ static int yelalarmdebounce = 500; /* RAI(yellow) def to 0.5s AT&T devguide */
static char *default_linemode = "t1"; /* 'e1', 't1', or 'j1' */
static int force_firmware;
static int latency = WCXB_DEFAULT_LATENCY;
static unsigned int max_latency = WCXB_DEFAULT_MAXLATENCY;
struct t13x_firm_header {
u8 header[6];
@@ -190,7 +195,6 @@ struct t13x_firm_header {
static void t13x_check_alarms(struct t13x *wc);
static void t13x_check_sigbits(struct t13x *wc);
#ifdef VPM_SUPPORT
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
@@ -656,7 +660,7 @@ static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw,
}
}
if (vpmsupport != 0)
if (vpmsupport)
wcxb_enable_echocan(&wc->xb);
kfree(ChipOpen);
@@ -786,7 +790,6 @@ static void t13x_vpm_init(struct t13x *wc)
"VPM450: Present and operational servicing %d span\n", 1);
}
#endif /* VPM_SUPPORT */
static int t13x_clear_maint(struct dahdi_span *span);
@@ -796,8 +799,8 @@ struct t13x_desc {
const char *name;
};
static const struct t13x_desc te133 = {"Wildcard TE133"}; /* pci express */
static const struct t13x_desc te134 = {"Wildcard TE134"}; /* legacy pci */
static const struct t13x_desc te133 = {"Wildcard TE131/TE133"}; /* pci express*/
static const struct t13x_desc te134 = {"Wildcard TE132/TE134"}; /* legacy pci */
static inline bool is_pcie(const struct t13x *t1)
{
@@ -1251,25 +1254,6 @@ static void t13x_framer_start(struct t13x *wc)
set_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags);
}
static void set_span_devicetype(struct t13x *wc)
{
const char *olddevicetype;
olddevicetype = wc->ddev->devicetype;
#ifndef VPM_SUPPORT
wc->ddev->devicetype = kasprintf(GFP_KERNEL,
"%s (VPMOCT032)", wc->devtype->name);
#else
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", wc->devtype->name);
#endif /* VPM_SUPPORT */
/* On the off chance that we were able to allocate it previously. */
if (!wc->ddev->devicetype)
wc->ddev->devicetype = olddevicetype;
else
kfree(olddevicetype);
}
/**
* te13xp_check_for_interrupts - Return 0 if the card is generating interrupts.
* @wc: The card to check.
@@ -1307,8 +1291,6 @@ static int t13x_startup(struct file *file, struct dahdi_span *span)
unsigned long flags;
int ret;
set_span_devicetype(wc);
/* Stop the DMA since the clock source may have changed. */
wcxb_stop_dma(&wc->xb);
ret = wcxb_wait_for_stop(&wc->xb, 50);
@@ -1726,8 +1708,6 @@ static int t13x_software_init(struct t13x *wc, enum linemode type)
goto error_exit;
}
set_span_devicetype(wc);
/* Because the interrupt handler is running, we need to atomically
* swap the channel arrays. */
spin_lock_irqsave(&wc->reglock, flags);
@@ -1779,8 +1759,6 @@ static int t13x_software_init(struct t13x *wc, enum linemode type)
wc->chans[x]->chanpos = x + 1;
}
set_span_devicetype(wc);
return 0;
error_exit:
@@ -2211,7 +2189,7 @@ static void te13x_handle_receive(struct wcxb *xb, void *vfp)
}
}
if (0 == vpmsupport) {
if (!vpmsupport || !wc->vpm) {
for (i = 0; i < wc->span.channels; i++) {
struct dahdi_chan *const c = wc->span.chans[i];
__dahdi_ec_chunk(c, c->readchunk, c->readchunk,
@@ -2379,10 +2357,8 @@ static const struct dahdi_span_ops t13x_span_ops = {
.maint = t13x_maint,
.ioctl = t13x_ioctl,
.set_spantype = t13x_set_linemode,
#ifdef VPM_SUPPORT
.echocan_create = t13x_echocan_create,
.echocan_name = t13x_echocan_name,
#endif /* VPM_SUPPORT */
};
#define SPI_BASE 0x200
@@ -2455,6 +2431,26 @@ error_exit:
return serial;
}
static int te13xp_check_firmware(struct t13x *wc)
{
const char *filename;
enum wcxb_reset_option reset;
if (is_pcie(wc))
filename = TE133_FW_FILENAME;
else
filename = TE134_FW_FILENAME;
/* Specific firmware requires power cycle to properly reset */
if (0x6f0017 == wcxb_get_firmware_version(&wc->xb))
reset = WCXB_RESET_LATER;
else
reset = WCXB_RESET_NOW;
return wcxb_check_firmware(&wc->xb, TE13X_FW_VERSION, filename,
force_firmware, reset);
}
static int __devinit te13xp_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -2464,6 +2460,7 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
int res;
unsigned int index = -1;
enum linemode type;
bool vpmcapable = false;
for (x = 0; x < ARRAY_SIZE(ifaces); x++) {
if (!ifaces[x]) {
@@ -2532,24 +2529,26 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
wc->xb.pdev = pdev;
wc->xb.ops = &xb_ops;
wc->xb.debug = &debug;
res = wcxb_init(&wc->xb, wc->name, 1);
res = wcxb_init(&wc->xb, wc->name, 0);
if (res)
goto fail_exit;
/* Check for field updatable firmware */
if (is_pcie(wc)) {
res = wcxb_check_firmware(&wc->xb, TE13X_FW_VERSION,
TE133_FW_FILENAME, force_firmware);
if (res)
goto fail_exit;
} else {
res = wcxb_check_firmware(&wc->xb, TE13X_FW_VERSION,
TE134_FW_FILENAME, force_firmware);
if (res)
goto fail_exit;
}
res = te13xp_check_firmware(wc);
if (res)
goto fail_exit;
wc->ddev->hardware_id = t13x_read_serial(wc);
if (!wc->ddev->hardware_id) {
dev_info(&wc->dev->dev, "No serial number found.\n");
res = -EIO;
goto fail_exit;
}
/* Check for hardware echo cancel support */
if (!strncmp("TE133", wc->ddev->hardware_id+1, 5) ||
!strncmp("TE134", wc->ddev->hardware_id+1, 5)) {
vpmcapable = true;
}
wc->wq = create_singlethread_workqueue(wc->name);
if (!wc->wq) {
@@ -2573,6 +2572,9 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
goto fail_exit;
}
wcxb_set_minlatency(&wc->xb, latency);
wcxb_set_maxlatency(&wc->xb, max_latency);
create_sysfs_files(wc);
res = t13x_hardware_post_init(wc, &type);
@@ -2585,10 +2587,15 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
if (res)
goto fail_exit;
#ifdef VPM_SUPPORT
if (!wc->vpm)
if (!wc->vpm && vpmsupport && vpmcapable)
t13x_vpm_init(wc);
#endif
if (wc->vpm)
wc->ddev->devicetype = kasprintf(GFP_KERNEL,
"%s (VPMOCT032)", wc->devtype->name);
else
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s",
wc->devtype->name);
wc->span.ops = &t13x_span_ops;
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
@@ -2646,11 +2653,9 @@ static void __devexit te13xp_remove_one(struct pci_dev *pdev)
/* Turn off status LED */
t13x_setleds(wc, 0);
#ifdef VPM_SUPPORT
if (wc->vpm)
release_vpm450m(wc->vpm);
wc->vpm = NULL;
#endif
dahdi_unregister_device(wc->ddev);
@@ -2725,12 +2730,12 @@ module_param(alarmdebounce, int, S_IRUGO | S_IWUSR);
module_param(losalarmdebounce, int, S_IRUGO | S_IWUSR);
module_param(aisalarmdebounce, int, S_IRUGO | S_IWUSR);
module_param(yelalarmdebounce, int, S_IRUGO | S_IWUSR);
#ifdef VPM_SUPPORT
module_param(vpmsupport, int, 0600);
#endif
module_param(force_firmware, int, S_IRUGO);
module_param(latency, int, S_IRUGO);
MODULE_PARM_DESC(latency, "How many milliseconds of audio to buffer between card and host (3ms default). This number will increase during runtime, dynamically, if dahdi detects that it is too small. This is commonly refered to as a \"latency bump\"");
module_param(max_latency, int, 0600);
MODULE_PARM_DESC(max_latency, "The maximum amount of latency that the driver will permit.");
MODULE_DESCRIPTION("Wildcard Digital Card Driver");
MODULE_AUTHOR("Digium Incorporated <support@digium.com>");

View File

@@ -55,7 +55,6 @@ static const char *TE435_FW_FILENAME = "dahdi-fw-te435.bin";
static const u32 TE435_VERSION = 0xe0017;
/* #define RPC_RCLK */
#define VPM_SUPPORT
enum linemode {
T1 = 1,
@@ -129,10 +128,8 @@ struct t43x {
struct workqueue_struct *wq;
struct t43x_clksrc_work clksrc_work;
unsigned int not_ready; /* 0 when entire card is ready to go */
#ifdef VPM_SUPPORT
struct vpm450m *vpm;
char *vpm_name;
#endif
struct mutex lock;
bool latency_locked;
int syncsrc;
@@ -147,10 +144,17 @@ static void t43x_handle_transmit(struct wcxb *xb, void *vfp);
static void t43x_handle_receive(struct wcxb *xb, void *vfp);
static void t43x_handle_interrupt(struct wcxb *xb, u32 pending);
static void t43x_handle_error(struct wcxb *xb)
{
struct t43x *wc = container_of(xb, struct t43x, xb);
wc->ddev->irqmisses++;
}
static struct wcxb_operations xb_ops = {
.handle_receive = t43x_handle_receive,
.handle_transmit = t43x_handle_transmit,
.handle_interrupt = t43x_handle_interrupt,
.handle_error = t43x_handle_error,
};
/* Maintenance Mode Registers */
@@ -220,9 +224,6 @@ static void t43x_check_sigbits(struct t43x *wc, int span_idx);
static const struct dahdi_span_ops t43x_span_ops;
static void __t43x_set_timing_source_auto(struct t43x *wc);
#ifndef VPM_SUPPORT
static int vpmsupport;
#else
static int vpmsupport = 1;
#include "oct6100api/oct6100_api.h"
@@ -654,16 +655,11 @@ static int t43x_echocan_create(struct dahdi_chan *chan,
struct t43x *wc = chan->pvt;
struct t43x_span *ts = container_of(chan->span, struct t43x_span, span);
int channel = chan->chanpos - 1;
const struct dahdi_echocan_ops *ops;
const struct dahdi_echocan_features *features;
const bool alaw = (chan->span->deflaw == 2);
if (!vpmsupport || !wc->vpm)
return -ENODEV;
ops = &vpm_ec_ops;
features = &vpm_ec_features;
if (ecp->param_count > 0) {
dev_warn(&wc->xb.pdev->dev,
"%s echo canceller does not support parameters; failing request\n",
@@ -672,8 +668,8 @@ static int t43x_echocan_create(struct dahdi_chan *chan,
}
*ec = ts->ec[channel];
(*ec)->ops = ops;
(*ec)->features = *features;
(*ec)->ops = &vpm_ec_ops;
(*ec)->features = vpm_ec_features;
channel += (32*chan->span->offset);
vpm450m_set_alaw_companding(wc->vpm, channel, alaw);
@@ -772,7 +768,6 @@ static void t43x_vpm_init(struct t43x *wc)
wc->numspans);
}
#endif /* VPM_SUPPORT */
static int t43x_clear_maint(struct dahdi_span *span);
@@ -3164,10 +3159,8 @@ static const struct dahdi_span_ops t43x_span_ops = {
.ioctl = t43x_ioctl,
.assigned = t43x_span_assigned,
.set_spantype = t43x_set_linemode,
#ifdef VPM_SUPPORT
.echocan_create = t43x_echocan_create,
.echocan_name = t43x_echocan_name,
#endif /* VPM_SUPPORT */
};
/**
@@ -3327,7 +3320,7 @@ static int __devinit t43x_init_one(struct pci_dev *pdev,
wc->xb.ops = &xb_ops;
wc->xb.debug = &debug;
res = wcxb_init(&wc->xb, KBUILD_MODNAME, 1);
res = wcxb_init(&wc->xb, KBUILD_MODNAME, 0);
if (res)
goto fail_exit;
@@ -3364,7 +3357,7 @@ static int __devinit t43x_init_one(struct pci_dev *pdev,
/* Check for field updatable firmware */
res = wcxb_check_firmware(&wc->xb, TE435_VERSION,
TE435_FW_FILENAME, force_firmware);
TE435_FW_FILENAME, force_firmware, WCXB_RESET_NOW);
if (res)
goto fail_exit;
@@ -3416,7 +3409,6 @@ static int __devinit t43x_init_one(struct pci_dev *pdev,
t43x_init_spans(wc, type);
#ifdef VPM_SUPPORT
if (!wc->vpm)
t43x_vpm_init(wc);
@@ -3428,10 +3420,6 @@ static int __devinit t43x_init_one(struct pci_dev *pdev,
wc->ddev->devicetype = kasprintf(GFP_KERNEL,
"%s", wc->devtype->name);
}
#else
wc->ddev->devicetype = kasprintf(GFP_KERNEL,
"%s", wc->devtype->name);
#endif
res = dahdi_register_device(wc->ddev, &wc->xb.pdev->dev);
if (res) {
@@ -3484,11 +3472,9 @@ static void __devexit t43x_remove_one(struct pci_dev *pdev)
/* Turn off status LEDs */
t43x_setleds(wc, 0);
#ifdef VPM_SUPPORT
if (wc->vpm)
release_vpm450m(wc->vpm);
wc->vpm = NULL;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
cancel_work_sync(&wc->clksrc_work.work);
@@ -3574,9 +3560,7 @@ module_param(alarmdebounce, int, S_IRUGO | S_IWUSR);
module_param(losalarmdebounce, int, S_IRUGO | S_IWUSR);
module_param(aisalarmdebounce, int, S_IRUGO | S_IWUSR);
module_param(yelalarmdebounce, int, S_IRUGO | S_IWUSR);
#ifdef VPM_SUPPORT
module_param(vpmsupport, int, 0600);
#endif
module_param(force_firmware, int, S_IRUGO);
module_param(latency, int, S_IRUGO);
MODULE_PARM_DESC(latency, "How many milliseconds of audio to buffer between card and host (3ms default). This number will increase during runtime, dynamically, if dahdi detects that it is too small. This is commonly refered to as a \"latency bump\"");

View File

@@ -397,20 +397,32 @@ static irqreturn_t _wcxb_isr(int irq, void *dev_id)
if (pending & DESC_UNDERRUN) {
u32 reg;
/* Report the error in case drivers have any custom
* methods for indicating potential data corruption. An
* underrun means data loss in the TDM channel. */
if (xb->ops->handle_error)
xb->ops->handle_error(xb);
/* bump latency */
spin_lock(&xb->lock);
if (!xb->flags.latency_locked) {
xb->latency++;
xb->latency = min(xb->latency + 1,
xb->max_latency);
#ifdef HAVE_RATELIMIT
if (__ratelimit(&_underrun_rl)) {
#else
if (printk_ratelimit()) {
#endif
dev_info(&xb->pdev->dev,
"Underrun detected by hardware. Latency bumped to: %dms\n",
xb->latency);
if (xb->latency != xb->max_latency) {
dev_info(&xb->pdev->dev,
"Underrun detected by hardware. Latency bumped to: %dms\n",
xb->latency);
} else {
dev_info(&xb->pdev->dev,
"Underrun detected by hardware. Latency at max of %dms.\n",
xb->latency);
}
}
}
@@ -602,6 +614,8 @@ int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode)
return -EINVAL;
xb->latency = WCXB_DEFAULT_LATENCY;
xb->max_latency = WCXB_DEFAULT_MAXLATENCY;
spin_lock_init(&xb->lock);
xb->membase = pci_iomap(pdev, 0, 0);
@@ -778,7 +792,7 @@ struct wcxb_firm_header {
__le32 version;
} __packed;
static u32 wcxb_get_firmware_version(struct wcxb *xb)
u32 wcxb_get_firmware_version(struct wcxb *xb)
{
u32 version = 0;
@@ -793,7 +807,8 @@ static u32 wcxb_get_firmware_version(struct wcxb *xb)
}
static int wcxb_update_firmware(struct wcxb *xb, const struct firmware *fw,
const char *filename)
const char *filename,
enum wcxb_reset_option reset)
{
u32 tdm_control;
static const int APPLICATION_ADDRESS = 0x200000;
@@ -845,14 +860,20 @@ static int wcxb_update_firmware(struct wcxb *xb, const struct firmware *fw,
APPLICATION_ADDRESS + META_BLOCK_OFFSET,
&meta, sizeof(meta));
/* Reset fpga after loading firmware */
dev_info(&xb->pdev->dev, "Firmware load complete. Reseting device.\n");
tdm_control = ioread32be(xb->membase + TDM_CONTROL);
if (WCXB_RESET_NOW == reset) {
/* Reset fpga after loading firmware */
dev_info(&xb->pdev->dev,
"Firmware load complete. Reseting device.\n");
tdm_control = ioread32be(xb->membase + TDM_CONTROL);
wcxb_hard_reset(xb);
wcxb_hard_reset(xb);
iowrite32be(0, xb->membase + 0x04);
iowrite32be(tdm_control, xb->membase + TDM_CONTROL);
iowrite32be(0, xb->membase + 0x04);
iowrite32be(tdm_control, xb->membase + TDM_CONTROL);
} else {
dev_info(&xb->pdev->dev,
"Delaying reset. Firmware load requires a power cycle\n");
}
wcxb_spi_device_destroy(flash_spi_device);
wcxb_spi_master_destroy(flash_spi_master);
@@ -860,10 +881,16 @@ static int wcxb_update_firmware(struct wcxb *xb, const struct firmware *fw,
}
int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
const char *firmware_filename, bool force_firmware)
const char *firmware_filename, bool force_firmware,
enum wcxb_reset_option reset)
{
const struct firmware *fw;
const struct wcxb_firm_header *header;
static const int APPLICATION_ADDRESS = 0x200000;
static const int META_BLOCK_OFFSET = 0x170000;
struct wcxb_spi_master *flash_spi_master;
struct wcxb_spi_device *flash_spi_device;
struct wcxb_meta_block meta;
int res = 0;
u32 crc;
u32 version = 0;
@@ -882,6 +909,27 @@ int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
return 0;
}
/* Check meta firmware version for a not-booted application image */
flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev,
xb->membase + FLASH_SPI_BASE,
false);
flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0);
res = wcxb_flash_read(flash_spi_device,
APPLICATION_ADDRESS + META_BLOCK_OFFSET,
&meta, sizeof(meta));
if (res) {
dev_info(&xb->pdev->dev, "Unable to read flash\n");
return -EIO;
}
if ((meta.version == cpu_to_le32(expected_version))
&& !force_firmware) {
dev_info(&xb->pdev->dev,
"Detected previous firmware updated to current version %x, but not running. You likely need to power cycle your system.\n",
expected_version);
return 0;
}
if (force_firmware) {
dev_info(&xb->pdev->dev,
"force_firmware module parameter is set. Forcing firmware load, regardless of version\n");
@@ -924,12 +972,22 @@ int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
dev_info(&xb->pdev->dev, "Found %s (version: %x) Preparing for flash\n",
firmware_filename, header->version);
res = wcxb_update_firmware(xb, fw, firmware_filename);
res = wcxb_update_firmware(xb, fw, firmware_filename, reset);
version = wcxb_get_firmware_version(xb);
dev_info(&xb->pdev->dev, "Reset into firmware version: %x\n", version);
if (WCXB_RESET_NOW == reset) {
dev_info(&xb->pdev->dev,
"Reset into firmware version: %x\n", version);
} else {
dev_info(&xb->pdev->dev,
"Running firmware version: %x\n", version);
dev_info(&xb->pdev->dev,
"Loaded firmware version: %x (Will load after next power cycle)\n",
header->version);
}
if ((expected_version != version) && !force_firmware) {
if ((WCXB_RESET_NOW == reset) && (expected_version != version)
&& !force_firmware) {
/* On the off chance that the interface is in a state where it
* cannot boot into the updated firmware image, power cycling
* the card can recover. A simple "reset" of the computer is not

View File

@@ -105,9 +105,17 @@ static inline void wcxb_disable_timing_header_driver(struct wcxb *xb)
xb->flags.drive_timing_cable = 0;
}
enum wcxb_reset_option {
WCXB_RESET_NOW,
WCXB_RESET_LATER
};
extern u32 wcxb_get_firmware_version(struct wcxb *xb);
extern int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
const char *firmware_filename,
bool force_firmware);
bool force_firmware,
enum wcxb_reset_option reset);
extern void wcxb_stop_dma(struct wcxb *xb);
extern void wcxb_disable_interrupts(struct wcxb *xb);

View File

@@ -60,8 +60,8 @@ static DEF_PARM(uint, command_queue_length, 1500, 0444,
static DEF_PARM(uint, poll_timeout, 1000, 0644,
"Timeout (in jiffies) waiting for units to reply");
static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets");
static DEF_PARM_BOOL(dahdi_autoreg, 1, 0644,
"Register devices automatically (1) or not (0)");
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0444,
"Register devices automatically (1) or not (0). UNUSED.");
#ifdef CONFIG_PROC_FS
static const struct file_operations xbus_read_proc_ops;
@@ -1118,7 +1118,7 @@ void xbus_populate(void *data)
*/
xbus_request_sync(xbus, SYNC_MODE_PLL);
elect_syncer("xbus_populate(end)"); /* FIXME: try to do it later */
if (dahdi_autoreg)
if (!auto_assign_spans)
xbus_register_dahdi_device(xbus);
out:
XBUS_DBG(DEVICES, xbus, "Leaving\n");
@@ -1977,6 +1977,10 @@ int __init xbus_core_init(void)
{
int ret = 0;
if (dahdi_autoreg == 1) {
NOTICE("WARNING: The dahdi_autoreg parameter is deprecated " \
"-- just set dahdi.auto_assign_spans=0\n");
}
initialize_xbuses_array();
#ifdef PROTOCOL_DEBUG
INFO("FEATURE: with PROTOCOL_DEBUG\n");

View File

@@ -941,6 +941,7 @@ struct dahdi_device {
const char *devicetype;
struct device dev;
unsigned int irqmisses;
struct timespec registration_time;
};
struct dahdi_span {
@@ -1279,6 +1280,7 @@ static inline void dahdi_ec_span(struct dahdi_span *span)
}
extern struct file_operations *dahdi_transcode_fops;
extern int auto_assign_spans;
/* Don't use these directly -- they're not guaranteed to
be there. */