xpp: PRI stability fixes
* We didn't handle proper E1/T1 transitions after device registration. * Fix SPAN_REGISTERED(xpd): It now checks for DAHDI_FLAGBIT_REGISTERED as well, as this flag is set/clear by assign/unassign. * From set_pri_proto(): - Always free/allocate channels - Always call dahdi_init_span() * Improve phonedev_cleanup() safety: - NULL pointers after free. - Zero number of channels at the end. * Refactor channel allocation out of phonedev_init(): - Into phonedev_alloc_channels() - Also called from xpd_init_span() to prevent duplicated logic. - And called from set_pri_proto() to prevent our bug. Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
This commit is contained in:
parent
06c45b7cd8
commit
d4868092bf
@ -611,7 +611,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 +1082,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 +1100,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)
|
||||
@ -1929,7 +1936,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;
|
||||
|
@ -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_NOTICE(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
|
||||
@ -1025,12 +1047,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 */
|
||||
|
Loading…
Reference in New Issue
Block a user