Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a951dd5e32 | ||
|
|
8210fea5b3 | ||
|
|
a1ff3cb0c0 | ||
|
|
089b593b56 | ||
|
|
71867c3de7 | ||
|
|
61aeaf13ae | ||
|
|
f35e8aafb0 | ||
|
|
b3a6b91858 | ||
|
|
2e33bdc7b5 | ||
|
|
3755ec9bf2 | ||
|
|
47f0fde0f1 | ||
|
|
180a17a39c | ||
|
|
d1afa1b101 | ||
|
|
b4941f35ad | ||
|
|
a3578ca156 | ||
|
|
761e02da52 | ||
|
|
cb50ae1500 | ||
|
|
e9ec13dfa0 | ||
|
|
dfa8a0ebd3 | ||
|
|
6e10dbdfb6 | ||
|
|
2010bc6433 | ||
|
|
624f30bbf6 | ||
|
|
d7c0b0aba1 | ||
|
|
e10f740476 | ||
|
|
dc92bf05cd | ||
|
|
8557bb6786 | ||
|
|
5981b152de | ||
|
|
cbe92363ea | ||
|
|
43a3dbb484 | ||
|
|
9a00fc6321 | ||
|
|
db07e1b74d | ||
|
|
235d530fee | ||
|
|
dfa7304f51 | ||
|
|
08127e14f7 | ||
|
|
6e2698f4c1 | ||
|
|
c9481d30bb | ||
|
|
779d62791c | ||
|
|
8342a3d21b | ||
|
|
ba05e31c8a | ||
|
|
b6a8623203 | ||
|
|
354d88cd41 | ||
|
|
0efce00a09 | ||
|
|
67e422c1ef | ||
|
|
cbe4825d1a | ||
|
|
b5ac763f29 | ||
|
|
6341783cc8 | ||
|
|
ea04099e77 | ||
|
|
bc274e1b5d | ||
|
|
44a33126e0 | ||
|
|
3446cdca8f | ||
|
|
391ca2b7aa | ||
|
|
ec9d162344 | ||
|
|
7168b87cb5 | ||
|
|
f8a6f55e80 | ||
|
|
6c796d0774 | ||
|
|
9c65971863 | ||
|
|
2ac2338247 | ||
|
|
3096ffe955 | ||
|
|
039daca12e | ||
|
|
15ff405dc8 | ||
|
|
5e24d501c5 | ||
|
|
193c9e59a8 | ||
|
|
606dd58a47 | ||
|
|
adfd0910b7 | ||
|
|
a66db43356 | ||
|
|
6649a3a166 | ||
|
|
8256ba602e | ||
|
|
c8b0d91972 | ||
|
|
b6eb7ae6d8 | ||
|
|
f6edaf5cea | ||
|
|
f2a3c1c963 | ||
|
|
22f034a307 | ||
|
|
6593097586 | ||
|
|
e62f0f1835 | ||
|
|
e4fce6849a | ||
|
|
bc0c04fb13 | ||
|
|
45b4937a35 | ||
|
|
50f2fd15b6 | ||
|
|
665bf9feb6 | ||
|
|
b817c7625a | ||
|
|
6cebc1c1fb | ||
|
|
7ce8498465 | ||
|
|
d4868092bf | ||
|
|
06c45b7cd8 | ||
|
|
fdca6f36de | ||
|
|
02f6b4e7bd | ||
|
|
701ed41adf | ||
|
|
03b3ce1a10 | ||
|
|
2c4373972b | ||
|
|
2ecf700dd8 | ||
|
|
74e949c33a | ||
|
|
3efa9d8cd1 | ||
|
|
4cd09feb54 | ||
|
|
1f024713ed | ||
|
|
0b499d9566 | ||
|
|
438b2a36b3 | ||
|
|
be94aa11bb | ||
|
|
1add33efe7 | ||
|
|
094e30483d | ||
|
|
e4ea886ee0 | ||
|
|
860eb4ab48 | ||
|
|
47dcc9377c | ||
|
|
f10eb3f547 | ||
|
|
99de304d84 | ||
|
|
c49a56c954 | ||
|
|
e6b16eace1 | ||
|
|
3933ffd350 | ||
|
|
05bf6ac601 | ||
|
|
d536c3e203 |
26
README
26
README
@@ -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
|
||||
|
||||
123
build_tools/dkms-helper
Executable file
123
build_tools/dkms-helper
Executable file
@@ -0,0 +1,123 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
DKMS=$(which dkms)
|
||||
|
||||
usage() {
|
||||
echo "$(basename $0): Helper functions for DKMS (Dynamic Kernel Module Support)"
|
||||
echo "Usage: $0 [add|remove|generate_conf]"
|
||||
echo "Options:"
|
||||
echo " remove -a : Remove all versions of DAHDI for all kernels."
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo ""
|
||||
echo " build_tools/dkms-helper add"
|
||||
echo " Installs the current version of DAHDI into the DKMS system."
|
||||
echo ""
|
||||
echo " build_tools/dkms-helper remove"
|
||||
echo " Removes the current version of DAHDI from all kernels."
|
||||
echo ""
|
||||
echo " build_tools/dkms-helper generate_conf > dkms.conf"
|
||||
echo " Create a dkms.conf based on the currently compiled kernel"
|
||||
echo " modules. This is also done as part of add and is not"
|
||||
echo " normally needed as a separate step."
|
||||
echo ""
|
||||
echo "NOTE: Because firmware files could be different between different"
|
||||
echo "versions of DAHDI, and the firmware files are installed into the common"
|
||||
echo "/lib/firmware directory, you should remove a given version of DAHDI from all"
|
||||
echo "kernels before installing a new version of DAHDI to avoid potential"
|
||||
echo "conflicts."
|
||||
echo ""
|
||||
}
|
||||
|
||||
generate_configuration() {
|
||||
echo 'PACKAGE_NAME="dahdi-linux"'
|
||||
echo "PACKAGE_VERSION=\"$(build_tools/make_version .)\""
|
||||
echo 'MAKE="make KSRC=/lib/modules/${kernelver}/build"'
|
||||
echo 'CLEAN="make clean"'
|
||||
echo 'AUTOINSTALL="yes"'
|
||||
let "module_number=0" || true
|
||||
for file in $(find ./ -type f -name "*.ko"); do
|
||||
MODULE_LOCATION=$(dirname $file | cut -d\/ -f 2-)
|
||||
echo "BUILT_MODULE_NAME[$module_number]=\"$(basename $file .ko)\""
|
||||
echo "BUILT_MODULE_LOCATION[$module_number]=\"$MODULE_LOCATION\""
|
||||
echo "DEST_MODULE_LOCATION[$module_number]=\"/kernel/dahdi/$(echo $MODULE_LOCATION | cut -d\/ -f 3-)\""
|
||||
let "module_number=${module_number}+1" || true
|
||||
done
|
||||
if [ $module_number -eq 0 ]; then
|
||||
echo "WARNING: You should build the modules before generating a config." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
add() {
|
||||
GIT=$(which git)
|
||||
VERSION="$(build_tools/make_version .)"
|
||||
if [ $(id -u) != "0" ]; then
|
||||
echo "You must run $0 as root."
|
||||
exit 1
|
||||
fi
|
||||
echo "Building for version ${VERSION}"
|
||||
make > /dev/null
|
||||
echo "Copying to /usr/src/dahdi-linux-${VERSION}"
|
||||
if [ ! -d /usr/src/dahdi-linux-${VERSION} ]; then
|
||||
if [ -d .git ]; then
|
||||
${GIT} checkout-index -a --prefix=/usr/src/dahdi-linux-${VERSION}/
|
||||
else
|
||||
cp -f -r * /usr/src/dahdi-linux-${VERSION}/
|
||||
fi
|
||||
fi
|
||||
make -C /usr/src/dahdi-linux-${VERSION} install-firmware firmware-loaders
|
||||
build_tools/dkms-helper generate_conf > /usr/src/dahdi-linux-${VERSION}/dkms.conf
|
||||
echo $VERSION > /usr/src/dahdi-linux-${VERSION}/.version
|
||||
${DKMS} add -m dahdi-linux -v ${VERSION}
|
||||
${DKMS} build -m dahdi-linux -v ${VERSION}
|
||||
${DKMS} install --force -m dahdi-linux -v ${VERSION}
|
||||
}
|
||||
|
||||
remove() {
|
||||
if [ $(id -u) != "0" ]; then
|
||||
echo "You must run $0 as root."
|
||||
exit 1
|
||||
fi
|
||||
REMOVE_ALL=false
|
||||
shift
|
||||
while getopts "a" opt; do
|
||||
case $opt in
|
||||
a) REMOVE_ALL=true ;;
|
||||
*) echo "Unknown option to remove" ; exit 1;;
|
||||
esac
|
||||
done
|
||||
if [ $REMOVE_ALL == true ]; then
|
||||
# Remove all installed dahdi versions for all kernels.
|
||||
for version in $(${DKMS} status -m dahdi-linux | cut -d, -f 2 | sed -e "s/^\s\+//"); do
|
||||
echo "Removing version ${version}"
|
||||
${DKMS} remove -m dahdi-linux -v ${version} --all
|
||||
rm -f -r /usr/src/dahdi-linux-${version}
|
||||
done
|
||||
else
|
||||
# Just remove the version for the current tree.
|
||||
GIT=$(which git)
|
||||
VERSION="$(build_tools/make_version .)"
|
||||
${DKMS} remove -m dahdi-linux -v ${VERSION} --all
|
||||
if [ -e /usr/src/dahdi-linux-${VERSION}/dkms.conf ]; then
|
||||
rm -f -r /usr/src/dahdi-linux-${VERSION}
|
||||
else
|
||||
echo "/usr/src/dahdi-linux-${VERSION} not a dkms dir?"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Run the command...
|
||||
shift $(($OPTIND-1))
|
||||
COMMAND=$1
|
||||
case $COMMAND in
|
||||
add) add $*; exit $? ;;
|
||||
remove) remove $* ; exit $? ;;
|
||||
generate_conf) generate_configuration; exit $? ;;
|
||||
*) echo "unknown command $0" ; usage; exit 1;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
21
build_tools/install_firmware
Executable file
21
build_tools/install_firmware
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
# This is a helper script intended to be called from
|
||||
# drivers/dahdi/firmware/Makefile to install the different firmware version.
|
||||
|
||||
FIRMWARE_PATTERN=$1
|
||||
FIRMWARE_VERSION=$2
|
||||
DESTDIR=$3
|
||||
target="$DESTDIR/lib/firmware"
|
||||
|
||||
if ! test -f $target/.${FIRMWARE_PATTERN}-${FIRMWARE_VERSION}; then
|
||||
echo "Installing ${FIRMWARE_PATTERN}.bin to $target"
|
||||
tar --no-same-owner -xf ${FIRMWARE_PATTERN}-${FIRMWARE_VERSION}.tar.gz || exit 1
|
||||
install -m 644 ${FIRMWARE_PATTERN}.bin $target || exit 1
|
||||
rm -rf $target/.${FIRMWARE_PATTERN}-*
|
||||
touch $target/.${FIRMWARE_PATTERN}-${FIRMWARE_VERSION}
|
||||
# Remove the .bin file so that if the version is reverted, it will not
|
||||
# be installed with a non-matching ${FIRMARE_VERSION} file.
|
||||
rm ${FIRMWARE_PATTERN}.bin
|
||||
else
|
||||
echo "Firmware ${FIRMWARE_PATTERN}.bin is already installed with required version ${FIRMWARE_VERSION}"
|
||||
fi
|
||||
@@ -50,6 +50,8 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#if defined(HAVE_UNLOCKED_IOCTL) && defined(CONFIG_BKL)
|
||||
#include <linux/smp_lock.h>
|
||||
@@ -989,10 +991,13 @@ static int dahdi_seq_show(struct seq_file *sfile, void *data)
|
||||
|
||||
seq_fill_alarm_string(sfile, chan->chan_alarms);
|
||||
|
||||
if (chan->ec_factory)
|
||||
mutex_lock(&chan->mutex);
|
||||
if (chan->ec_factory) {
|
||||
seq_printf(sfile, "(EC: %s - %s) ",
|
||||
chan->ec_factory->get_name(chan),
|
||||
chan->ec_state ? "ACTIVE" : "INACTIVE");
|
||||
}
|
||||
mutex_unlock(&chan->mutex);
|
||||
|
||||
seq_printf(sfile, "\n");
|
||||
}
|
||||
@@ -1487,14 +1492,13 @@ static const struct dahdi_echocan_factory hwec_factory = {
|
||||
static int dahdi_enable_hw_preechocan(struct dahdi_chan *chan)
|
||||
{
|
||||
int res;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
mutex_lock(&chan->mutex);
|
||||
if (chan->ec_factory != &hwec_factory)
|
||||
res = -ENODEV;
|
||||
else
|
||||
res = 0;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
mutex_unlock(&chan->mutex);
|
||||
|
||||
if (-ENODEV == res)
|
||||
return 0;
|
||||
@@ -1807,6 +1811,17 @@ static int start_tone(struct dahdi_chan *chan, int tone)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* stop_tone - Stops any tones on a channel.
|
||||
*
|
||||
* Must be called with chan->lock held.
|
||||
*
|
||||
*/
|
||||
static inline int stop_tone(struct dahdi_chan *chan)
|
||||
{
|
||||
return start_tone(chan, -1);
|
||||
}
|
||||
|
||||
static int set_tone_zone(struct dahdi_chan *chan, int zone)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -1834,6 +1849,9 @@ static int set_tone_zone(struct dahdi_chan *chan, int zone)
|
||||
return -ENODATA;
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
|
||||
stop_tone(chan);
|
||||
|
||||
if (chan->curzone) {
|
||||
struct dahdi_zone *zone = chan->curzone;
|
||||
chan->curzone = NULL;
|
||||
@@ -1882,6 +1900,7 @@ static void __dahdi_init_chan(struct dahdi_chan *chan)
|
||||
might_sleep();
|
||||
|
||||
spin_lock_init(&chan->lock);
|
||||
mutex_init(&chan->mutex);
|
||||
init_waitqueue_head(&chan->waitq);
|
||||
if (!chan->master)
|
||||
chan->master = chan;
|
||||
@@ -2300,10 +2319,10 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan)
|
||||
*/
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
mutex_lock(&chan->mutex);
|
||||
release_echocan(chan->ec_factory);
|
||||
chan->ec_factory = NULL;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
mutex_unlock(&chan->mutex);
|
||||
|
||||
#ifdef CONFIG_DAHDI_NET
|
||||
if (dahdi_have_netdev(chan)) {
|
||||
@@ -3052,57 +3071,64 @@ static const struct file_operations dahdi_chan_fops;
|
||||
|
||||
static int dahdi_specchan_open(struct file *file)
|
||||
{
|
||||
int res = 0;
|
||||
int res = -ENXIO;
|
||||
struct dahdi_chan *const chan = chan_from_file(file);
|
||||
|
||||
if (chan && chan->sig) {
|
||||
/* Make sure we're not already open, a net device, or a slave device */
|
||||
if (dahdi_have_netdev(chan))
|
||||
res = -EBUSY;
|
||||
else if (chan->master != chan)
|
||||
res = -EBUSY;
|
||||
else if ((chan->sig & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS)
|
||||
res = -EBUSY;
|
||||
else if (!test_and_set_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) {
|
||||
unsigned long flags;
|
||||
res = initialize_channel(chan);
|
||||
if (res) {
|
||||
/* Reallocbufs must have failed */
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
|
||||
return res;
|
||||
}
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if (is_pseudo_chan(chan))
|
||||
chan->flags |= DAHDI_FLAG_AUDIO;
|
||||
if (chan->span) {
|
||||
const struct dahdi_span_ops *const ops =
|
||||
chan->span->ops;
|
||||
if (!try_module_get(ops->owner)) {
|
||||
res = -ENXIO;
|
||||
} else if (ops->open) {
|
||||
res = ops->open(chan);
|
||||
if (res)
|
||||
module_put(ops->owner);
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
chan->file = file;
|
||||
file->private_data = chan;
|
||||
/* Since we know we're a channel now, we can
|
||||
* update the f_op pointer and bypass a few of
|
||||
* the checks on the minor number. */
|
||||
file->f_op = &dahdi_chan_fops;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
close_channel(chan);
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
|
||||
}
|
||||
} else {
|
||||
res = -EBUSY;
|
||||
if (!chan || !chan->sig)
|
||||
return -ENXIO;
|
||||
|
||||
/* Make sure we're not already open, a net device, or a slave
|
||||
* device */
|
||||
if (dahdi_have_netdev(chan))
|
||||
res = -EBUSY;
|
||||
else if (chan->master != chan)
|
||||
res = -EBUSY;
|
||||
else if ((chan->sig & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS)
|
||||
res = -EBUSY;
|
||||
else if (!test_and_set_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) {
|
||||
unsigned long flags;
|
||||
const struct dahdi_span_ops *const ops =
|
||||
(!is_pseudo_chan(chan)) ? chan->span->ops : NULL;
|
||||
|
||||
if (ops && !try_module_get(ops->owner)) {
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
|
||||
return -ENXIO;
|
||||
}
|
||||
} else
|
||||
res = -ENXIO;
|
||||
|
||||
res = initialize_channel(chan);
|
||||
if (res) {
|
||||
/* Reallocbufs must have failed */
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if (is_pseudo_chan(chan))
|
||||
chan->flags |= DAHDI_FLAG_AUDIO;
|
||||
chan->file = file;
|
||||
file->private_data = chan;
|
||||
/* Since we know we're a channel now, we can
|
||||
* update the f_op pointer and bypass a few of
|
||||
* the checks on the minor number. */
|
||||
file->f_op = &dahdi_chan_fops;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
if (ops && ops->open) {
|
||||
res = ops->open(chan);
|
||||
if (res) {
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
chan->file = NULL;
|
||||
file->private_data = NULL;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
module_put(ops->owner);
|
||||
close_channel(chan);
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN,
|
||||
&chan->flags);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = -EBUSY;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -5224,7 +5250,6 @@ static bool dahdi_is_hwec_available(const struct dahdi_chan *chan)
|
||||
|
||||
static int dahdi_ioctl_attach_echocan(unsigned long data)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct dahdi_chan *chan;
|
||||
struct dahdi_attach_echocan ae;
|
||||
const struct dahdi_echocan_factory *new = NULL, *old;
|
||||
@@ -5266,10 +5291,10 @@ static int dahdi_ioctl_attach_echocan(unsigned long data)
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
mutex_lock(&chan->mutex);
|
||||
old = chan->ec_factory;
|
||||
chan->ec_factory = new;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
mutex_unlock(&chan->mutex);
|
||||
|
||||
if (old)
|
||||
release_echocan(old);
|
||||
@@ -6329,6 +6354,7 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
|
||||
if (ecp->tap_length == 0) {
|
||||
/* disable mode, don't need to inspect params */
|
||||
mutex_lock(&chan->mutex);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
ec_state = chan->ec_state;
|
||||
chan->ec_state = NULL;
|
||||
@@ -6339,7 +6365,7 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
ec_state->ops->echocan_free(chan, ec_state);
|
||||
release_echocan(ec_current);
|
||||
}
|
||||
|
||||
mutex_unlock(&chan->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6356,6 +6382,7 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
goto exit_with_free;
|
||||
}
|
||||
|
||||
mutex_lock(&chan->mutex);
|
||||
/* free any echocan that may be on the channel already */
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
ec_state = chan->ec_state;
|
||||
@@ -6426,6 +6453,7 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
}
|
||||
|
||||
exit_with_free:
|
||||
mutex_unlock(&chan->mutex);
|
||||
kfree(params);
|
||||
|
||||
return ret;
|
||||
@@ -7188,13 +7216,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 +7276,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 +7288,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) ||
|
||||
@@ -7372,6 +7404,15 @@ int dahdi_assign_device_spans(struct dahdi_device *ddev)
|
||||
static int auto_assign_spans = 1;
|
||||
static const char *UNKNOWN = "";
|
||||
|
||||
/**
|
||||
* dahdi_auto_assign_spans - is the parameter auto_assign_spans set?
|
||||
*/
|
||||
int dahdi_get_auto_assign_spans(void)
|
||||
{
|
||||
return auto_assign_spans;
|
||||
}
|
||||
EXPORT_SYMBOL(dahdi_get_auto_assign_spans);
|
||||
|
||||
/**
|
||||
* _dahdi_register_device - Registers a DAHDI device and assign its spans.
|
||||
* @ddev: the DAHDI device
|
||||
@@ -7399,6 +7440,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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -168,8 +168,9 @@ static void dtc_release(struct dahdi_transcoder_channel *chan)
|
||||
BUG_ON(!chan);
|
||||
if (chan->parent && chan->parent->release) {
|
||||
chan->parent->release(chan);
|
||||
} else {
|
||||
dahdi_tc_clear_busy(chan);
|
||||
}
|
||||
dahdi_tc_clear_busy(chan);
|
||||
}
|
||||
|
||||
static int dahdi_tc_release(struct inode *inode, struct file *file)
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <linux/pkt_sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <net/syncppp.h>
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@ VPMADT032_VERSION:=1.25.0
|
||||
HX8_VERSION:=2.06
|
||||
VPMOCT032_VERSION:=1.12.0
|
||||
WCT820_VERSION:=1.76
|
||||
TE133_VERSION:=6f0017
|
||||
TE134_VERSION:=6f0017
|
||||
TE435_VERSION:=e0017
|
||||
TE133_VERSION:=780019
|
||||
TE134_VERSION:=780017
|
||||
TE435_VERSION:=e0019
|
||||
A8A_VERSION:=1d0017
|
||||
A8B_VERSION:=1d0017
|
||||
A8B_VERSION:=1d0019
|
||||
A4A_VERSION:=a0017
|
||||
A4B_VERSION:=b0017
|
||||
A4B_VERSION:=b0019
|
||||
|
||||
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
|
||||
|
||||
@@ -82,6 +82,8 @@ OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032.o)
|
||||
# Force usage of wget, for now
|
||||
DOWNLOAD=wget
|
||||
WGET=wget
|
||||
INSTALL_FIRMWARE=../../../build_tools/install_firmware
|
||||
RUN_INST=$(INSTALL_FIRMWARE) $(1) $(2) $(DESTDIR)
|
||||
|
||||
# If "fetch" is used, --continue is not a valid option.
|
||||
ifeq ($(WGET),wget)
|
||||
@@ -107,7 +109,6 @@ dahdi-fw-%.tar.gz:
|
||||
echo "Attempting to download $@"; \
|
||||
if test ! -f $@; then $(DOWNLOAD) $(WGET_ARGS) $(FIRMWARE_URL)/$@; fi; \
|
||||
if test ! -f $@; then exit 1; fi; \
|
||||
(cat $@ | gzip -d | tar --no-same-owner -xf -) \
|
||||
fi
|
||||
|
||||
firmware-loaders: $(FWLOADERS)
|
||||
@@ -126,172 +127,21 @@ $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware:
|
||||
|
||||
# Install all downloaded firmware images for hotplug usage
|
||||
hotplug-install: $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware $(FIRMWARE)
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-oct6114-032.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-oct6114-032.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION)
|
||||
@install -m 644 dahdi-fw-oct6114-032.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-032.bin is already installed with required version $(OCT6114_032_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-oct6114-064.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-oct6114-064.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION)
|
||||
@install -m 644 dahdi-fw-oct6114-064.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-064.bin is already installed with required version $(OCT6114_064_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-oct6114-128.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-oct6114-128.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION)
|
||||
@install -m 644 dahdi-fw-oct6114-128.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-128.bin is already installed with required version $(OCT6114_128_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-oct6114-256.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
|
||||
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-256.bin is already installed with required version $(OCT6114_256_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-tc400m.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION)
|
||||
@install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-tc400m.bin is already installed with required version $(TC400M_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-hx8-$(HX8_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-hx8-$(HX8_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-hx8.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-hx8.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-hx8-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-hx8-$(HX8_VERSION)
|
||||
@install -m 644 dahdi-fw-hx8.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-hx8-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-hx8-$(HX8_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-hx8.bin is already installed with required version $(HX8_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-vpmoct032.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-vpmoct032.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION)
|
||||
@install -m 644 dahdi-fw-vpmoct032.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-vpmoct032-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-vpmoct032.bin is already installed with required version $(VPMOCT032_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-te820.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
|
||||
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te820-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-te820.bin is already installed with required version $(WCT820_VERSION)"
|
||||
endif
|
||||
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-$(TE133_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te133-$(TE133_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-te133.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-te133.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-$(TE133_VERSION)
|
||||
@install -m 644 dahdi-fw-te133.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te133-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te133-$(TE133_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-te133.bin is already installed with required version $(TE133_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE134_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te134-$(TE134_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-te134.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-te134.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE134_VERSION)
|
||||
@install -m 644 dahdi-fw-te134.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te134-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te134-$(TE134_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-te134.bin is already installed with required version $(TE134_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te435-$(TE435_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te435-$(TE435_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-te435.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-te435.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te435-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te435-$(TE435_VERSION)
|
||||
@install -m 644 dahdi-fw-te435.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te435-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te435-$(TE435_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-te435.bin is already installed with required version $(TE435_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8a-$(A8A_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a8a-$(A8A_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-a8a.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-a8a.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8a-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8a-$(A8A_VERSION)
|
||||
@install -m 644 dahdi-fw-a8a.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a8a-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a8a-$(A8A_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-a8a.bin is already installed with required version $(A8A_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8b-$(A8B_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a8b-$(A8B_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-a8b.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-a8b.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8b-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8b-$(A8B_VERSION)
|
||||
@install -m 644 dahdi-fw-a8b.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a8b-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a8b-$(A8B_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-a8b.bin is already installed with required version $(A8B_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4a-$(A4A_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a4a-$(A4A_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-a4a.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-a4a.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4a-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4a-$(A4A_VERSION)
|
||||
@install -m 644 dahdi-fw-a4a.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a4a-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a4a-$(A4A_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-a4a.bin is already installed with required version $(A4A_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4b-$(A4B_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a4b-$(A4B_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-a4b.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-a4b.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4b-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4b-$(A4B_VERSION)
|
||||
@install -m 645 dahdi-fw-a4b.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a4b-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a4b-$(A4B_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-a4b.bin is already installed with required version $(A4B_VERSION)"
|
||||
endif
|
||||
@$(call RUN_INST,dahdi-fw-oct6114-032,$(OCT6114_032_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-oct6114-064,$(OCT6114_064_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-oct6114-128,$(OCT6114_128_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-oct6114-256,$(OCT6114_256_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-tc400m,$(TC400M_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-hx8,$(HX8_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-vpmoct032,$(VPMOCT032_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-te820,$(WCT820_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-te133,$(TE133_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-te134,$(TE134_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-te435,$(TE435_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-a8a,$(A8A_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-a8b,$(A8B_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-a4a,$(A4A_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-a4b,$(A4B_VERSION))
|
||||
|
||||
# Uninstall any installed dahdi firmware images from hotplug firmware directories
|
||||
hotplug-uninstall:
|
||||
|
||||
@@ -129,7 +129,7 @@ $Octasic_Revision: 16 $
|
||||
/***************************** TYPES ***************************************/
|
||||
|
||||
/*Change this type if your platform uses 64bits semaphores/locks */
|
||||
typedef UINT32 tOCT6100_USER_SERIAL_OBJECT;
|
||||
typedef void* tOCT6100_USER_SERIAL_OBJECT;
|
||||
|
||||
typedef struct _OCT6100_GET_TIME_
|
||||
{
|
||||
|
||||
@@ -59,29 +59,38 @@ UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource,
|
||||
UINT32 Oct6100UserCreateSerializeObject(
|
||||
tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
|
||||
{
|
||||
struct oct612x_context *context = f_pCreate->pProcessContext;
|
||||
struct mutex *lock = kzalloc(sizeof(*lock), GFP_KERNEL);
|
||||
if (!lock) {
|
||||
dev_err(context->dev, "Out of memory in %s.\n", __func__);
|
||||
return cOCT6100_ERR_BASE;
|
||||
}
|
||||
mutex_init(lock);
|
||||
f_pCreate->ulSerialObjHndl = lock;
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDestroySerializeObject(
|
||||
tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
|
||||
{
|
||||
#ifdef OCTASIC_DEBUG
|
||||
pr_debug("I should never be called! (destroy serialize object)\n");
|
||||
#endif
|
||||
struct mutex *lock = f_pDestroy->ulSerialObjHndl;
|
||||
kfree(lock);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserSeizeSerializeObject(
|
||||
tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
|
||||
{
|
||||
/* Not needed */
|
||||
struct mutex *lock = f_pSeize->ulSerialObjHndl;
|
||||
mutex_lock(lock);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserReleaseSerializeObject(
|
||||
tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
|
||||
{
|
||||
/* Not needed */
|
||||
struct mutex *lock = f_pRelease->ulSerialObjHndl;
|
||||
mutex_unlock(lock);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@ With driver: 303826 (1.5 %)
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/delay.h>
|
||||
|
||||
@@ -480,8 +482,6 @@ static void rbi_out(struct pciradio *rad, int n, unsigned char *rbicmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
int x;
|
||||
DECLARE_WAIT_QUEUE_HEAD(mywait);
|
||||
|
||||
|
||||
for(;;)
|
||||
{
|
||||
@@ -489,7 +489,8 @@ DECLARE_WAIT_QUEUE_HEAD(mywait);
|
||||
x = rad->remote_locked || (__pciradio_getcreg(rad,0xc) & 2);
|
||||
if (!x) rad->remote_locked = 1;
|
||||
spin_unlock_irqrestore(&rad->lock,flags);
|
||||
if (x) interruptible_sleep_on_timeout(&mywait,2);
|
||||
if (x)
|
||||
msleep_interruptible(20);
|
||||
else break;
|
||||
}
|
||||
spin_lock_irqsave(&rad->lock,flags);
|
||||
@@ -526,7 +527,6 @@ static void mx828_command(struct pciradio *rad,int channel, unsigned char comman
|
||||
|
||||
static void mx828_command_wait(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2)
|
||||
{
|
||||
DECLARE_WAIT_QUEUE_HEAD(mywait);
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
@@ -534,7 +534,7 @@ unsigned long flags;
|
||||
while(rad->encdec.state)
|
||||
{
|
||||
spin_unlock_irqrestore(&rad->lock,flags);
|
||||
interruptible_sleep_on_timeout(&mywait,2);
|
||||
msleep_interruptible(20);
|
||||
spin_lock_irqsave(&rad->lock,flags);
|
||||
}
|
||||
rad->encdec.lastcmd = jiffies + 1000;
|
||||
@@ -966,7 +966,6 @@ static int pciradio_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned lo
|
||||
} stack;
|
||||
|
||||
struct pciradio *rad = chan->pvt;
|
||||
DECLARE_WAIT_QUEUE_HEAD(mywait);
|
||||
|
||||
switch (cmd) {
|
||||
case DAHDI_RADIO_GETPARAM:
|
||||
@@ -1254,7 +1253,7 @@ static int pciradio_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned lo
|
||||
__pciradio_setcreg(rad,8,byte2);
|
||||
spin_unlock_irqrestore(&rad->lock,flags);
|
||||
if (i || (jiffies < rad->lastremcmd + 10))
|
||||
interruptible_sleep_on_timeout(&mywait,10);
|
||||
msleep_interruptible(100);
|
||||
rad->lastremcmd = jiffies;
|
||||
rbi_out(rad,chan->chanpos - 1,(unsigned char *)&stack.p.data);
|
||||
spin_lock_irqsave(&rad->lock,flags);
|
||||
@@ -1269,7 +1268,8 @@ static int pciradio_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned lo
|
||||
x = rad->remote_locked || (__pciradio_getcreg(rad,0xc) & 2);
|
||||
if (!x) rad->remote_locked = 1;
|
||||
spin_unlock_irqrestore(&rad->lock,flags);
|
||||
if (x) interruptible_sleep_on_timeout(&mywait,2);
|
||||
if (x)
|
||||
msleep_interruptible(20);
|
||||
else break;
|
||||
}
|
||||
spin_lock_irqsave(&rad->lock,flags);
|
||||
@@ -1286,14 +1286,14 @@ static int pciradio_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned lo
|
||||
__pciradio_setcreg(rad,8,byte2);
|
||||
spin_unlock_irqrestore(&rad->lock,flags);
|
||||
if (byte1 != byte2)
|
||||
interruptible_sleep_on_timeout(&mywait,3);
|
||||
msleep_interruptible(30);
|
||||
while (jiffies < rad->lastremcmd + 10)
|
||||
interruptible_sleep_on_timeout(&mywait,10);
|
||||
msleep_interruptible(100);
|
||||
rad->lastremcmd = jiffies;
|
||||
for(;;)
|
||||
{
|
||||
if (!(__pciradio_getcreg(rad,0xc) & 2)) break;
|
||||
interruptible_sleep_on_timeout(&mywait,2);
|
||||
msleep_interruptible(20);
|
||||
}
|
||||
spin_lock_irqsave(&rad->lock,flags);
|
||||
/* enable and address async serializer */
|
||||
@@ -1315,7 +1315,7 @@ static int pciradio_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned lo
|
||||
(!strchr((char *)rad->rxbuf,'\r'))))
|
||||
{
|
||||
spin_unlock_irqrestore(&rad->lock,flags);
|
||||
interruptible_sleep_on_timeout(&mywait,2);
|
||||
msleep_interruptible(20);
|
||||
spin_lock_irqsave(&rad->lock,flags);
|
||||
continue;
|
||||
}
|
||||
@@ -1335,7 +1335,7 @@ static int pciradio_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned lo
|
||||
while(rad->txlen && (rad->txindex < rad->txlen))
|
||||
{
|
||||
spin_unlock_irqrestore(&rad->lock,flags);
|
||||
interruptible_sleep_on_timeout(&mywait,2);
|
||||
msleep_interruptible(20);
|
||||
spin_lock_irqsave(&rad->lock,flags);
|
||||
}
|
||||
/* disable and un-address async serializer */
|
||||
@@ -1344,7 +1344,7 @@ static int pciradio_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned lo
|
||||
rad->remote_locked = 0;
|
||||
spin_unlock_irqrestore(&rad->lock,flags);
|
||||
if (rad->remmode[chan->chanpos - 1] == DAHDI_RADPAR_REM_SERIAL_ASCII)
|
||||
interruptible_sleep_on_timeout(&mywait,100);
|
||||
msleep_interruptible(1000);
|
||||
if (copy_to_user((__user void *) data, &stack.p, sizeof(stack.p))) return -EFAULT;
|
||||
return 0;
|
||||
default:
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
#define NEED_PCI_IDS
|
||||
@@ -253,16 +254,6 @@ static int tor2_chanconfig(struct file *file,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tor2_open(struct dahdi_chan *chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tor2_close(struct dahdi_chan *chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dahdi_span_ops tor2_span_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.spanconfig = tor2_spanconfig,
|
||||
@@ -271,8 +262,6 @@ static const struct dahdi_span_ops tor2_span_ops = {
|
||||
.shutdown = tor2_shutdown,
|
||||
.rbsbits = tor2_rbsbits,
|
||||
.maint = tor2_maint,
|
||||
.open = tor2_open,
|
||||
.close = tor2_close,
|
||||
.ioctl = tor2_ioctl,
|
||||
};
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#else
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
#include <dahdi/user.h>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "voicebus/vpmoct.h"
|
||||
#include "linux/firmware.h"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
|
||||
@@ -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 {
|
||||
@@ -3887,9 +3886,9 @@ static int wcaxx_check_firmware(struct wcaxx *wc)
|
||||
u32 firmware_version;
|
||||
const bool force_firmware = false;
|
||||
const unsigned int A4A_VERSION = 0x0a0017;
|
||||
const unsigned int A4B_VERSION = 0x0b0017;
|
||||
const unsigned int A4B_VERSION = 0x0b0019;
|
||||
const unsigned int A8A_VERSION = 0x1d0017;
|
||||
const unsigned int A8B_VERSION = 0x1d0017;
|
||||
const unsigned int A8B_VERSION = 0x1d0019;
|
||||
|
||||
if (wc->desc == &device_a8a) {
|
||||
firmware_version = A8A_VERSION;
|
||||
@@ -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,
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <linux/timer.h> /* timer_struct */
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
@@ -2429,7 +2430,7 @@ b4xxp_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int b4xxp_open(struct dahdi_chan *chan)
|
||||
static int _b4xxp_open(struct dahdi_chan *chan)
|
||||
{
|
||||
struct b4xxp *b4 = chan->pvt;
|
||||
struct b4xxp_span *bspan = &b4->spans[chan->span->offset];
|
||||
@@ -2443,6 +2444,15 @@ static int b4xxp_open(struct dahdi_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int b4xxp_open(struct dahdi_chan *chan)
|
||||
{
|
||||
unsigned long flags;
|
||||
int res;
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
res = _b4xxp_open(chan);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int b4xxp_close(struct dahdi_chan *chan)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
@@ -569,7 +570,7 @@ static inline struct wcfxo *wcfxo_from_span(struct dahdi_span *span)
|
||||
return container_of(span, struct wcfxo, span);
|
||||
}
|
||||
|
||||
static int wcfxo_open(struct dahdi_chan *chan)
|
||||
static int _wcfxo_open(struct dahdi_chan *chan)
|
||||
{
|
||||
struct wcfxo *wc = chan->pvt;
|
||||
if (wc->dead)
|
||||
@@ -578,6 +579,16 @@ static int wcfxo_open(struct dahdi_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcfxo_open(struct dahdi_chan *chan)
|
||||
{
|
||||
int res;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
res = _wcfxo_open(chan);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int wcfxo_watchdog(struct dahdi_span *span, int event)
|
||||
{
|
||||
printk(KERN_INFO "FXO: Restarting DMA\n");
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <dahdi/kernel.h>
|
||||
@@ -370,9 +371,14 @@ struct t4 {
|
||||
dma_addr_t writedma;
|
||||
void __iomem *membase; /* Base address of card */
|
||||
|
||||
/* Flags for our bottom half */
|
||||
#define T4_CHECK_VPM 0
|
||||
#define T4_LOADING_FW 1
|
||||
#define T4_STOP_DMA 2
|
||||
#define T4_CHECK_TIMING 3
|
||||
#define T4_CHANGE_LATENCY 4
|
||||
#define T4_IGNORE_LATENCY 5
|
||||
unsigned long checkflag;
|
||||
struct tasklet_struct t4_tlet;
|
||||
struct work_struct bh_work;
|
||||
/* Latency related additions */
|
||||
unsigned char rxident;
|
||||
unsigned char lastindex;
|
||||
@@ -548,8 +554,6 @@ static void t4_check_sigbits(struct t4 *wc, int span);
|
||||
|
||||
#define MAX_T4_CARDS 64
|
||||
|
||||
static void t4_isr_bh(unsigned long data);
|
||||
|
||||
static struct t4 *cards[MAX_T4_CARDS];
|
||||
|
||||
struct t8_firm_header {
|
||||
@@ -1121,16 +1125,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 +1138,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;
|
||||
|
||||
@@ -1833,16 +1832,6 @@ t4_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t4_open(struct dahdi_chan *chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t4_close(struct dahdi_chan *chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_span_devicetype(struct t4 *wc)
|
||||
{
|
||||
#ifdef VPM_SUPPORT
|
||||
@@ -2120,6 +2109,8 @@ static void free_wc(struct t4 *wc)
|
||||
{
|
||||
unsigned int x, y;
|
||||
|
||||
flush_scheduled_work();
|
||||
|
||||
for (x = 0; x < ARRAY_SIZE(wc->tspans); x++) {
|
||||
if (!wc->tspans[x])
|
||||
continue;
|
||||
@@ -2333,8 +2324,6 @@ static const struct dahdi_span_ops t4_gen1_span_ops = {
|
||||
.shutdown = t4_shutdown,
|
||||
.rbsbits = t4_rbsbits,
|
||||
.maint = t4_maint,
|
||||
.open = t4_open,
|
||||
.close = t4_close,
|
||||
.ioctl = t4_ioctl,
|
||||
.hdlc_hard_xmit = t4_hdlc_hard_xmit,
|
||||
.assigned = t4_span_assigned,
|
||||
@@ -2349,8 +2338,6 @@ static const struct dahdi_span_ops t4_gen2_span_ops = {
|
||||
.shutdown = t4_shutdown,
|
||||
.rbsbits = t4_rbsbits,
|
||||
.maint = t4_maint,
|
||||
.open = t4_open,
|
||||
.close = t4_close,
|
||||
.ioctl = t4_ioctl,
|
||||
.hdlc_hard_xmit = t4_hdlc_hard_xmit,
|
||||
.dacs = t4_dacs,
|
||||
@@ -2723,7 +2710,7 @@ static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlev
|
||||
if (lineconfig & DAHDI_CONFIG_AMI) {
|
||||
line = "AMI";
|
||||
/* workaround for errata #2 in ES v3 09-10-16 */
|
||||
fmr0 = (wc->falc31) ? 0xb0 : 0xa0;
|
||||
fmr0 = (is_octal(wc) || wc->falc31) ? 0xb0 : 0xa0;
|
||||
} else {
|
||||
line = "B8ZS";
|
||||
fmr0 = 0xf0;
|
||||
@@ -2822,7 +2809,7 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
|
||||
if (lineconfig & DAHDI_CONFIG_AMI) {
|
||||
line = "AMI";
|
||||
/* workaround for errata #2 in ES v3 09-10-16 */
|
||||
fmr0 = (wc->falc31) ? 0xb0 : 0xa0;
|
||||
fmr0 = (is_octal(wc) || wc->falc31) ? 0xb0 : 0xa0;
|
||||
} else {
|
||||
line = "HDB3";
|
||||
fmr0 = 0xf0;
|
||||
@@ -3309,8 +3296,6 @@ static void t4_check_sigbits(struct t4 *wc, int span)
|
||||
dev_notice(&wc->dev->dev, "Checking sigbits on span %d\n",
|
||||
span + 1);
|
||||
|
||||
if (!(ts->span.flags & DAHDI_FLAG_RUNNING))
|
||||
return;
|
||||
if (E1 == ts->linemode) {
|
||||
for (i = 0; i < 15; i++) {
|
||||
a = t4_framer_in(wc, span, 0x71 + i);
|
||||
@@ -3700,6 +3685,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
||||
struct t4_span *ts = wc->tspans[span];
|
||||
struct dahdi_chan *sigchan;
|
||||
unsigned long flags;
|
||||
bool recheck_sigbits = false;
|
||||
|
||||
|
||||
/* 1st gen cards isn't used interrupts */
|
||||
@@ -3725,6 +3711,8 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
||||
ts->span.count.ebit += __t4_framer_in(wc, span, EBCL_T);
|
||||
ts->span.count.be += __t4_framer_in(wc, span, BECL_T);
|
||||
ts->span.count.prbs = __t4_framer_in(wc, span, FRS1_T);
|
||||
if (DAHDI_RXSIG_INITIAL == ts->span.chans[0]->rxhooksig)
|
||||
recheck_sigbits = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
|
||||
@@ -3733,7 +3721,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
||||
ts->span.count.errsec += 1;
|
||||
}
|
||||
|
||||
if (isr0)
|
||||
if (isr0 & 0x08 || recheck_sigbits)
|
||||
t4_check_sigbits(wc, span);
|
||||
|
||||
if (E1 == ts->linemode) {
|
||||
@@ -4060,9 +4048,15 @@ static void t4_increase_latency(struct t4 *wc, int newlatency)
|
||||
|
||||
}
|
||||
|
||||
static void t4_isr_bh(unsigned long data)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void t4_work_func(void *data)
|
||||
{
|
||||
struct t4 *wc = (struct t4 *)data;
|
||||
struct t4 *wc = data;
|
||||
#else
|
||||
static void t4_work_func(struct work_struct *work)
|
||||
{
|
||||
struct t4 *wc = container_of(work, struct t4, bh_work);
|
||||
#endif
|
||||
|
||||
if (test_bit(T4_CHANGE_LATENCY, &wc->checkflag)) {
|
||||
if (wc->needed_latency != wc->numbufs) {
|
||||
@@ -4269,7 +4263,7 @@ static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
|
||||
|
||||
out:
|
||||
if (unlikely(test_bit(T4_CHANGE_LATENCY, &wc->checkflag) || test_bit(T4_CHECK_VPM, &wc->checkflag)))
|
||||
tasklet_schedule(&wc->t4_tlet);
|
||||
schedule_work(&wc->bh_work);
|
||||
|
||||
#ifndef ENABLE_WORKQUEUES
|
||||
__t4_pci_out(wc, WC_INTR, 0);
|
||||
@@ -5150,7 +5144,11 @@ static int __devinit t4_launch(struct t4 *wc)
|
||||
&wc->ddev->spans);
|
||||
}
|
||||
|
||||
tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&wc->bh_work, t4_work_func, wc);
|
||||
#else
|
||||
INIT_WORK(&wc->bh_work, t4_work_func);
|
||||
#endif
|
||||
|
||||
res = dahdi_register_device(wc->ddev, &wc->dev->dev);
|
||||
if (res) {
|
||||
|
||||
@@ -239,7 +239,7 @@ static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode)
|
||||
|
||||
if (vpm450m->ecmode[channel] == mode)
|
||||
return;
|
||||
modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC);
|
||||
modify = kzalloc(sizeof(*modify), GFP_ATOMIC);
|
||||
if (!modify) {
|
||||
printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setec!\n");
|
||||
return;
|
||||
@@ -269,7 +269,7 @@ void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute)
|
||||
return;
|
||||
}
|
||||
|
||||
modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_KERNEL);
|
||||
modify = kzalloc(sizeof(*modify), GFP_KERNEL);
|
||||
if (!modify) {
|
||||
printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setdtmf!\n");
|
||||
return;
|
||||
@@ -454,28 +454,27 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
struct vpm450m *vpm450m;
|
||||
int x,y,law;
|
||||
|
||||
if (!(vpm450m = kmalloc(sizeof(struct vpm450m), GFP_KERNEL)))
|
||||
vpm450m = kzalloc(sizeof(*vpm450m), GFP_KERNEL);
|
||||
if (!vpm450m)
|
||||
return NULL;
|
||||
|
||||
memset(vpm450m, 0, sizeof(struct vpm450m));
|
||||
vpm450m->context.dev = device;
|
||||
vpm450m->context.ops = &wct4xxp_oct612x_ops;
|
||||
|
||||
if (!(ChipOpen = kmalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL))) {
|
||||
ChipOpen = kzalloc(sizeof(*ChipOpen), GFP_KERNEL);
|
||||
if (!ChipOpen) {
|
||||
kfree(vpm450m);
|
||||
kfree(vpm450m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(ChipOpen, 0, sizeof(tOCT6100_CHIP_OPEN));
|
||||
|
||||
if (!(ChannelOpen = kmalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL))) {
|
||||
ChannelOpen = kzalloc(sizeof(*ChannelOpen), GFP_KERNEL);
|
||||
if (!ChannelOpen) {
|
||||
kfree(vpm450m);
|
||||
kfree(ChipOpen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(ChannelOpen, 0, sizeof(tOCT6100_CHANNEL_OPEN));
|
||||
|
||||
for (x = 0; x < ARRAY_SIZE(vpm450m->ecmode); x++)
|
||||
vpm450m->ecmode[x] = -1;
|
||||
|
||||
|
||||
@@ -131,13 +131,6 @@ struct t4_reg {
|
||||
unsigned int val;
|
||||
};
|
||||
|
||||
#define T4_CHECK_VPM 0
|
||||
#define T4_LOADING_FW 1
|
||||
#define T4_STOP_DMA 2
|
||||
#define T4_CHECK_TIMING 3
|
||||
#define T4_CHANGE_LATENCY 4
|
||||
#define T4_IGNORE_LATENCY 5
|
||||
|
||||
#define WCT4_GET_REGS _IOW(DAHDI_CODE, 60, struct t4_regs)
|
||||
#define WCT4_GET_REG _IOW(DAHDI_CODE, 61, struct t4_reg)
|
||||
#define WCT4_SET_REG _IOW(DAHDI_CODE, 62, struct t4_reg)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/io.h>
|
||||
#include "proslic.h"
|
||||
|
||||
@@ -2143,7 +2144,7 @@ static int wctdm_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long
|
||||
|
||||
}
|
||||
|
||||
static int wctdm_open(struct dahdi_chan *chan)
|
||||
static int _wctdm_open(struct dahdi_chan *chan)
|
||||
{
|
||||
struct wctdm *wc = chan->pvt;
|
||||
if (!(wc->cardflag & (1 << (chan->chanpos - 1))))
|
||||
@@ -2154,6 +2155,16 @@ static int wctdm_open(struct dahdi_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wctdm_open(struct dahdi_chan *chan)
|
||||
{
|
||||
unsigned long flags;
|
||||
int res;
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
res = _wctdm_open(chan);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline struct wctdm *wctdm_from_span(struct dahdi_span *span)
|
||||
{
|
||||
return container_of(span, struct wctdm, span);
|
||||
|
||||
@@ -55,6 +55,7 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -3100,6 +3101,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 +3247,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)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/ppp_defs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define FAST_HDLC_NEED_TABLES
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
@@ -224,7 +225,7 @@ static inline void __select_control(struct t1 *wc)
|
||||
}
|
||||
}
|
||||
|
||||
static int t1xxp_open(struct dahdi_chan *chan)
|
||||
static int _t1xxp_open(struct dahdi_chan *chan)
|
||||
{
|
||||
struct t1 *wc = chan->pvt;
|
||||
if (wc->dead)
|
||||
@@ -234,6 +235,16 @@ static int t1xxp_open(struct dahdi_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t1xxp_open(struct dahdi_chan *chan)
|
||||
{
|
||||
unsigned long flags;
|
||||
int res;
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
res = _t1xxp_open(chan);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __control_set_reg(struct t1 *wc, int reg, unsigned char val)
|
||||
{
|
||||
__select_control(wc);
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
@@ -45,9 +45,9 @@
|
||||
|
||||
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 TE133_FW_VERSION = 0x780019;
|
||||
static const u32 TE134_FW_VERSION = 0x780017;
|
||||
|
||||
#define VPM_SUPPORT
|
||||
#define WC_MAX_IFACES 8
|
||||
|
||||
enum linemode {
|
||||
@@ -73,7 +73,6 @@ enum linemode {
|
||||
#define FALC_INT (1<<3)
|
||||
|
||||
struct t13x {
|
||||
struct pci_dev *dev;
|
||||
spinlock_t reglock;
|
||||
|
||||
u8 latency;
|
||||
@@ -93,9 +92,10 @@ struct t13x {
|
||||
unsigned long loopuptimer;
|
||||
unsigned long loopdntimer;
|
||||
const char *name;
|
||||
#define INITIALIZED 1
|
||||
#define SHUTDOWN 2
|
||||
#define READY 3
|
||||
#define INITIALIZED 1
|
||||
#define SHUTDOWN 2
|
||||
#define READY 3
|
||||
#define HAVE_OPEN_CHANNELS 4
|
||||
unsigned long bit_flags;
|
||||
u32 ledstate;
|
||||
struct dahdi_device *ddev;
|
||||
@@ -107,21 +107,27 @@ 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;
|
||||
u32 lineconfig_fingerprint;
|
||||
};
|
||||
|
||||
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 +184,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 +197,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>
|
||||
@@ -533,23 +539,23 @@ static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw,
|
||||
|
||||
vpm450m = kzalloc(sizeof(struct vpm450m), GFP_KERNEL);
|
||||
if (!vpm450m) {
|
||||
dev_info(&wc->dev->dev, "Unable to allocate vpm450m struct\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Unable to allocate vpm450m struct\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vpm450m->context.dev = &wc->dev->dev;
|
||||
vpm450m->context.dev = &wc->xb.pdev->dev;
|
||||
vpm450m->context.ops = &t13x_oct612x_ops;
|
||||
|
||||
ChipOpen = kzalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL);
|
||||
if (!ChipOpen) {
|
||||
dev_info(&wc->dev->dev, "Unable to allocate ChipOpen\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Unable to allocate ChipOpen\n");
|
||||
kfree(vpm450m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ChannelOpen = kzalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL);
|
||||
if (!ChannelOpen) {
|
||||
dev_info(&wc->dev->dev, "Unable to allocate ChannelOpen\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Unable to allocate ChannelOpen\n");
|
||||
kfree(vpm450m);
|
||||
kfree(ChipOpen);
|
||||
return NULL;
|
||||
@@ -558,7 +564,7 @@ static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw,
|
||||
for (x = 0; x < ARRAY_SIZE(vpm450m->ecmode); x++)
|
||||
vpm450m->ecmode[x] = -1;
|
||||
|
||||
dev_info(&wc->dev->dev, "Echo cancellation for %d channels\n",
|
||||
dev_info(&wc->xb.pdev->dev, "Echo cancellation for %d channels\n",
|
||||
ECHOCAN_NUM_CHANS);
|
||||
|
||||
Oct6100ChipOpenDef(ChipOpen);
|
||||
@@ -620,14 +626,14 @@ static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw,
|
||||
/* Get the size of the OCT6100 instance structure. */
|
||||
ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize);
|
||||
if (ulResult != cOCT6100_ERR_OK) {
|
||||
dev_info(&wc->dev->dev, "Unable to get instance size: %x\n",
|
||||
dev_info(&wc->xb.pdev->dev, "Unable to get instance size: %x\n",
|
||||
ulResult);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vpm450m->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize);
|
||||
if (!vpm450m->pApiInstance) {
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Out of memory (can't allocate %d bytes)!\n",
|
||||
InstanceSize.ulApiInstanceSize);
|
||||
return NULL;
|
||||
@@ -637,7 +643,7 @@ static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw,
|
||||
oct_enable_dram(wc);
|
||||
ulResult = Oct6100ChipOpen(vpm450m->pApiInstance, ChipOpen);
|
||||
if (ulResult != cOCT6100_ERR_OK) {
|
||||
dev_info(&wc->dev->dev, "Unable to Oct6100ChipOpen: %x\n",
|
||||
dev_info(&wc->xb.pdev->dev, "Unable to Oct6100ChipOpen: %x\n",
|
||||
ulResult);
|
||||
return NULL;
|
||||
}
|
||||
@@ -647,7 +653,7 @@ static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw,
|
||||
for (i = 0; i < ECHOCAN_NUM_CHANS; i++) {
|
||||
ulResult = echocan_initialize_channel(vpm450m, i, isalaw);
|
||||
if (0 != ulResult) {
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Unable to echocan_initialize_channel: %x\n",
|
||||
ulResult);
|
||||
return NULL;
|
||||
@@ -656,7 +662,7 @@ static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw,
|
||||
}
|
||||
}
|
||||
|
||||
if (vpmsupport != 0)
|
||||
if (vpmsupport)
|
||||
wcxb_enable_echocan(&wc->xb);
|
||||
|
||||
kfree(ChipOpen);
|
||||
@@ -709,7 +715,7 @@ static int t13x_echocan_create(struct dahdi_chan *chan,
|
||||
features = &vpm_ec_features;
|
||||
|
||||
if (ecp->param_count > 0) {
|
||||
dev_warn(&wc->dev->dev, "%s echo canceller does not support parameters; failing request\n",
|
||||
dev_warn(&wc->xb.pdev->dev, "%s echo canceller does not support parameters; failing request\n",
|
||||
chan->ec_factory->get_name(chan));
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -747,14 +753,14 @@ static void t13x_vpm_init(struct t13x *wc)
|
||||
#endif
|
||||
|
||||
if (!vpmsupport) {
|
||||
dev_info(&wc->dev->dev, "VPM450: Support Disabled\n");
|
||||
dev_info(&wc->xb.pdev->dev, "VPM450: Support Disabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(HOTPLUG_FIRMWARE)
|
||||
if ((request_firmware(&firmware, oct032_firmware, &wc->dev->dev) != 0)
|
||||
|| !firmware) {
|
||||
dev_notice(&wc->dev->dev, "VPM450: firmware %s not available from userspace\n",
|
||||
if ((request_firmware(&firmware, oct032_firmware,
|
||||
&wc->xb.pdev->dev) != 0) || !firmware) {
|
||||
dev_notice(&wc->xb.pdev->dev, "VPM450: firmware %s not available from userspace\n",
|
||||
oct032_firmware);
|
||||
return;
|
||||
}
|
||||
@@ -773,7 +779,7 @@ static void t13x_vpm_init(struct t13x *wc)
|
||||
|
||||
wc->vpm = init_vpm450m(wc, companding, firmware);
|
||||
if (!wc->vpm) {
|
||||
dev_notice(&wc->dev->dev, "VPM450: Failed to initialize\n");
|
||||
dev_notice(&wc->xb.pdev->dev, "VPM450: Failed to initialize\n");
|
||||
if (firmware != &embedded_firmware)
|
||||
release_firmware(firmware);
|
||||
return;
|
||||
@@ -782,11 +788,10 @@ static void t13x_vpm_init(struct t13x *wc)
|
||||
if (firmware != &embedded_firmware)
|
||||
release_firmware(firmware);
|
||||
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"VPM450: Present and operational servicing %d span\n", 1);
|
||||
|
||||
}
|
||||
#endif /* VPM_SUPPORT */
|
||||
|
||||
static int t13x_clear_maint(struct dahdi_span *span);
|
||||
|
||||
@@ -796,8 +801,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)
|
||||
{
|
||||
@@ -1134,7 +1139,7 @@ static void t13x_configure_t1(struct t13x *wc, int lineconfig, int txlevel)
|
||||
__t13x_framer_set(wc, 0x18, 0x3f); /* IMR4: Slips on transmit */
|
||||
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
dev_info(&wc->dev->dev, "Span configured for %s/%s\n", framing, line);
|
||||
dev_info(&wc->xb.pdev->dev, "Span configured for %s/%s\n", framing, line);
|
||||
}
|
||||
|
||||
static void t13x_configure_e1(struct t13x *wc, int lineconfig)
|
||||
@@ -1233,7 +1238,7 @@ static void t13x_configure_e1(struct t13x *wc, int lineconfig)
|
||||
transmit */
|
||||
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Span configured for %s/%s%s\n", framing, line, crc4);
|
||||
}
|
||||
|
||||
@@ -1251,25 +1256,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.
|
||||
@@ -1290,7 +1276,7 @@ static int te13xp_check_for_interrupts(struct t13x *wc)
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
if (time_after(jiffies, stop_time)) {
|
||||
wc->span.alarms = DAHDI_ALARM_RED;
|
||||
dev_err(&wc->dev->dev, "Interrupts not detected.\n");
|
||||
dev_err(&wc->xb.pdev->dev, "Interrupts not detected.\n");
|
||||
return -EIO;
|
||||
}
|
||||
msleep(100);
|
||||
@@ -1301,19 +1287,29 @@ static int te13xp_check_for_interrupts(struct t13x *wc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool have_open_channels(const struct t13x *wc)
|
||||
{
|
||||
int x, j;
|
||||
for (x = 0, j = 0; x < wc->span.channels; x++) {
|
||||
const struct dahdi_chan *chan = wc->span.chans[x];
|
||||
if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags) ||
|
||||
dahdi_have_netdev(chan))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int t13x_startup(struct file *file, struct dahdi_span *span)
|
||||
{
|
||||
struct t13x *wc = container_of(span, struct t13x, 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);
|
||||
if (ret) {
|
||||
dev_err(&wc->dev->dev, "Timeout waiting for DMA to stop.\n");
|
||||
dev_err(&wc->xb.pdev->dev, "Timeout waiting for DMA to stop.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1330,9 +1326,15 @@ static int t13x_startup(struct file *file, struct dahdi_span *span)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Calling startup (flags is %lu)\n", span->flags);
|
||||
|
||||
/* Check for "open channels" here in case some channels have netdev. */
|
||||
if (have_open_channels(wc))
|
||||
clear_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags);
|
||||
else
|
||||
set_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags);
|
||||
|
||||
/* Get this party started */
|
||||
local_irq_save(flags);
|
||||
t13x_check_alarms(wc);
|
||||
@@ -1491,11 +1493,11 @@ static int t13x_maint(struct dahdi_span *span, int cmd)
|
||||
|
||||
switch (cmd) {
|
||||
case DAHDI_MAINT_NONE:
|
||||
dev_info(&wc->dev->dev, "Clearing all maint modes\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Clearing all maint modes\n");
|
||||
t13x_clear_maint(span);
|
||||
break;
|
||||
case DAHDI_MAINT_LOCALLOOP:
|
||||
dev_info(&wc->dev->dev, "Turning on local loopback\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Turning on local loopback\n");
|
||||
t13x_clear_maint(span);
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
reg = __t13x_framer_get(wc, LIM0);
|
||||
@@ -1503,7 +1505,7 @@ static int t13x_maint(struct dahdi_span *span, int cmd)
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
break;
|
||||
case DAHDI_MAINT_NETWORKLINELOOP:
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Turning on network line loopback\n");
|
||||
t13x_clear_maint(span);
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
@@ -1512,7 +1514,7 @@ static int t13x_maint(struct dahdi_span *span, int cmd)
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
break;
|
||||
case DAHDI_MAINT_NETWORKPAYLOADLOOP:
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Turning on network payload loopback\n");
|
||||
t13x_clear_maint(span);
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
@@ -1521,7 +1523,7 @@ static int t13x_maint(struct dahdi_span *span, int cmd)
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
break;
|
||||
case DAHDI_MAINT_LOOPUP:
|
||||
dev_info(&wc->dev->dev, "Transmitting loopup code\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Transmitting loopup code\n");
|
||||
t13x_clear_maint(span);
|
||||
if (dahdi_is_e1_span(&wc->span)) {
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
@@ -1536,7 +1538,7 @@ static int t13x_maint(struct dahdi_span *span, int cmd)
|
||||
}
|
||||
break;
|
||||
case DAHDI_MAINT_LOOPDOWN:
|
||||
dev_info(&wc->dev->dev, "Transmitting loopdown code\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Transmitting loopdown code\n");
|
||||
t13x_clear_maint(span);
|
||||
if (dahdi_is_e1_span(&wc->span)) {
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
@@ -1572,7 +1574,7 @@ static int t13x_maint(struct dahdi_span *span, int cmd)
|
||||
t13x_reset_counters(span);
|
||||
break;
|
||||
default:
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Unknown maint command: %d\n", cmd);
|
||||
return -ENOSYS;
|
||||
}
|
||||
@@ -1674,25 +1676,56 @@ static void t13x_chan_set_sigcap(struct dahdi_span *span, int x)
|
||||
}
|
||||
}
|
||||
|
||||
static bool t13x_lineconfig_changed(struct t13x *wc,
|
||||
const struct dahdi_lineconfig *lc)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool result;
|
||||
u32 crc = crc32(~0, lc, sizeof(*lc));
|
||||
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
result = (crc != wc->lineconfig_fingerprint);
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void t13x_save_lineconfig(struct t13x *wc,
|
||||
const struct dahdi_lineconfig *lc)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 crc = crc32(~0, lc, sizeof(*lc));
|
||||
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
wc->lineconfig_fingerprint = crc;
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
t13x_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
struct dahdi_lineconfig *lc)
|
||||
{
|
||||
struct t13x *wc = container_of(span, struct t13x, span);
|
||||
int i;
|
||||
int res = 0;
|
||||
|
||||
if (file->f_flags & O_NONBLOCK)
|
||||
return -EAGAIN;
|
||||
|
||||
/* Set recover timing mode */
|
||||
span->syncsrc = lc->sync;
|
||||
|
||||
/* make sure that sigcaps gets updated if necessary */
|
||||
for (i = 0; i < wc->span.channels; i++)
|
||||
t13x_chan_set_sigcap(span, i);
|
||||
|
||||
/* If already running, apply changes immediately */
|
||||
if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags))
|
||||
return t13x_startup(file, span);
|
||||
|
||||
return 0;
|
||||
if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags) &&
|
||||
t13x_lineconfig_changed(wc, lc)) {
|
||||
res = t13x_startup(file, span);
|
||||
if (!res)
|
||||
t13x_save_lineconfig(wc, lc);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1723,8 +1756,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);
|
||||
@@ -1764,7 +1795,7 @@ static int t13x_software_init(struct t13x *wc, enum linemode type)
|
||||
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
|
||||
dev_info(&wc->dev->dev, "Setting up global serial parameters for %s\n",
|
||||
dev_info(&wc->xb.pdev->dev, "Setting up global serial parameters for %s\n",
|
||||
dahdi_spantype2str(wc->span.spantype));
|
||||
|
||||
t13x_serial_setup(wc);
|
||||
@@ -1776,8 +1807,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:
|
||||
@@ -1816,7 +1845,6 @@ static int t13x_set_linemode(struct dahdi_span *span, enum spantypes linemode)
|
||||
clear_bit(INITIALIZED, &wc->bit_flags);
|
||||
disable_irq(wc->xb.pdev->irq);
|
||||
|
||||
synchronize_irq(wc->dev->irq);
|
||||
smp_mb__after_clear_bit();
|
||||
del_timer_sync(&wc->timer);
|
||||
flush_workqueue(wc->wq);
|
||||
@@ -1826,24 +1854,24 @@ static int t13x_set_linemode(struct dahdi_span *span, enum spantypes linemode)
|
||||
|
||||
switch (linemode) {
|
||||
case SPANTYPE_DIGITAL_T1:
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Changing from %s to T1 line mode.\n",
|
||||
dahdi_spantype2str(wc->span.spantype));
|
||||
res = t13x_software_init(wc, T1);
|
||||
break;
|
||||
case SPANTYPE_DIGITAL_E1:
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Changing from %s to E1 line mode.\n",
|
||||
dahdi_spantype2str(wc->span.spantype));
|
||||
res = t13x_software_init(wc, E1);
|
||||
break;
|
||||
case SPANTYPE_DIGITAL_J1:
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Changing from %s to E1 line mode.\n",
|
||||
dahdi_spantype2str(wc->span.spantype));
|
||||
res = t13x_software_init(wc, J1);
|
||||
default:
|
||||
dev_err(&wc->dev->dev,
|
||||
dev_err(&wc->xb.pdev->dev,
|
||||
"Got invalid linemode '%s' from dahdi\n",
|
||||
dahdi_spantype2str(linemode));
|
||||
res = -EINVAL;
|
||||
@@ -1876,14 +1904,14 @@ static int t13x_hardware_post_init(struct t13x *wc, enum linemode *type)
|
||||
} else if (!strcasecmp(default_linemode, "j1")) {
|
||||
*type = J1;
|
||||
} else {
|
||||
dev_warn(&wc->dev->dev,
|
||||
dev_warn(&wc->xb.pdev->dev,
|
||||
"'%s' is an unknown linemode. Defaulting to 't1'\n",
|
||||
default_linemode);
|
||||
*type = T1;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
dev_info(&wc->dev->dev, "linemode: %s\n",
|
||||
dev_info(&wc->xb.pdev->dev, "linemode: %s\n",
|
||||
(*type == T1) ? "T1" : ((J1 == *type) ? "J1" : "E1"));
|
||||
}
|
||||
|
||||
@@ -1891,23 +1919,23 @@ static int t13x_hardware_post_init(struct t13x *wc, enum linemode *type)
|
||||
wcxb_gpio_set(&wc->xb, FALC_CPU_RESET);
|
||||
reg = t13x_framer_get(wc, 0x4a);
|
||||
if (reg < 0) {
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Failed to read FALC version (%x)\n", reg);
|
||||
return -EIO;
|
||||
}
|
||||
dev_info(&wc->dev->dev, "FALC version: %1x\n", reg);
|
||||
dev_info(&wc->xb.pdev->dev, "FALC version: %1x\n", reg);
|
||||
|
||||
/* make sure reads and writes work */
|
||||
for (x = 0; x < 256; x++) {
|
||||
t13x_framer_set(wc, 0x14, x);
|
||||
reg = t13x_framer_get(wc, 0x14);
|
||||
if (reg < 0) {
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Failed register read (%d)\n", reg);
|
||||
return -EIO;
|
||||
}
|
||||
if (reg != x) {
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"Register test failed. Wrote '%x' but read '%x'\n",
|
||||
x, reg);
|
||||
return -EIO;
|
||||
@@ -1924,7 +1952,6 @@ static void t13x_check_alarms(struct t13x *wc)
|
||||
{
|
||||
unsigned char c, d;
|
||||
int alarms;
|
||||
int x, j;
|
||||
|
||||
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
|
||||
return;
|
||||
@@ -1946,7 +1973,7 @@ static void t13x_check_alarms(struct t13x *wc)
|
||||
/* LIM0: Force RAI High */
|
||||
__t13x_framer_set(wc, 0x20, 0x9f | 0x20);
|
||||
wc->flags.nmf = 1;
|
||||
dev_info(&wc->dev->dev, "NMF workaround on!\n");
|
||||
dev_info(&wc->xb.pdev->dev, "NMF workaround on!\n");
|
||||
}
|
||||
__t13x_framer_set(wc, 0x1e, 0xc3); /* Reset to CRC4 mode */
|
||||
__t13x_framer_set(wc, 0x1c, 0xf2); /* Force Resync */
|
||||
@@ -1956,18 +1983,14 @@ static void t13x_check_alarms(struct t13x *wc)
|
||||
/* LIM0: Clear forced RAI */
|
||||
__t13x_framer_set(wc, 0x20, 0x9f);
|
||||
wc->flags.nmf = 0;
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"NMF workaround off!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN) {
|
||||
for (x = 0, j = 0; x < wc->span.channels; x++)
|
||||
if ((wc->span.chans[x]->flags & DAHDI_FLAG_OPEN) ||
|
||||
dahdi_have_netdev(wc->span.chans[x]))
|
||||
j++;
|
||||
if (!j)
|
||||
if (!test_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags))
|
||||
alarms |= DAHDI_ALARM_NOTOPEN;
|
||||
else
|
||||
alarms &= ~DAHDI_ALARM_NOTOPEN;
|
||||
@@ -2065,31 +2088,31 @@ static void t13x_debounce_alarms(struct t13x *wc)
|
||||
if (wc->lofalarmtimer && time_after(jiffies, wc->lofalarmtimer)) {
|
||||
alarms |= DAHDI_ALARM_RED;
|
||||
wc->lofalarmtimer = 0;
|
||||
dev_info(&wc->dev->dev, "LOF alarm detected\n");
|
||||
dev_info(&wc->xb.pdev->dev, "LOF alarm detected\n");
|
||||
}
|
||||
|
||||
if (wc->losalarmtimer && time_after(jiffies, wc->losalarmtimer)) {
|
||||
alarms |= DAHDI_ALARM_RED;
|
||||
wc->losalarmtimer = 0;
|
||||
dev_info(&wc->dev->dev, "LOS alarm detected\n");
|
||||
dev_info(&wc->xb.pdev->dev, "LOS alarm detected\n");
|
||||
}
|
||||
|
||||
if (wc->aisalarmtimer && time_after(jiffies, wc->aisalarmtimer)) {
|
||||
alarms |= DAHDI_ALARM_BLUE;
|
||||
wc->aisalarmtimer = 0;
|
||||
dev_info(&wc->dev->dev, "AIS alarm detected\n");
|
||||
dev_info(&wc->xb.pdev->dev, "AIS alarm detected\n");
|
||||
}
|
||||
|
||||
if (wc->yelalarmtimer && time_after(jiffies, wc->yelalarmtimer)) {
|
||||
alarms |= DAHDI_ALARM_YELLOW;
|
||||
wc->yelalarmtimer = 0;
|
||||
dev_info(&wc->dev->dev, "YEL alarm detected\n");
|
||||
dev_info(&wc->xb.pdev->dev, "YEL alarm detected\n");
|
||||
}
|
||||
|
||||
if (wc->recoverytimer && time_after(jiffies, wc->recoverytimer)) {
|
||||
alarms &= ~(DAHDI_ALARM_RECOVER);
|
||||
wc->recoverytimer = 0;
|
||||
dev_info(&wc->dev->dev, "Alarms cleared\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Alarms cleared\n");
|
||||
}
|
||||
|
||||
if (alarms != wc->span.alarms) {
|
||||
@@ -2103,7 +2126,7 @@ static void t13x_debounce_alarms(struct t13x *wc)
|
||||
if (alarms & (DAHDI_ALARM_RED|DAHDI_ALARM_BLUE|
|
||||
DAHDI_ALARM_NOTOPEN|DAHDI_ALARM_RECOVER)) {
|
||||
if (!wc->flags.sendingyellow) {
|
||||
dev_info(&wc->dev->dev, "Setting yellow alarm\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Setting yellow alarm\n");
|
||||
/* We manually do yellow alarm to handle RECOVER
|
||||
* and NOTOPEN, otherwise it's auto anyway */
|
||||
fmr4 = __t13x_framer_get(wc, 0x20);
|
||||
@@ -2112,7 +2135,7 @@ static void t13x_debounce_alarms(struct t13x *wc)
|
||||
}
|
||||
} else {
|
||||
if (wc->flags.sendingyellow) {
|
||||
dev_info(&wc->dev->dev, "Clearing yellow alarm\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Clearing yellow alarm\n");
|
||||
/* We manually do yellow alarm to handle RECOVER */
|
||||
fmr4 = __t13x_framer_get(wc, 0x20);
|
||||
__t13x_framer_set(wc, 0x20, fmr4 & ~0x20);
|
||||
@@ -2130,7 +2153,7 @@ static void t13x_debounce_loopcodes(struct t13x *wc)
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
if (wc->loopuptimer && time_after(jiffies, wc->loopuptimer)) {
|
||||
/* Loop-up code debounced */
|
||||
dev_info(&wc->dev->dev, "Loopup detected, enabling remote loop\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Loopup detected, enabling remote loop\n");
|
||||
__t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Disable
|
||||
any local loop */
|
||||
__t13x_framer_set(wc, 0x37, 0xf6); /* LIM1: Enable
|
||||
@@ -2144,7 +2167,7 @@ static void t13x_debounce_loopcodes(struct t13x *wc)
|
||||
|
||||
if (wc->loopdntimer && time_after(jiffies, wc->loopdntimer)) {
|
||||
/* Loop-down code debounced */
|
||||
dev_info(&wc->dev->dev, "Loopdown detected, disabling remote loop\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Loopdown detected, disabling remote loop\n");
|
||||
__t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Disable
|
||||
any local loop */
|
||||
__t13x_framer_set(wc, 0x37, 0xf0); /* LIM1: Disable
|
||||
@@ -2208,7 +2231,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,
|
||||
@@ -2256,7 +2279,8 @@ static void timer_work_func(struct work_struct *work)
|
||||
static int work_count;
|
||||
|
||||
if (debug)
|
||||
dev_notice(&wc->dev->dev, "Timer work: %d!\n", ++work_count);
|
||||
dev_notice(&wc->xb.pdev->dev, "Timer work: %d!\n",
|
||||
++work_count);
|
||||
|
||||
t13x_debounce_alarms(wc);
|
||||
if (!dahdi_is_e1_span(&wc->span))
|
||||
@@ -2288,7 +2312,7 @@ static void handle_falc_int(struct t13x *wc)
|
||||
isr4 = (gis & FRMR_GIS_ISR4) ? __t13x_framer_get(wc, FRMR_ISR4) : 0;
|
||||
|
||||
if ((debug) && !(isr3 & ISR3_SEC)) {
|
||||
dev_info(&wc->dev->dev, "gis: %02x, isr0: %02x, isr1: %02x, "\
|
||||
dev_info(&wc->xb.pdev->dev, "gis: %02x, isr0: %02x, isr1: %02x, "\
|
||||
"isr2: %02x, isr3: %02x, isr4: %02x, intcount=%u\n",
|
||||
gis, isr0, isr1, isr2, isr3, isr4, intcount);
|
||||
}
|
||||
@@ -2367,6 +2391,41 @@ static void te13xp_timer(unsigned long data)
|
||||
static inline void create_sysfs_files(struct t13x *wc) { return; }
|
||||
static inline void remove_sysfs_files(struct t13x *wc) { return; }
|
||||
|
||||
static int t13x_open(struct dahdi_chan *chan)
|
||||
{
|
||||
struct t13x *wc = chan->pvt;
|
||||
unsigned long flags;
|
||||
|
||||
if (!(wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN))
|
||||
return 0;
|
||||
|
||||
if (!test_and_set_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags)) {
|
||||
local_irq_save(flags);
|
||||
t13x_check_alarms(wc);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t13x_close(struct dahdi_chan *chan)
|
||||
{
|
||||
struct t13x *wc = chan->pvt;
|
||||
unsigned long flags;
|
||||
|
||||
if (!(wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN))
|
||||
return 0;
|
||||
|
||||
if (!have_open_channels(wc)) {
|
||||
if (test_and_clear_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags)) {
|
||||
local_irq_save(flags);
|
||||
t13x_check_alarms(wc);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dahdi_span_ops t13x_span_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.spanconfig = t13x_spanconfig,
|
||||
@@ -2376,10 +2435,10 @@ 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 */
|
||||
.open = t13x_open,
|
||||
.close = t13x_close,
|
||||
};
|
||||
|
||||
#define SPI_BASE 0x200
|
||||
@@ -2452,6 +2511,30 @@ error_exit:
|
||||
return serial;
|
||||
}
|
||||
|
||||
static int te13xp_check_firmware(struct t13x *wc)
|
||||
{
|
||||
const char *filename;
|
||||
u32 expected_version;
|
||||
enum wcxb_reset_option reset;
|
||||
|
||||
if (is_pcie(wc)) {
|
||||
filename = TE133_FW_FILENAME;
|
||||
expected_version = TE133_FW_VERSION;
|
||||
} else {
|
||||
filename = TE134_FW_FILENAME;
|
||||
expected_version = TE134_FW_VERSION;
|
||||
}
|
||||
|
||||
/* 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, expected_version, filename,
|
||||
force_firmware, reset);
|
||||
}
|
||||
|
||||
static int __devinit te13xp_init_one(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
@@ -2461,6 +2544,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]) {
|
||||
@@ -2480,7 +2564,6 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
wc->dev = pdev;
|
||||
wc->devtype = d;
|
||||
dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
|
||||
|
||||
@@ -2529,24 +2612,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->xb.pdev->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) {
|
||||
@@ -2559,17 +2644,20 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
|
||||
if (latency > 0 && latency < DRING_SIZE) {
|
||||
wcxb_set_minlatency(&wc->xb, latency);
|
||||
if (WCXB_DEFAULT_LATENCY != latency)
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"latency manually overridden to %d\n",
|
||||
latency);
|
||||
} else {
|
||||
dev_info(&wc->dev->dev,
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"latency module parameter must be between 1 and %d\n",
|
||||
DRING_SIZE);
|
||||
res = -EPERM;
|
||||
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);
|
||||
@@ -2582,10 +2670,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);
|
||||
@@ -2593,9 +2686,9 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
|
||||
/* Span is in red alarm by default */
|
||||
wc->span.alarms = DAHDI_ALARM_NONE;
|
||||
|
||||
res = dahdi_register_device(wc->ddev, &wc->dev->dev);
|
||||
res = dahdi_register_device(wc->ddev, &wc->xb.pdev->dev);
|
||||
if (res) {
|
||||
dev_info(&wc->dev->dev, "Unable to register with DAHDI\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Unable to register with DAHDI\n");
|
||||
goto fail_exit;
|
||||
}
|
||||
|
||||
@@ -2603,10 +2696,10 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
|
||||
mod_timer(&wc->timer, jiffies + HZ/5);
|
||||
|
||||
if (wc->ddev->hardware_id) {
|
||||
dev_info(&wc->dev->dev, "Found a %s (SN: %s)\n",
|
||||
dev_info(&wc->xb.pdev->dev, "Found a %s (SN: %s)\n",
|
||||
wc->devtype->name, wc->ddev->hardware_id);
|
||||
} else {
|
||||
dev_info(&wc->dev->dev, "Found a %s\n",
|
||||
dev_info(&wc->xb.pdev->dev, "Found a %s\n",
|
||||
wc->devtype->name);
|
||||
}
|
||||
|
||||
@@ -2623,7 +2716,7 @@ fail_exit:
|
||||
static void __devexit te13xp_remove_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct t13x *wc = pci_get_drvdata(pdev);
|
||||
dev_info(&wc->dev->dev, "Removing a Wildcard TE13xP.\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Removing a Wildcard TE13xP.\n");
|
||||
if (!wc)
|
||||
return;
|
||||
|
||||
@@ -2643,11 +2736,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);
|
||||
|
||||
@@ -2666,7 +2757,7 @@ static DEFINE_PCI_DEVICE_TABLE(te13xp_pci_tbl) = {
|
||||
static void te13xp_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct t13x *wc = pci_get_drvdata(pdev);
|
||||
dev_info(&wc->dev->dev, "Quiescing a Wildcard TE13xP.\n");
|
||||
dev_info(&wc->xb.pdev->dev, "Quiescing a Wildcard TE13xP.\n");
|
||||
if (!wc)
|
||||
return;
|
||||
|
||||
@@ -2722,12 +2813,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>");
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/crc32.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/time.h>
|
||||
@@ -51,11 +51,23 @@
|
||||
#include "wcxb_spi.h"
|
||||
#include "wcxb_flash.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
# ifdef RHEL_RELEASE_VERSION
|
||||
# if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5, 6)
|
||||
# define T43X_HAVE_CANCEL_WORK_SYNC
|
||||
# endif
|
||||
# else
|
||||
static inline int delayed_work_pending(struct work_struct *work)
|
||||
{
|
||||
return test_bit(0, &work->pending);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static const char *TE435_FW_FILENAME = "dahdi-fw-te435.bin";
|
||||
static const u32 TE435_VERSION = 0xe0017;
|
||||
static const u32 TE435_VERSION = 0xe0019;
|
||||
|
||||
/* #define RPC_RCLK */
|
||||
#define VPM_SUPPORT
|
||||
|
||||
enum linemode {
|
||||
T1 = 1,
|
||||
@@ -79,10 +91,10 @@ struct t43x;
|
||||
struct t43x_span {
|
||||
struct t43x *owner;
|
||||
struct dahdi_span span;
|
||||
struct {
|
||||
unsigned int nmf:1;
|
||||
unsigned int sendingyellow:1;
|
||||
} flags;
|
||||
#define NMF_FLAGBIT 1
|
||||
#define SENDINGYELLOW_FLAGBIT 2
|
||||
#define HAVE_OPEN_CHANNELS_FLAGBIT 3
|
||||
unsigned long bit_flags;
|
||||
unsigned char txsigs[16]; /* Copy of tx sig registers */
|
||||
unsigned long lofalarmtimer;
|
||||
unsigned long losalarmtimer;
|
||||
@@ -98,6 +110,7 @@ struct t43x_span {
|
||||
bool debounce;
|
||||
int syncpos;
|
||||
int sync;
|
||||
u32 lineconfig_fingerprint;
|
||||
};
|
||||
|
||||
struct t43x_clksrc_work {
|
||||
@@ -129,10 +142,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 +158,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 +238,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 +669,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 +682,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 +782,6 @@ static void t43x_vpm_init(struct t43x *wc)
|
||||
wc->numspans);
|
||||
|
||||
}
|
||||
#endif /* VPM_SUPPORT */
|
||||
|
||||
static int t43x_clear_maint(struct dahdi_span *span);
|
||||
|
||||
@@ -1215,7 +1224,7 @@ static void t43x_clksrc_work_fn(struct work_struct *data)
|
||||
* @mode: The clock mode that we would like to move to.
|
||||
* @master: If true, drive the clock on the timing header.
|
||||
*
|
||||
* The clock srouce cannot be changed while DMA is active, so this function
|
||||
* The clock source cannot be changed while DMA is active, so this function
|
||||
* will stop the DMA, then queue a delayed work item in order to come back and
|
||||
* check that DMA was actually stopped before changing the source of the clock.
|
||||
*
|
||||
@@ -1712,10 +1721,21 @@ static void t43x_configure_e1(struct t43x *wc, int span_idx, int lineconfig)
|
||||
framing, line, crc4);
|
||||
}
|
||||
|
||||
static bool have_open_channels(const struct t43x_span *ts)
|
||||
{
|
||||
int x, j;
|
||||
for (x = 0, j = 0; x < ts->span.channels; x++) {
|
||||
const struct dahdi_chan *chan = ts->span.chans[x];
|
||||
if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags) ||
|
||||
dahdi_have_netdev(chan))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void t43x_framer_start(struct t43x *wc)
|
||||
{
|
||||
int unit;
|
||||
struct t43x_span *ts;
|
||||
unsigned long flags;
|
||||
int res;
|
||||
|
||||
@@ -1732,7 +1752,7 @@ static void t43x_framer_start(struct t43x *wc)
|
||||
dev_warn(&wc->xb.pdev->dev, "DMA engine did not stop.\n");
|
||||
|
||||
for (unit = 0; unit < wc->numspans; unit++) {
|
||||
ts = wc->tspans[unit];
|
||||
struct t43x_span *ts = wc->tspans[unit];
|
||||
if (dahdi_is_e1_span(&ts->span)) {
|
||||
t43x_configure_e1(wc, unit, ts->span.lineconfig);
|
||||
} else { /* is a T1 card */
|
||||
@@ -1746,6 +1766,15 @@ static void t43x_framer_start(struct t43x *wc)
|
||||
|
||||
for (unit = 0; unit < wc->numspans; unit++) {
|
||||
/* Get this party started */
|
||||
struct t43x_span *ts = wc->tspans[unit];
|
||||
|
||||
/* Check for "open channels" here in case some channels have
|
||||
* netdev. */
|
||||
if (have_open_channels(ts))
|
||||
clear_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags);
|
||||
else
|
||||
set_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags);
|
||||
|
||||
local_irq_save(flags);
|
||||
t43x_check_alarms(wc, unit);
|
||||
t43x_check_sigbits(wc, unit);
|
||||
@@ -1767,7 +1796,7 @@ static void t43x_framer_start(struct t43x *wc)
|
||||
|
||||
/* Clear all counters */
|
||||
for (unit = 0; unit < wc->numspans; unit++) {
|
||||
ts = wc->tspans[unit];
|
||||
struct t43x_span *ts = wc->tspans[unit];
|
||||
memset(&ts->span.count, 0, sizeof(ts->span.count));
|
||||
}
|
||||
|
||||
@@ -2349,6 +2378,30 @@ static void t43x_chan_set_sigcap(struct dahdi_span *span, int x)
|
||||
}
|
||||
}
|
||||
|
||||
static bool t43x_lineconfig_changed(struct t43x_span *ts,
|
||||
const struct dahdi_lineconfig *lc)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool result;
|
||||
u32 crc = crc32(~0, lc, sizeof(*lc));
|
||||
|
||||
spin_lock_irqsave(&ts->owner->reglock, flags);
|
||||
result = (crc != ts->lineconfig_fingerprint);
|
||||
spin_unlock_irqrestore(&ts->owner->reglock, flags);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void t43x_save_lineconfig(struct t43x_span *ts,
|
||||
const struct dahdi_lineconfig *lc)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 crc = crc32(~0, lc, sizeof(*lc));
|
||||
|
||||
spin_lock_irqsave(&ts->owner->reglock, flags);
|
||||
ts->lineconfig_fingerprint = crc;
|
||||
spin_unlock_irqrestore(&ts->owner->reglock, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
t43x_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
struct dahdi_lineconfig *lc)
|
||||
@@ -2356,6 +2409,7 @@ t43x_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
struct t43x_span *ts = container_of(span, struct t43x_span, span);
|
||||
struct t43x *wc = ts->owner;
|
||||
int i;
|
||||
int res = 0;
|
||||
|
||||
if (debug)
|
||||
dev_info(&wc->xb.pdev->dev, "%s\n", __func__);
|
||||
@@ -2392,10 +2446,13 @@ t43x_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
t43x_chan_set_sigcap(span, i);
|
||||
|
||||
/* If already running, apply changes immediately */
|
||||
if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags))
|
||||
return t43x_startup(file, span);
|
||||
|
||||
return 0;
|
||||
if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags) &&
|
||||
t43x_lineconfig_changed(ts, lc)) {
|
||||
res = t43x_startup(file, span);
|
||||
if (!res)
|
||||
t43x_save_lineconfig(ts, lc);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2459,6 +2516,7 @@ t43x_init_one_span(struct t43x *wc, struct t43x_span *ts, enum linemode type)
|
||||
default:
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
res = -EINVAL;
|
||||
enable_irq(wc->xb.pdev->irq);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
@@ -2481,7 +2539,6 @@ t43x_init_one_span(struct t43x *wc, struct t43x_span *ts, enum linemode type)
|
||||
return 0;
|
||||
|
||||
error_exit:
|
||||
enable_irq(wc->xb.pdev->irq);
|
||||
|
||||
for (x = 0; x < ARRAY_SIZE(chans); ++x) {
|
||||
kfree(chans[x]);
|
||||
@@ -2650,7 +2707,6 @@ static void t43x_check_alarms(struct t43x *wc, int span_idx)
|
||||
struct t43x_span *ts = wc->tspans[span_idx];
|
||||
unsigned char c, d;
|
||||
int alarms;
|
||||
int x, j;
|
||||
int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx;
|
||||
|
||||
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &ts->span.flags)))
|
||||
@@ -2669,10 +2725,9 @@ static void t43x_check_alarms(struct t43x *wc, int span_idx)
|
||||
/* No multiframe found, force RAI high after 400ms only
|
||||
* if we haven't found a multiframe since last loss of
|
||||
* frame */
|
||||
if (!ts->flags.nmf) {
|
||||
if (!test_and_set_bit(NMF_FLAGBIT, &ts->bit_flags)) {
|
||||
/* LIM0: Force RAI High */
|
||||
__t43x_framer_set(wc, fidx, 0x20, 0x9f | 0x20);
|
||||
ts->flags.nmf = 1;
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"NMF workaround on!\n");
|
||||
}
|
||||
@@ -2683,10 +2738,9 @@ static void t43x_check_alarms(struct t43x *wc, int span_idx)
|
||||
/* Force Resync */
|
||||
__t43x_framer_set(wc, fidx, 0x1c, 0xf0);
|
||||
} else if (!(c & 0x02)) {
|
||||
if (ts->flags.nmf) {
|
||||
if (test_and_clear_bit(NMF_FLAGBIT, &ts->bit_flags)) {
|
||||
/* LIM0: Clear forced RAI */
|
||||
__t43x_framer_set(wc, fidx, 0x20, 0x9f);
|
||||
ts->flags.nmf = 0;
|
||||
dev_info(&wc->xb.pdev->dev,
|
||||
"NMF workaround off!\n");
|
||||
}
|
||||
@@ -2694,11 +2748,7 @@ static void t43x_check_alarms(struct t43x *wc, int span_idx)
|
||||
}
|
||||
|
||||
if (ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN) {
|
||||
for (x = 0, j = 0; x < ts->span.channels; x++)
|
||||
if ((ts->chans[x]->flags & DAHDI_FLAG_OPEN) ||
|
||||
dahdi_have_netdev(ts->chans[x]))
|
||||
j++;
|
||||
if (!j)
|
||||
if (!test_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags))
|
||||
alarms |= DAHDI_ALARM_NOTOPEN;
|
||||
else
|
||||
alarms &= ~DAHDI_ALARM_NOTOPEN;
|
||||
@@ -2860,21 +2910,19 @@ static void t43x_debounce_alarms(struct t43x *wc, int span_idx)
|
||||
/* If receiving alarms (except Yellow), go into Yellow alarm state */
|
||||
if (alarms & (DAHDI_ALARM_RED|DAHDI_ALARM_BLUE|
|
||||
DAHDI_ALARM_NOTOPEN|DAHDI_ALARM_RECOVER)) {
|
||||
if (!ts->flags.sendingyellow) {
|
||||
if (!test_and_set_bit(SENDINGYELLOW_FLAGBIT, &ts->bit_flags)) {
|
||||
dev_info(&wc->xb.pdev->dev, "Setting yellow alarm\n");
|
||||
/* We manually do yellow alarm to handle RECOVER
|
||||
* and NOTOPEN, otherwise it's auto anyway */
|
||||
fmr4 = __t43x_framer_get(wc, fidx, 0x20);
|
||||
__t43x_framer_set(wc, fidx, 0x20, fmr4 | 0x20);
|
||||
ts->flags.sendingyellow = 1;
|
||||
}
|
||||
} else {
|
||||
if (ts->flags.sendingyellow) {
|
||||
if (test_and_clear_bit(SENDINGYELLOW_FLAGBIT, &ts->bit_flags)) {
|
||||
dev_info(&wc->xb.pdev->dev, "Clearing yellow alarm\n");
|
||||
/* We manually do yellow alarm to handle RECOVER */
|
||||
fmr4 = __t43x_framer_get(wc, fidx, 0x20);
|
||||
__t43x_framer_set(wc, fidx, 0x20, fmr4 & ~0x20);
|
||||
ts->flags.sendingyellow = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3154,6 +3202,45 @@ static void t43x_timer(unsigned long data)
|
||||
return;
|
||||
}
|
||||
|
||||
static int t43x_open(struct dahdi_chan *chan)
|
||||
{
|
||||
struct t43x *wc = chan->pvt;
|
||||
struct t43x_span *ts = container_of(chan->span, struct t43x_span, span);
|
||||
unsigned long flags;
|
||||
|
||||
if (!(ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN))
|
||||
return 0;
|
||||
|
||||
if (!test_and_set_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags)) {
|
||||
local_irq_save(flags);
|
||||
t43x_check_alarms(wc, ts->span.offset);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t43x_close(struct dahdi_chan *chan)
|
||||
{
|
||||
struct t43x *wc = chan->pvt;
|
||||
struct t43x_span *ts = container_of(chan->span, struct t43x_span, span);
|
||||
unsigned long flags;
|
||||
|
||||
if (!(ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN))
|
||||
return 0;
|
||||
|
||||
if (have_open_channels(ts))
|
||||
return 0;
|
||||
|
||||
if (!test_and_set_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags)) {
|
||||
local_irq_save(flags);
|
||||
t43x_check_alarms(wc, ts->span.offset);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dahdi_span_ops t43x_span_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.spanconfig = t43x_spanconfig,
|
||||
@@ -3164,10 +3251,10 @@ 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 */
|
||||
.open = t43x_open,
|
||||
.close = t43x_close,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3327,7 +3414,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 +3451,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 +3503,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 +3514,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,14 +3566,17 @@ 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)
|
||||
# ifdef T43X_HAVE_CANCEL_WORK_SYNC
|
||||
cancel_work_sync(&wc->clksrc_work.work);
|
||||
# else
|
||||
cancel_delayed_work(&wc->clksrc_work.work);
|
||||
flush_workqueue(wc->wq);
|
||||
# endif
|
||||
#else
|
||||
cancel_delayed_work_sync(&wc->clksrc_work.work);
|
||||
#endif
|
||||
@@ -3574,9 +3659,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\"");
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
|
||||
#define HAVE_RATELIMIT
|
||||
@@ -45,10 +46,13 @@
|
||||
|
||||
/* The definition for Surprise Down was added in Linux 3.6 in (a0dee2e PCI: misc
|
||||
* pci_reg additions). It may be backported though so we won't check for the
|
||||
* version. */
|
||||
* version. Same with PCI_EXP_SLTCTL_PDCE. */
|
||||
#ifndef PCI_ERR_UNC_SURPDN
|
||||
#define PCI_ERR_UNC_SURPDN 0x20
|
||||
#endif
|
||||
#ifndef PCI_EXP_SLTCTL_PDCE
|
||||
#define PCI_EXP_SLTCTL_PDCE 0x8
|
||||
#endif
|
||||
|
||||
/* FPGA Status definitions */
|
||||
#define OCT_CPU_RESET (1 << 0)
|
||||
@@ -62,8 +66,9 @@
|
||||
#define DRING_SIZE_MASK (DRING_SIZE-1)
|
||||
#define DESC_EOR (1 << 0)
|
||||
#define DESC_INT (1 << 1)
|
||||
#define DESC_IO_ERROR (1 << 30)
|
||||
#define DESC_OWN (1 << 31)
|
||||
#define DESC_DEFAULT_STATUS 0xdeadbeef
|
||||
#define DESC_DEFAULT_STATUS 0xdeadbe00
|
||||
#define DMA_CHAN_SIZE 128
|
||||
|
||||
/* Echocan definitions */
|
||||
@@ -351,16 +356,49 @@ static void _wcxb_reset_dring(struct wcxb *xb)
|
||||
BUG_ON(!hdesc);
|
||||
/* Set end of ring bit in last descriptor to force hw to loop around */
|
||||
hdesc->control |= cpu_to_be32(DESC_EOR);
|
||||
#ifdef DEBUG
|
||||
xb->last_retry_count = 0;
|
||||
#endif
|
||||
iowrite32be(xb->hw_dring_phys, xb->membase + TDM_DRING_ADDR);
|
||||
}
|
||||
|
||||
static void wcxb_handle_dma(struct wcxb *xb)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
bool did_retry_dma = false;
|
||||
u8 retry;
|
||||
#endif
|
||||
struct wcxb_meta_desc *mdesc;
|
||||
struct wcxb_hw_desc *tail = &(xb->hw_dring[xb->dma_tail]);
|
||||
|
||||
while (!(xb->hw_dring[xb->dma_tail].control & cpu_to_be32(DESC_OWN))) {
|
||||
while (!(tail->control & cpu_to_be32(DESC_OWN))) {
|
||||
u_char *frame;
|
||||
|
||||
if (tail->control & cpu_to_be32(DESC_IO_ERROR)) {
|
||||
u32 ier;
|
||||
unsigned long flags;
|
||||
|
||||
/* The firmware detected an error condition on the bus.
|
||||
* Force an underrun by disabling the descriptor
|
||||
* complete interrupt. When the driver processes the
|
||||
* underrun it will reset the TDM engine. */
|
||||
xb->flags.io_error = 1;
|
||||
|
||||
spin_lock_irqsave(&xb->lock, flags);
|
||||
ier = ioread32be(xb->membase + IER);
|
||||
iowrite32be(ier & ~DESC_COMPLETE, xb->membase + IER);
|
||||
spin_unlock_irqrestore(&xb->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
retry = be32_to_cpu(tail->status) & 0xff;
|
||||
if (xb->last_retry_count != retry) {
|
||||
xb->last_retry_count = retry;
|
||||
did_retry_dma = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
mdesc = &xb->meta_dring[xb->dma_tail];
|
||||
frame = mdesc->rx_buf_virt;
|
||||
|
||||
@@ -368,6 +406,7 @@ static void wcxb_handle_dma(struct wcxb *xb)
|
||||
|
||||
xb->dma_tail =
|
||||
(xb->dma_tail == xb->latency-1) ? 0 : xb->dma_tail + 1;
|
||||
tail = &(xb->hw_dring[xb->dma_tail]);
|
||||
|
||||
mdesc = &xb->meta_dring[xb->dma_head];
|
||||
frame = mdesc->tx_buf_virt;
|
||||
@@ -379,6 +418,13 @@ static void wcxb_handle_dma(struct wcxb *xb)
|
||||
xb->dma_head =
|
||||
(xb->dma_head == xb->latency-1) ? 0 : xb->dma_head + 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (did_retry_dma) {
|
||||
dev_info(&xb->pdev->dev,
|
||||
"DMA retries detected: %d\n", xb->last_retry_count);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static irqreturn_t _wcxb_isr(int irq, void *dev_id)
|
||||
@@ -397,20 +443,40 @@ static irqreturn_t _wcxb_isr(int irq, void *dev_id)
|
||||
if (pending & DESC_UNDERRUN) {
|
||||
u32 reg;
|
||||
|
||||
/* bump latency */
|
||||
/* 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);
|
||||
|
||||
spin_lock(&xb->lock);
|
||||
|
||||
if (!xb->flags.latency_locked) {
|
||||
xb->latency++;
|
||||
if (xb->flags.io_error) {
|
||||
/* Since an IO error is not necessarily because
|
||||
* the host could not keep up, we do not want to
|
||||
* bump the latency. */
|
||||
xb->flags.io_error = 0;
|
||||
dev_warn(&xb->pdev->dev,
|
||||
"IO error reported by firmware.\n");
|
||||
} else if (!xb->flags.latency_locked) {
|
||||
/* bump 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,27 +606,41 @@ static void _wcxb_pcie_hard_reset(struct wcxb *xb)
|
||||
{
|
||||
struct pci_dev *const parent = xb->pdev->bus->self;
|
||||
u32 aer_mask;
|
||||
int pos;
|
||||
u16 sltctl;
|
||||
int pos_err;
|
||||
int pos_exp;
|
||||
|
||||
if (!wcxb_is_pcie(xb))
|
||||
return;
|
||||
|
||||
pos = pci_find_ext_capability(parent, PCI_EXT_CAP_ID_ERR);
|
||||
if (pos) {
|
||||
pci_read_config_dword(parent, pos + PCI_ERR_UNCOR_MASK,
|
||||
pos_err = pci_find_ext_capability(parent, PCI_EXT_CAP_ID_ERR);
|
||||
if (pos_err) {
|
||||
pci_read_config_dword(parent, pos_err + PCI_ERR_UNCOR_MASK,
|
||||
&aer_mask);
|
||||
pci_write_config_dword(parent, pos + PCI_ERR_UNCOR_MASK,
|
||||
pci_write_config_dword(parent, pos_err + PCI_ERR_UNCOR_MASK,
|
||||
aer_mask | PCI_ERR_UNC_SURPDN);
|
||||
}
|
||||
|
||||
/* Also disable any presence change reporting. */
|
||||
pos_exp = pci_find_capability(parent, PCI_CAP_ID_EXP);
|
||||
if (pos_exp) {
|
||||
pci_read_config_word(parent, pos_exp + PCI_EXP_SLTCTL,
|
||||
&sltctl);
|
||||
pci_write_config_word(parent, pos_exp + PCI_EXP_SLTCTL,
|
||||
sltctl & ~PCI_EXP_SLTCTL_PDCE);
|
||||
}
|
||||
|
||||
_wcxb_hard_reset(xb);
|
||||
|
||||
if (pos) {
|
||||
pci_write_config_dword(parent, pos + PCI_ERR_UNCOR_MASK,
|
||||
if (pos_exp)
|
||||
pci_write_config_word(parent, pos_exp + PCI_EXP_SLTCTL, sltctl);
|
||||
|
||||
if (pos_err) {
|
||||
pci_write_config_dword(parent, pos_err + PCI_ERR_UNCOR_MASK,
|
||||
aer_mask);
|
||||
|
||||
/* Clear the error as well from the status register. */
|
||||
pci_write_config_dword(parent, pos + PCI_ERR_UNCOR_STATUS,
|
||||
pci_write_config_dword(parent, pos_err + PCI_ERR_UNCOR_STATUS,
|
||||
PCI_ERR_UNC_SURPDN);
|
||||
}
|
||||
|
||||
@@ -602,6 +682,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 +860,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 +875,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 +928,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 +949,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 +977,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 %x is currently running on card. You likely need to power cycle your system.\n",
|
||||
expected_version, 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 +1040,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
|
||||
|
||||
@@ -47,6 +47,11 @@ struct wcxb_operations {
|
||||
struct wcxb_meta_desc;
|
||||
struct wcxb_hw_desc;
|
||||
|
||||
/**
|
||||
* struct wcxb - Interface to wcxb firmware.
|
||||
* @last_retry_count: Running count of times firmware had to retry host DMA
|
||||
* transaction. Debugging aide.
|
||||
*/
|
||||
struct wcxb {
|
||||
struct pci_dev *pdev;
|
||||
spinlock_t lock;
|
||||
@@ -61,6 +66,7 @@ struct wcxb {
|
||||
#ifdef WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE
|
||||
u32 is_pcie:1;
|
||||
#endif
|
||||
u32 io_error:1;
|
||||
} flags;
|
||||
void __iomem *membase;
|
||||
struct wcxb_meta_desc *meta_dring;
|
||||
@@ -70,6 +76,9 @@ struct wcxb {
|
||||
dma_addr_t hw_dring_phys;
|
||||
struct dma_pool *pool;
|
||||
unsigned long framecount;
|
||||
#ifdef DEBUG
|
||||
u8 last_retry_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode);
|
||||
@@ -105,9 +114,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);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <linux/completion.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
|
||||
|
||||
@@ -1957,7 +1957,7 @@ static DEVICE_ATTR_WRITER(fxs_ring_registers_store, dev, buf, count)
|
||||
regno);
|
||||
goto invalid_input;
|
||||
}
|
||||
XPD_INFO(xpd, "%s Indirect 0x%X <=== 0x%X 0x%X\n",
|
||||
XPD_DBG(SIGNAL, xpd, "%s Indirect 0x%X <=== 0x%X 0x%X\n",
|
||||
rtype_name, regno, h_val, l_val);
|
||||
} else {
|
||||
if (ret != 3) {
|
||||
@@ -1968,7 +1968,7 @@ static DEVICE_ATTR_WRITER(fxs_ring_registers_store, dev, buf, count)
|
||||
}
|
||||
l_val = h_val;
|
||||
h_val = 0;
|
||||
XPD_INFO(xpd, "%s Direct 0x%X <=== 0x%X\n",
|
||||
XPD_DBG(SIGNAL, xpd, "%s Direct 0x%X <=== 0x%X\n",
|
||||
rtype_name, regno, h_val);
|
||||
}
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
|
||||
@@ -524,9 +524,12 @@ static void PRI_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
|
||||
//XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask);
|
||||
/* Add/remove all the trivial cases */
|
||||
pcm_mask |= PHONEDEV(xpd).offhook_state;
|
||||
if (priv->is_cas)
|
||||
pcm_mask |= BITMASK(PHONEDEV(xpd).channels);
|
||||
for_each_line(xpd, i)
|
||||
if (IS_SET(pcm_mask, i))
|
||||
line_count++;
|
||||
else
|
||||
if (priv->is_cas) {
|
||||
if (priv->pri_protocol == PRI_PROTO_E1) {
|
||||
/* CAS: Don't send PCM to D-Channel */
|
||||
@@ -611,7 +614,7 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
||||
}
|
||||
priv->pri_protocol = set_proto;
|
||||
priv->is_cas = -1;
|
||||
phonedev->channels = pri_num_channels(set_proto);
|
||||
phonedev_alloc_channels(xpd, pri_num_channels(set_proto));
|
||||
phonedev->offhook_state = BITMASK(phonedev->channels);
|
||||
CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
|
||||
priv->deflaw = deflaw;
|
||||
@@ -1082,6 +1085,7 @@ static int pri_set_spantype(struct dahdi_span *span, enum spantypes spantype)
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
enum pri_protocol set_proto = PRI_PROTO_0;
|
||||
int ret;
|
||||
|
||||
XPD_INFO(xpd, "%s: %s\n", __func__, dahdi_spantype2str(spantype));
|
||||
switch (spantype) {
|
||||
@@ -1099,7 +1103,13 @@ static int pri_set_spantype(struct dahdi_span *span, enum spantypes spantype)
|
||||
__func__, dahdi_spantype2str(spantype));
|
||||
return -EINVAL;
|
||||
}
|
||||
return set_pri_proto(xpd, set_proto);
|
||||
ret = set_pri_proto(xpd, set_proto);
|
||||
if (ret < 0) {
|
||||
XPD_ERR(xpd, "%s: set_pri_proto failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
dahdi_init_span(span);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int PRI_card_open(xpd_t *xpd, lineno_t pos)
|
||||
@@ -1224,7 +1234,7 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
||||
if (priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 0)
|
||||
set_mode_cas(xpd, 0);
|
||||
} else {
|
||||
if (chan->channo == 1) {
|
||||
if (chan->chanpos == 1) {
|
||||
XPD_DBG(GENERAL, xpd,
|
||||
"channel %d (%s) marked a not DChan\n",
|
||||
chan->channo, chan->name);
|
||||
@@ -1929,7 +1939,8 @@ static void PRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
|
||||
dchan_state(xpd, 0);
|
||||
}
|
||||
if (IS_SET(physical_mask, i)) {
|
||||
r = XPD_CHAN(xpd, logical_chan)->readchunk;
|
||||
struct dahdi_chan *chan = XPD_CHAN(xpd, logical_chan);
|
||||
r = chan->readchunk;
|
||||
// memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE); // DEBUG
|
||||
memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE);
|
||||
pcm += DAHDI_CHUNKSIZE;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/blackfin.h>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
#include <linux/ctype.h>
|
||||
#endif
|
||||
@@ -60,8 +61,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;
|
||||
@@ -79,8 +80,14 @@ static struct proc_dir_entry *proc_xbuses;
|
||||
|
||||
static struct xbus_desc {
|
||||
xbus_t *xbus;
|
||||
int shutting_down;
|
||||
} xbuses_array[MAX_BUSES];
|
||||
|
||||
static int xbus_is_shutting_down(int num)
|
||||
{
|
||||
return xbuses_array[num].shutting_down;
|
||||
}
|
||||
|
||||
static xbus_t *xbus_byhwid(const char *hwid)
|
||||
{
|
||||
int i;
|
||||
@@ -148,6 +155,8 @@ static void init_xbus(uint num, xbus_t *xbus)
|
||||
BUG_ON(num >= ARRAY_SIZE(xbuses_array));
|
||||
desc = &xbuses_array[num];
|
||||
desc->xbus = xbus;
|
||||
if (xbus)
|
||||
desc->shutting_down = 0;
|
||||
}
|
||||
|
||||
xbus_t *xbus_num(uint num)
|
||||
@@ -187,9 +196,12 @@ static void finalize_xbuses_array(void)
|
||||
static void xbus_destroy(struct kref *kref)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
int num;
|
||||
|
||||
xbus = kref_to_xbus(kref);
|
||||
XBUS_NOTICE(xbus, "%s\n", __func__);
|
||||
XBUS_DBG(DEVICES, xbus, "%s\n", __func__);
|
||||
num = xbus->num;
|
||||
xbuses_array[num].shutting_down = 1;
|
||||
xbus_sysfs_remove(xbus);
|
||||
}
|
||||
|
||||
@@ -198,6 +210,11 @@ xbus_t *get_xbus(const char *msg, uint num)
|
||||
unsigned long flags;
|
||||
xbus_t *xbus;
|
||||
|
||||
if (xbus_is_shutting_down(num)) {
|
||||
DBG(DEVICES, "%s(%s): XBUS-%d: shutting down\n", __func__,
|
||||
msg, num);
|
||||
return NULL;
|
||||
}
|
||||
spin_lock_irqsave(&xbuses_lock, flags);
|
||||
xbus = xbus_num(num);
|
||||
if (xbus != NULL) {
|
||||
@@ -211,6 +228,13 @@ xbus_t *get_xbus(const char *msg, uint num)
|
||||
|
||||
void put_xbus(const char *msg, xbus_t *xbus)
|
||||
{
|
||||
if (xbus_is_shutting_down(xbus->num)) {
|
||||
if (!refcount_xbus(xbus)) {
|
||||
DBG(DEVICES, "%s(%s): XBUS-%d: shutting down\n",
|
||||
__func__, msg, xbus->num);
|
||||
return;
|
||||
}
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n", msg,
|
||||
refcount_xbus(xbus));
|
||||
kref_put(&xbus->kref, xbus_destroy);
|
||||
@@ -560,6 +584,14 @@ static void receive_tasklet_func(unsigned long data)
|
||||
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe)
|
||||
{
|
||||
BUG_ON(!xbus);
|
||||
if (xbus_is_shutting_down(xbus->num)) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 1000) == 0)
|
||||
XBUS_NOTICE(xbus, "%s: during shutdown (%d)\n",
|
||||
__func__, rate_limit);
|
||||
return;
|
||||
}
|
||||
if (rx_tasklet) {
|
||||
xframe_enqueue_recv(xbus, xframe);
|
||||
} else {
|
||||
@@ -953,10 +985,14 @@ int xbus_register_dahdi_device(xbus_t *xbus)
|
||||
goto err;
|
||||
}
|
||||
if (xbus_is_registered(xbus)) {
|
||||
XBUS_ERR(xbus, "Already registered to DAHDI\n");
|
||||
WARN_ON(1);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
/*
|
||||
* Ignore duplicate registrations (from dahdi_registration)
|
||||
* Until we completely migrate to dahdi_autoreg=1 and
|
||||
* hotplug-based span-assignments
|
||||
*/
|
||||
XBUS_DBG(DEVICES, xbus, "Already registered to DAHDI\n");
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
xbus->ddev = dahdi_create_device();
|
||||
if (!xbus->ddev) {
|
||||
@@ -1030,26 +1066,34 @@ void xbus_unregister_dahdi_device(xbus_t *xbus)
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
XBUS_NOTICE(xbus, "%s\n", __func__);
|
||||
XBUS_DBG(DEVICES, xbus, "%s\n", __func__);
|
||||
ret = mutex_lock_interruptible(&dahdi_registration_mutex);
|
||||
if (ret < 0) {
|
||||
XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n");
|
||||
return;
|
||||
}
|
||||
if (!xbus_is_registered(xbus)) {
|
||||
/*
|
||||
* Ignore duplicate unregistrations
|
||||
*/
|
||||
XBUS_DBG(DEVICES, xbus, "Already unregistered to DAHDI\n");
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
xpd_dahdi_preunregister(xpd);
|
||||
}
|
||||
if (xbus->ddev) {
|
||||
dahdi_unregister_device(xbus->ddev);
|
||||
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n",
|
||||
__func__);
|
||||
XBUS_DBG(DEVICES, xbus,
|
||||
"%s: finished dahdi_unregister_device()\n", __func__);
|
||||
xbus_free_ddev(xbus);
|
||||
}
|
||||
for (i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
xpd_dahdi_postunregister(xpd);
|
||||
}
|
||||
err:
|
||||
mutex_unlock(&dahdi_registration_mutex);
|
||||
}
|
||||
|
||||
@@ -1118,7 +1162,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 (!dahdi_get_auto_assign_spans())
|
||||
xbus_register_dahdi_device(xbus);
|
||||
out:
|
||||
XBUS_DBG(DEVICES, xbus, "Leaving\n");
|
||||
@@ -1176,8 +1220,7 @@ static void worker_reset(xbus_t *xbus)
|
||||
name = (xbus) ? xbus->busname : "detached";
|
||||
DBG(DEVICES, "%s\n", name);
|
||||
if (!worker->xpds_init_done) {
|
||||
NOTICE("%s: worker(%s)->xpds_init_done=%d\n", __func__, name,
|
||||
worker->xpds_init_done);
|
||||
XBUS_NOTICE(xbus, "XPDS initialization was not finished\n");
|
||||
}
|
||||
spin_lock_irqsave(&worker->worker_lock, flags);
|
||||
list_for_each_safe(card, next_card, &worker->card_list) {
|
||||
@@ -1195,13 +1238,15 @@ static void worker_reset(xbus_t *xbus)
|
||||
spin_unlock_irqrestore(&worker->worker_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called only after worker_reset(xbus)
|
||||
*/
|
||||
static void worker_destroy(xbus_t *xbus)
|
||||
{
|
||||
struct xbus_workqueue *worker;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
worker = &xbus->worker;
|
||||
worker_reset(xbus);
|
||||
XBUS_DBG(DEVICES, xbus, "Waiting for worker to finish...\n");
|
||||
down(&worker->running_initialization);
|
||||
XBUS_DBG(DEVICES, xbus, "Waiting for worker to finish -- done\n");
|
||||
@@ -1254,6 +1299,7 @@ static int worker_run(xbus_t *xbus)
|
||||
}
|
||||
return 1;
|
||||
err:
|
||||
worker_reset(xbus);
|
||||
worker_destroy(xbus);
|
||||
return 0;
|
||||
}
|
||||
@@ -1421,6 +1467,7 @@ void xbus_disconnect(xbus_t *xbus)
|
||||
del_timer_sync(&xbus->command_timer);
|
||||
transportops_put(xbus);
|
||||
transport_destroy(xbus);
|
||||
/* worker_reset(xbus) was called in xbus_deactivate(xbus) */
|
||||
worker_destroy(xbus);
|
||||
XBUS_DBG(DEVICES, xbus, "Deactivated refcount_xbus=%d\n",
|
||||
refcount_xbus(xbus));
|
||||
@@ -1470,6 +1517,7 @@ void xbus_free(xbus_t *xbus)
|
||||
num = xbus->num;
|
||||
BUG_ON(!xbuses_array[num].xbus);
|
||||
BUG_ON(xbus != xbuses_array[num].xbus);
|
||||
init_xbus(num, NULL);
|
||||
spin_unlock_irqrestore(&xbuses_lock, flags);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (xbus->proc_xbus_dir) {
|
||||
@@ -1496,7 +1544,6 @@ void xbus_free(xbus_t *xbus)
|
||||
#endif
|
||||
spin_lock_irqsave(&xbuses_lock, flags);
|
||||
XBUS_DBG(DEVICES, xbus, "Going to free...\n");
|
||||
init_xbus(num, NULL);
|
||||
spin_unlock_irqrestore(&xbuses_lock, flags);
|
||||
KZFREE(xbus);
|
||||
}
|
||||
@@ -1627,10 +1674,6 @@ int waitfor_xpds(xbus_t *xbus, char *buf)
|
||||
* FIXME: worker is created before ?????
|
||||
* So by now it exists and initialized.
|
||||
*/
|
||||
/* until end of waitfor_xpds_show(): */
|
||||
xbus = get_xbus(__func__, xbus->num);
|
||||
if (!xbus)
|
||||
return -ENODEV;
|
||||
worker = &xbus->worker;
|
||||
BUG_ON(!worker);
|
||||
if (!worker->wq) {
|
||||
@@ -1669,7 +1712,6 @@ int waitfor_xpds(xbus_t *xbus, char *buf)
|
||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||
}
|
||||
out:
|
||||
put_xbus(__func__, xbus); /* from start of waitfor_xpds_show() */
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -1977,6 +2019,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");
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
#include <linux/ctype.h>
|
||||
@@ -31,6 +30,7 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h> /* for msleep() to debug */
|
||||
#include <linux/sched.h>
|
||||
#include "xpd.h"
|
||||
#include "xpp_dahdi.h"
|
||||
#include "xbus-core.h"
|
||||
@@ -303,6 +303,42 @@ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
|
||||
xbus_attr(connector, "%s\n");
|
||||
xbus_attr(label, "%s\n");
|
||||
|
||||
static DEVICE_ATTR_WRITER(dahdi_registration_store, dev, buf, count)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
int dahdi_reg;
|
||||
int ret;
|
||||
|
||||
xbus = dev_to_xbus(dev);
|
||||
if (!xbus)
|
||||
return -ENODEV;
|
||||
ret = sscanf(buf, "%d", &dahdi_reg);
|
||||
if (ret != 1)
|
||||
return -EINVAL;
|
||||
if (dahdi_reg) {
|
||||
ret = xbus_register_dahdi_device(xbus);
|
||||
if (ret < 0) {
|
||||
XBUS_ERR(xbus,
|
||||
"xbus_register_dahdi_device() failed (ret = %d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
xbus_unregister_dahdi_device(xbus);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_READER(dahdi_registration_show, dev, buf)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
int len;
|
||||
|
||||
xbus = dev_to_xbus(dev);
|
||||
len = sprintf(buf, "%d\n", xbus_is_registered(xbus));
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct device_attribute xbus_dev_attrs[] = {
|
||||
__ATTR_RO(connector),
|
||||
__ATTR_RO(label),
|
||||
@@ -317,6 +353,9 @@ static struct device_attribute xbus_dev_attrs[] = {
|
||||
#ifdef SAMPLE_TICKS
|
||||
__ATTR(samples, S_IWUSR | S_IRUGO, samples_show, samples_store),
|
||||
#endif
|
||||
__ATTR(dahdi_registration, S_IRUGO | S_IWUSR,
|
||||
dahdi_registration_show,
|
||||
dahdi_registration_store),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
@@ -596,8 +635,6 @@ static DEVICE_ATTR_READER(span_show, dev, buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEFINE_MUTEX(span_store_mutex);
|
||||
|
||||
/*
|
||||
* For backward compatibility with old dahdi-tools
|
||||
* Remove after dahdi_registration is upgraded
|
||||
@@ -619,29 +656,10 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
|
||||
return -ENODEV;
|
||||
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use assigned-spans)\n",
|
||||
(dahdi_reg) ? "register" : "unregister");
|
||||
ret = mutex_lock_interruptible(&span_store_mutex);
|
||||
if (ret < 0) {
|
||||
XBUS_ERR(xpd->xbus, "span_store_mutex already taken\n");
|
||||
return ret;
|
||||
}
|
||||
if (xbus_is_registered(xpd->xbus)) {
|
||||
if (dahdi_reg) {
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"already registered %s. Ignored.\n",
|
||||
xpd->xbus->busname);
|
||||
} else {
|
||||
xbus_unregister_dahdi_device(xpd->xbus);
|
||||
}
|
||||
} else {
|
||||
if (!dahdi_reg) {
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"already unregistered %s. Ignored.\n",
|
||||
xpd->xbus->busname);
|
||||
} else {
|
||||
xbus_register_dahdi_device(xpd->xbus);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&span_store_mutex);
|
||||
if (dahdi_reg)
|
||||
xbus_register_dahdi_device(xpd->xbus);
|
||||
else
|
||||
xbus_unregister_dahdi_device(xpd->xbus);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -950,10 +968,13 @@ void xbus_sysfs_remove(xbus_t *xbus)
|
||||
struct device *astribank;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
XBUS_DBG(DEVICES, xbus, "\n");
|
||||
astribank = &xbus->astribank;
|
||||
if (!dev_get_drvdata(astribank))
|
||||
if (!dev_get_drvdata(astribank)) {
|
||||
XBUS_NOTICE(xbus, "%s: already removed\n", __func__);
|
||||
return;
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus, "going to unregister: refcount=%d\n",
|
||||
atomic_read(&astribank->kobj.kref.refcount));
|
||||
BUG_ON(dev_get_drvdata(astribank) != xbus);
|
||||
device_unregister(astribank);
|
||||
dev_set_drvdata(astribank, NULL);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/slab.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#include <linux/semaphore.h>
|
||||
#else
|
||||
|
||||
@@ -458,29 +458,28 @@ static void phonedev_cleanup(xpd_t *xpd)
|
||||
unsigned int x;
|
||||
|
||||
for (x = 0; x < phonedev->channels; x++) {
|
||||
if (phonedev->chans[x])
|
||||
if (phonedev->chans[x]) {
|
||||
KZFREE(phonedev->chans[x]);
|
||||
if (phonedev->ec[x])
|
||||
phonedev->chans[x] = NULL;
|
||||
}
|
||||
if (phonedev->ec[x]) {
|
||||
KZFREE(phonedev->ec[x]);
|
||||
phonedev->ec[x] = NULL;
|
||||
}
|
||||
}
|
||||
phonedev->channels = 0;
|
||||
}
|
||||
|
||||
__must_check static int phonedev_init(xpd_t *xpd,
|
||||
const xproto_table_t *proto_table,
|
||||
int channels, xpp_line_t no_pcm)
|
||||
int phonedev_alloc_channels(xpd_t *xpd, int channels)
|
||||
{
|
||||
struct phonedev *phonedev = &PHONEDEV(xpd);
|
||||
int old_channels = phonedev->channels;
|
||||
unsigned int x;
|
||||
|
||||
spin_lock_init(&phonedev->lock_recompute_pcm);
|
||||
XPD_DBG(DEVICES, xpd, "Reallocating channels: %d -> %d\n",
|
||||
old_channels, channels);
|
||||
phonedev_cleanup(xpd);
|
||||
phonedev->channels = channels;
|
||||
phonedev->no_pcm = no_pcm;
|
||||
phonedev->offhook_state = 0x0; /* ONHOOK */
|
||||
phonedev->phoneops = proto_table->phoneops;
|
||||
phonedev->digital_outputs = 0;
|
||||
phonedev->digital_inputs = 0;
|
||||
atomic_set(&phonedev->dahdi_registered, 0);
|
||||
atomic_set(&phonedev->open_counter, 0);
|
||||
for (x = 0; x < phonedev->channels; x++) {
|
||||
if (!
|
||||
(phonedev->chans[x] =
|
||||
@@ -501,6 +500,29 @@ err:
|
||||
phonedev_cleanup(xpd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL(phonedev_alloc_channels);
|
||||
|
||||
__must_check static int phonedev_init(xpd_t *xpd,
|
||||
const xproto_table_t *proto_table,
|
||||
int channels, xpp_line_t no_pcm)
|
||||
{
|
||||
struct phonedev *phonedev = &PHONEDEV(xpd);
|
||||
|
||||
spin_lock_init(&phonedev->lock_recompute_pcm);
|
||||
phonedev->no_pcm = no_pcm;
|
||||
phonedev->offhook_state = 0x0; /* ONHOOK */
|
||||
phonedev->phoneops = proto_table->phoneops;
|
||||
phonedev->digital_outputs = 0;
|
||||
phonedev->digital_inputs = 0;
|
||||
atomic_set(&phonedev->dahdi_registered, 0);
|
||||
atomic_set(&phonedev->open_counter, 0);
|
||||
if (phonedev_alloc_channels(xpd, channels) < 0)
|
||||
goto err;
|
||||
return 0;
|
||||
err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* xpd_alloc - Allocator for new XPD's
|
||||
@@ -692,15 +714,15 @@ EXPORT_SYMBOL(hookstate_changed);
|
||||
/*------------------------- Dahdi Interfaces -----------------------*/
|
||||
|
||||
/*
|
||||
* Called from dahdi with spinlock held on chan. Must not call back
|
||||
* Called with spinlock held on chan. Must not call back
|
||||
* dahdi functions.
|
||||
*/
|
||||
int xpp_open(struct dahdi_chan *chan)
|
||||
static int _xpp_open(struct dahdi_chan *chan)
|
||||
{
|
||||
xpd_t *xpd;
|
||||
xbus_t *xbus;
|
||||
int pos;
|
||||
unsigned long flags;
|
||||
int open_counter;
|
||||
|
||||
if (!chan) {
|
||||
NOTICE("open called on a null chan\n");
|
||||
@@ -721,31 +743,37 @@ int xpp_open(struct dahdi_chan *chan)
|
||||
LINE_NOTICE(xpd, pos, "Cannot open -- device not ready\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
spin_lock_irqsave(&xbus->lock, flags);
|
||||
atomic_inc(&PHONEDEV(xpd).open_counter);
|
||||
open_counter = atomic_inc_return(&PHONEDEV(xpd).open_counter);
|
||||
LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", current->comm,
|
||||
current->pid, atomic_read(&PHONEDEV(xpd).open_counter));
|
||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||
current->pid, open_counter);
|
||||
if (PHONE_METHOD(card_open, xpd))
|
||||
CALL_PHONE_METHOD(card_open, xpd, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xpp_open(struct dahdi_chan *chan)
|
||||
{
|
||||
unsigned long flags;
|
||||
int res;
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
res = _xpp_open(chan);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_open);
|
||||
|
||||
int xpp_close(struct dahdi_chan *chan)
|
||||
{
|
||||
xpd_t *xpd = chan->pvt;
|
||||
xbus_t *xbus = xpd->xbus;
|
||||
int pos = chan->chanpos - 1;
|
||||
unsigned long flags;
|
||||
int open_counter;
|
||||
|
||||
spin_lock_irqsave(&xbus->lock, flags);
|
||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||
if (PHONE_METHOD(card_close, xpd))
|
||||
CALL_PHONE_METHOD(card_close, xpd, pos);
|
||||
/* from xpp_open(): */
|
||||
open_counter = atomic_dec_return(&PHONEDEV(xpd).open_counter);
|
||||
LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", current->comm,
|
||||
current->pid, atomic_read(&PHONEDEV(xpd).open_counter));
|
||||
atomic_dec(&PHONEDEV(xpd).open_counter); /* from xpp_open() */
|
||||
current->pid, open_counter);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_close);
|
||||
@@ -1025,12 +1053,9 @@ EXPORT_SYMBOL(xpd_set_spanname);
|
||||
static void xpd_init_span(xpd_t *xpd, unsigned offset, int cn)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
int i;
|
||||
|
||||
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));
|
||||
|
||||
phonedev_alloc_channels(xpd, cn);
|
||||
span = &PHONEDEV(xpd).span;
|
||||
span->deflaw = DAHDI_LAW_MULAW; /* card_* drivers may override */
|
||||
span->channels = cn;
|
||||
|
||||
@@ -38,6 +38,7 @@ xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits,
|
||||
int channels);
|
||||
void xpd_free(xpd_t *xpd);
|
||||
void xpd_remove(xpd_t *xpd);
|
||||
int phonedev_alloc_channels(xpd_t *xpd, int channels);
|
||||
void update_xpd_status(xpd_t *xpd, int alarm_flag);
|
||||
const char *xpp_echocan_name(const struct dahdi_chan *chan);
|
||||
int xpp_echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
@@ -64,6 +65,7 @@ void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig);
|
||||
extern struct proc_dir_entry *xpp_proc_toplevel;
|
||||
#endif
|
||||
|
||||
#define SPAN_REGISTERED(xpd) atomic_read(&PHONEDEV(xpd).dahdi_registered)
|
||||
#define SPAN_REGISTERED(xpd) (atomic_read(&PHONEDEV(xpd).dahdi_registered) && \
|
||||
test_bit(DAHDI_FLAGBIT_REGISTERED, &PHONEDEV(xpd).span.flags))
|
||||
|
||||
#endif /* XPP_DAHDI_H */
|
||||
|
||||
@@ -211,7 +211,7 @@ static xusb_t *xusb_array[MAX_BUSES] = { };
|
||||
static unsigned bus_count;
|
||||
|
||||
/* prevent races between open() and disconnect() */
|
||||
static DEFINE_SEMAPHORE(disconnect_sem);
|
||||
static DEFINE_MUTEX(protect_xusb_devices);
|
||||
|
||||
/*
|
||||
* AsteriskNow kernel has backported the "lean" callback from 2.6.20
|
||||
@@ -652,6 +652,7 @@ static int xusb_probe(struct usb_interface *interface,
|
||||
iface_desc->desc.bInterfaceNumber, model_info->iface_num);
|
||||
return -ENODEV;
|
||||
}
|
||||
mutex_lock(&protect_xusb_devices);
|
||||
if ((retval = usb_reset_device(udev)) < 0) {
|
||||
ERR("usb_reset_device failed: %d\n", retval);
|
||||
goto probe_failed;
|
||||
@@ -759,6 +760,7 @@ static int xusb_probe(struct usb_interface *interface,
|
||||
for (i = 0; i < 10; i++)
|
||||
xusb_listen(xusb);
|
||||
xbus_connect(xbus);
|
||||
mutex_unlock(&protect_xusb_devices);
|
||||
return retval;
|
||||
probe_failed:
|
||||
ERR("Failed to initialize xpp usb bus: %d\n", retval);
|
||||
@@ -785,6 +787,7 @@ probe_failed:
|
||||
ERR("Calling xbus_disconnect()\n");
|
||||
xbus_disconnect(xbus); // Blocking until fully deactivated!
|
||||
}
|
||||
mutex_unlock(&protect_xusb_devices);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -810,7 +813,7 @@ static void xusb_disconnect(struct usb_interface *interface)
|
||||
DBG(DEVICES, "CALLED on interface #%d\n",
|
||||
iface_desc->desc.bInterfaceNumber);
|
||||
/* prevent races with open() */
|
||||
down(&disconnect_sem);
|
||||
mutex_lock(&protect_xusb_devices);
|
||||
|
||||
xusb = usb_get_intfdata(interface);
|
||||
usb_set_intfdata(interface, NULL);
|
||||
@@ -844,7 +847,7 @@ static void xusb_disconnect(struct usb_interface *interface)
|
||||
XUSB_INFO(xusb, "now disconnected\n");
|
||||
KZFREE(xusb);
|
||||
|
||||
up(&disconnect_sem);
|
||||
mutex_unlock(&protect_xusb_devices);
|
||||
}
|
||||
|
||||
static void xpp_send_callback(USB_PASS_CB(urb))
|
||||
|
||||
@@ -425,6 +425,7 @@ struct dahdi_chan {
|
||||
int lastnumbufs;
|
||||
#endif
|
||||
spinlock_t lock;
|
||||
struct mutex mutex;
|
||||
char name[40];
|
||||
/* Specified by DAHDI */
|
||||
/*! \brief DAHDI channel number */
|
||||
@@ -941,6 +942,7 @@ struct dahdi_device {
|
||||
const char *devicetype;
|
||||
struct device dev;
|
||||
unsigned int irqmisses;
|
||||
struct timespec registration_time;
|
||||
};
|
||||
|
||||
struct dahdi_span {
|
||||
@@ -1280,6 +1282,8 @@ static inline void dahdi_ec_span(struct dahdi_span *span)
|
||||
|
||||
extern struct file_operations *dahdi_transcode_fops;
|
||||
|
||||
int dahdi_get_auto_assign_spans(void);
|
||||
|
||||
/* Don't use these directly -- they're not guaranteed to
|
||||
be there. */
|
||||
extern short __dahdi_mulaw[256];
|
||||
@@ -1589,6 +1593,10 @@ struct mutex {
|
||||
#define chan_err(chan, fmt, ...) chan_printk(ERR, "", chan, fmt, \
|
||||
## __VA_ARGS__)
|
||||
|
||||
#ifndef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
#endif
|
||||
|
||||
#ifndef pr_err
|
||||
#define pr_err(fmt, ...) \
|
||||
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
|
||||
|
||||
Reference in New Issue
Block a user