wctc4xxp: Do not allow duplicated sequence numbers to be received for the channels.
Makes the channels themselves behave like the supervisor channel. This only protects the driver in the case the commands were severly backed up, like when there was high packet loss. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
This commit is contained in:
parent
391ca2b7aa
commit
3446cdca8f
@ -204,6 +204,7 @@ struct tcb {
|
|||||||
#define WAIT_FOR_RESPONSE (__WAIT_FOR_RESPONSE | DO_NOT_AUTO_FREE)
|
#define WAIT_FOR_RESPONSE (__WAIT_FOR_RESPONSE | DO_NOT_AUTO_FREE)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct tcb *response;
|
struct tcb *response;
|
||||||
|
struct channel_pvt *cpvt;
|
||||||
struct completion complete;
|
struct completion complete;
|
||||||
/* The number of bytes available in data. */
|
/* The number of bytes available in data. */
|
||||||
int data_len;
|
int data_len;
|
||||||
@ -289,6 +290,7 @@ struct channel_pvt {
|
|||||||
u16 seqno;
|
u16 seqno;
|
||||||
u8 cmd_seqno;
|
u8 cmd_seqno;
|
||||||
u8 ssrc;
|
u8 ssrc;
|
||||||
|
u8 last_rx_seq_num;
|
||||||
u16 timeslot_in_num; /* DTE timeslot to receive from */
|
u16 timeslot_in_num; /* DTE timeslot to receive from */
|
||||||
u16 timeslot_out_num; /* DTE timeslot to send data to */
|
u16 timeslot_out_num; /* DTE timeslot to send data to */
|
||||||
u16 chan_in_num; /* DTE channel to receive from */
|
u16 chan_in_num; /* DTE channel to receive from */
|
||||||
@ -1041,6 +1043,7 @@ create_supervisor_cmd(struct wcdte *wc, struct tcb *cmd, u8 type, u8 class,
|
|||||||
|
|
||||||
cmd->flags = WAIT_FOR_RESPONSE;
|
cmd->flags = WAIT_FOR_RESPONSE;
|
||||||
cmd->data_len = SIZE_WITH_N_PARAMETERS(num_parameters);
|
cmd->data_len = SIZE_WITH_N_PARAMETERS(num_parameters);
|
||||||
|
cmd->cpvt = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1069,6 +1072,7 @@ create_channel_cmd(struct channel_pvt *pvt, struct tcb *cmd, u8 type, u8 class,
|
|||||||
|
|
||||||
cmd->flags = WAIT_FOR_RESPONSE;
|
cmd->flags = WAIT_FOR_RESPONSE;
|
||||||
cmd->data_len = SIZE_WITH_N_PARAMETERS(num_parameters);
|
cmd->data_len = SIZE_WITH_N_PARAMETERS(num_parameters);
|
||||||
|
cmd->cpvt = pvt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1669,6 +1673,7 @@ wctc4xxp_init_state(struct channel_pvt *cpvt, int encoder,
|
|||||||
cpvt->ssrc = 0x78;
|
cpvt->ssrc = 0x78;
|
||||||
cpvt->timeslot_in_num = channel*2;
|
cpvt->timeslot_in_num = channel*2;
|
||||||
cpvt->timeslot_out_num = channel*2;
|
cpvt->timeslot_out_num = channel*2;
|
||||||
|
cpvt->last_rx_seq_num = 0xff;
|
||||||
if (encoder)
|
if (encoder)
|
||||||
++cpvt->timeslot_out_num;
|
++cpvt->timeslot_out_num;
|
||||||
else
|
else
|
||||||
@ -2223,15 +2228,18 @@ wctc4xxp_send_ack(struct wcdte *wc, u8 seqno, __be16 channel)
|
|||||||
wctc4xxp_transmit_cmd(wc, cmd);
|
wctc4xxp_transmit_cmd(wc, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void do_rx_response_packet(struct wcdte *wc, struct tcb *cmd)
|
static void do_rx_response_packet(struct wcdte *wc, struct tcb *cmd)
|
||||||
{
|
{
|
||||||
const struct csm_encaps_hdr *listhdr, *rxhdr;
|
struct csm_encaps_hdr *rxhdr;
|
||||||
|
const struct csm_encaps_hdr *listhdr;
|
||||||
struct tcb *pos, *temp;
|
struct tcb *pos, *temp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
rxhdr = cmd->data;
|
rxhdr = cmd->data;
|
||||||
|
|
||||||
|
/* Check if duplicated response on the supervisor channel. */
|
||||||
if (SUPERVISOR_CHANNEL == rxhdr->channel) {
|
if (SUPERVISOR_CHANNEL == rxhdr->channel) {
|
||||||
/* We received a duplicate response. */
|
|
||||||
if (rxhdr->seq_num == wc->last_rx_seq_num) {
|
if (rxhdr->seq_num == wc->last_rx_seq_num) {
|
||||||
free_cmd(cmd);
|
free_cmd(cmd);
|
||||||
return;
|
return;
|
||||||
@ -2246,6 +2254,16 @@ static void do_rx_response_packet(struct wcdte *wc, struct tcb *cmd)
|
|||||||
if ((listhdr->function == rxhdr->function) &&
|
if ((listhdr->function == rxhdr->function) &&
|
||||||
(listhdr->channel == rxhdr->channel)) {
|
(listhdr->channel == rxhdr->channel)) {
|
||||||
|
|
||||||
|
/* If this is a channel command, do not complete it if
|
||||||
|
* the seq_num is the same as previous. */
|
||||||
|
if (pos->cpvt) {
|
||||||
|
if (rxhdr->seq_num ==
|
||||||
|
pos->cpvt->last_rx_seq_num) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos->cpvt->last_rx_seq_num = rxhdr->seq_num;
|
||||||
|
}
|
||||||
|
|
||||||
list_del_init(&pos->node);
|
list_del_init(&pos->node);
|
||||||
pos->flags &= ~(__WAIT_FOR_RESPONSE);
|
pos->flags &= ~(__WAIT_FOR_RESPONSE);
|
||||||
pos->response = cmd;
|
pos->response = cmd;
|
||||||
@ -3029,6 +3047,8 @@ wctc4xxp_create_channel_pair(struct wcdte *wc, struct channel_pvt *cpvt,
|
|||||||
decoder_pvt = wc->udecode->channels[decoder_timeslot/2].pvt;
|
decoder_pvt = wc->udecode->channels[decoder_timeslot/2].pvt;
|
||||||
BUG_ON(!encoder_pvt);
|
BUG_ON(!encoder_pvt);
|
||||||
BUG_ON(!decoder_pvt);
|
BUG_ON(!decoder_pvt);
|
||||||
|
encoder_pvt->last_rx_seq_num = 0xff;
|
||||||
|
decoder_pvt->last_rx_seq_num = 0xff;
|
||||||
|
|
||||||
WARN_ON(encoder_timeslot == decoder_timeslot);
|
WARN_ON(encoder_timeslot == decoder_timeslot);
|
||||||
/* First, let's create two channels, one for the simple -> complex
|
/* First, let's create two channels, one for the simple -> complex
|
||||||
|
Loading…
Reference in New Issue
Block a user