Compare commits
71 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 |
@@ -5,16 +5,14 @@
|
||||
FIRMWARE_PATTERN=$1
|
||||
FIRMWARE_VERSION=$2
|
||||
DESTDIR=$3
|
||||
target="$DESTDIR/lib/firmware"
|
||||
|
||||
if ! test -f ${DESTDIR}/usr/lib/hotplug/firmware/.${FIRMWARE_PATTERN}-${FIRMWARE_VERSION} || ! test -f ${DESTDIR}/lib/firmware/.${FIRMWARE_PATTERN}-${FIRMWARE_VERSION}; then
|
||||
echo "Installing ${FIRMWARE_PATTERN}.bin to hotplug firmware directories"
|
||||
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 ${DESTDIR}/usr/lib/hotplug/firmware || exit 1
|
||||
rm -rf ${DESTDIR}/usr/lib/hotplug/firmware/.${FIRMWARE_PATTERN}-*
|
||||
touch ${DESTDIR}/usr/lib/hotplug/firmware/.${FIRMWARE_PATTERN}-${FIRMWARE_VERSION}
|
||||
install -m 644 ${FIRMWARE_PATTERN}.bin ${DESTDIR}/lib/firmware || exit 1
|
||||
rm -rf ${DESTDIR}/lib/firmware/.${FIRMWARE_PATTERN}-*
|
||||
touch ${DESTDIR}/lib/firmware/.${FIRMWARE_PATTERN}-${FIRMWARE_VERSION}
|
||||
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
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#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>
|
||||
@@ -990,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");
|
||||
}
|
||||
@@ -1488,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;
|
||||
@@ -1808,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;
|
||||
@@ -1835,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;
|
||||
@@ -1883,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;
|
||||
@@ -2301,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)) {
|
||||
@@ -3053,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;
|
||||
}
|
||||
|
||||
@@ -5225,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;
|
||||
@@ -5267,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);
|
||||
@@ -6330,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;
|
||||
@@ -6340,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;
|
||||
}
|
||||
|
||||
@@ -6357,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;
|
||||
@@ -6427,6 +6453,7 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
}
|
||||
|
||||
exit_with_free:
|
||||
mutex_unlock(&chan->mutex);
|
||||
kfree(params);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 {
|
||||
@@ -1828,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
|
||||
@@ -2115,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;
|
||||
@@ -2328,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,
|
||||
@@ -2344,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,
|
||||
@@ -2718,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;
|
||||
@@ -2817,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;
|
||||
@@ -3304,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);
|
||||
@@ -3695,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 */
|
||||
@@ -3720,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);
|
||||
|
||||
@@ -3728,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) {
|
||||
@@ -4055,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) {
|
||||
@@ -4264,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);
|
||||
@@ -5145,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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
@@ -110,6 +110,7 @@ struct t13x {
|
||||
struct vpm450m *vpm;
|
||||
struct mutex lock;
|
||||
struct wcxb xb;
|
||||
u32 lineconfig_fingerprint;
|
||||
};
|
||||
|
||||
static void te13x_handle_transmit(struct wcxb *xb, void *vfp);
|
||||
@@ -538,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;
|
||||
@@ -563,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);
|
||||
@@ -625,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;
|
||||
@@ -642,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;
|
||||
}
|
||||
@@ -652,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;
|
||||
@@ -714,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;
|
||||
}
|
||||
@@ -752,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;
|
||||
}
|
||||
@@ -778,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;
|
||||
@@ -787,7 +788,7 @@ 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);
|
||||
|
||||
}
|
||||
@@ -1138,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)
|
||||
@@ -1237,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);
|
||||
}
|
||||
|
||||
@@ -1275,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);
|
||||
@@ -1286,6 +1287,18 @@ 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);
|
||||
@@ -1296,7 +1309,7 @@ static int t13x_startup(struct file *file, struct dahdi_span *span)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1313,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);
|
||||
@@ -1474,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);
|
||||
@@ -1486,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);
|
||||
@@ -1495,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);
|
||||
@@ -1504,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);
|
||||
@@ -1519,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);
|
||||
@@ -1555,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;
|
||||
}
|
||||
@@ -1657,12 +1676,37 @@ 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;
|
||||
@@ -1675,10 +1719,13 @@ t13x_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1748,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);
|
||||
@@ -1798,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);
|
||||
@@ -1808,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;
|
||||
@@ -1858,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"));
|
||||
}
|
||||
|
||||
@@ -1873,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;
|
||||
@@ -1906,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;
|
||||
@@ -1928,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 */
|
||||
@@ -1938,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;
|
||||
@@ -2047,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) {
|
||||
@@ -2085,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);
|
||||
@@ -2094,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);
|
||||
@@ -2112,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
|
||||
@@ -2126,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
|
||||
@@ -2238,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))
|
||||
@@ -2270,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);
|
||||
}
|
||||
@@ -2349,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,
|
||||
@@ -2360,6 +2437,8 @@ static const struct dahdi_span_ops t13x_span_ops = {
|
||||
.set_spantype = t13x_set_linemode,
|
||||
.echocan_create = t13x_echocan_create,
|
||||
.echocan_name = t13x_echocan_name,
|
||||
.open = t13x_open,
|
||||
.close = t13x_close,
|
||||
};
|
||||
|
||||
#define SPI_BASE 0x200
|
||||
@@ -2485,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));
|
||||
|
||||
@@ -2544,7 +2622,7 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
|
||||
|
||||
wc->ddev->hardware_id = t13x_read_serial(wc);
|
||||
if (!wc->ddev->hardware_id) {
|
||||
dev_info(&wc->dev->dev, "No serial number found.\n");
|
||||
dev_info(&wc->xb.pdev->dev, "No serial number found.\n");
|
||||
res = -EIO;
|
||||
goto fail_exit;
|
||||
}
|
||||
@@ -2566,11 +2644,11 @@ 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;
|
||||
@@ -2608,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;
|
||||
}
|
||||
|
||||
@@ -2618,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);
|
||||
}
|
||||
|
||||
@@ -2638,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;
|
||||
|
||||
@@ -2679,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;
|
||||
|
||||
|
||||
@@ -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,6 +51,19 @@
|
||||
#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 = 0xe0019;
|
||||
|
||||
@@ -78,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;
|
||||
@@ -97,6 +110,7 @@ struct t43x_span {
|
||||
bool debounce;
|
||||
int syncpos;
|
||||
int sync;
|
||||
u32 lineconfig_fingerprint;
|
||||
};
|
||||
|
||||
struct t43x_clksrc_work {
|
||||
@@ -1210,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.
|
||||
*
|
||||
@@ -1707,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;
|
||||
|
||||
@@ -1727,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 */
|
||||
@@ -1741,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);
|
||||
@@ -1762,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));
|
||||
}
|
||||
|
||||
@@ -2344,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)
|
||||
@@ -2351,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__);
|
||||
@@ -2387,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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2454,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;
|
||||
}
|
||||
|
||||
@@ -2476,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]);
|
||||
@@ -2645,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)))
|
||||
@@ -2664,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");
|
||||
}
|
||||
@@ -2678,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");
|
||||
}
|
||||
@@ -2689,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;
|
||||
@@ -2855,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3149,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,
|
||||
@@ -3161,6 +3253,8 @@ static const struct dahdi_span_ops t43x_span_ops = {
|
||||
.set_spantype = t43x_set_linemode,
|
||||
.echocan_create = t43x_echocan_create,
|
||||
.echocan_name = t43x_echocan_name,
|
||||
.open = t43x_open,
|
||||
.close = t43x_close,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3477,7 +3571,12 @@ static void __devexit t43x_remove_one(struct pci_dev *pdev)
|
||||
wc->vpm = NULL;
|
||||
|
||||
#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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
@@ -1231,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);
|
||||
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
@@ -1034,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);
|
||||
}
|
||||
|
||||
@@ -1180,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) {
|
||||
@@ -1199,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");
|
||||
@@ -1258,6 +1299,7 @@ static int worker_run(xbus_t *xbus)
|
||||
}
|
||||
return 1;
|
||||
err:
|
||||
worker_reset(xbus);
|
||||
worker_destroy(xbus);
|
||||
return 0;
|
||||
}
|
||||
@@ -1425,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));
|
||||
@@ -1474,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) {
|
||||
@@ -1500,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);
|
||||
}
|
||||
@@ -1631,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) {
|
||||
@@ -1673,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,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"
|
||||
@@ -302,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),
|
||||
@@ -316,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,
|
||||
};
|
||||
|
||||
@@ -928,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
|
||||
|
||||
@@ -476,7 +476,7 @@ int phonedev_alloc_channels(xpd_t *xpd, int channels)
|
||||
int old_channels = phonedev->channels;
|
||||
unsigned int x;
|
||||
|
||||
XPD_NOTICE(xpd, "Reallocating channels: %d -> %d\n",
|
||||
XPD_DBG(DEVICES, xpd, "Reallocating channels: %d -> %d\n",
|
||||
old_channels, channels);
|
||||
phonedev_cleanup(xpd);
|
||||
phonedev->channels = channels;
|
||||
@@ -714,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");
|
||||
@@ -743,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);
|
||||
|
||||
@@ -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 */
|
||||
@@ -1592,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