summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsruffell <sruffell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-11-17 19:43:23 +0000
committersruffell <sruffell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-11-17 19:43:23 +0000
commitce8078871b3737c73d41631bec9e8c95ad0636af (patch)
treed05c63e41c517260daad498cb9f81915a18b8eaa
parent7b0d20fc9bcae0eb5a7d5e3d0f71aca8341b7e4c (diff)
- Fix for race condition of encoder and decoder are allocated at the same time
in the driver. This would result in -EBUSY returns from the DAHDI_TC_ALLOCATE ioctl. - Increase the length of the receive descriptor ring from 8 to 32 to reduce the probability of running out of receive descriptors. git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@4582 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rw-r--r--kernel/wctc4xxp/base.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/kernel/wctc4xxp/base.c b/kernel/wctc4xxp/base.c
index 097321a..7092b61 100644
--- a/kernel/wctc4xxp/base.c
+++ b/kernel/wctc4xxp/base.c
@@ -432,8 +432,6 @@ struct channel_pvt {
struct channel_stats stats;
u16 last_dte_seqno;
- unsigned int wctc4xxp_seqno_rcv;
-
unsigned char ssrc;
struct list_head rx_queue; /* Transcoded packets for this channel. */
};
@@ -898,7 +896,7 @@ struct wctc4xxp_descriptor {
__le32 container; /* Unused */
} __attribute__((packed));
-#define DRING_SIZE (1 << 3) /* Must be a power of two */
+#define DRING_SIZE (1 << 5) /* Must be a power of two */
#define DRING_MASK (DRING_SIZE-1)
#define MIN_PACKET_LEN 64
@@ -1444,6 +1442,7 @@ wctc4xxp_cleanup_channel_private(struct wcdte *wc,
spin_lock_bh(&cpvt->lock);
list_splice_init(&cpvt->rx_queue, &local_list);
zt_tc_clear_data_waiting(dtc);
+ cpvt->last_dte_seqno = 0;
spin_unlock_bh(&cpvt->lock);
list_for_each_entry_safe(cmd, temp, &local_list, node) {
@@ -1492,7 +1491,19 @@ do_channel_allocate(struct zt_transcoder_channel *dtc)
u8 wctc4xxp_dstfmt; /* Digium Transcoder Engine Dest Format */
int res;
- down(&wc->chansem);
+ if (down_interruptible(&wc->chansem)) {
+ return -EINTR;
+ }
+ /* Check again to see if the channel was built after grabbing the
+ * channel semaphore, in case the previous holder of the semaphore
+ * built this channel as a complement to itself. */
+ if (dahdi_tc_is_built(dtc)) {
+ up(&wc->chansem);
+ DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP,
+ "Allocating channel %p which is already built.\n", dtc);
+ return 0;
+ }
+
DTE_DEBUG(DTE_DEBUG_CHANNEL_SETUP,
"Entering %s for channel %p.\n", __FUNCTION__, dtc);
/* Anything on the rx queue now is old news... */
@@ -1557,10 +1568,10 @@ wctc4xxp_operation_release(struct zt_transcoder_channel *dtc)
return -EIO;
}
- /* !!!SRR!!! change this back to down after troubleshooting */
if (down_interruptible(&wc->chansem)) {
return -EINTR;
}
+
/* Remove any packets that are waiting on the outbound queue. */
wctc4xxp_cleanup_channel_private(wc, dtc);
index = cpvt->timeslot_in_num/2;
@@ -1578,9 +1589,9 @@ wctc4xxp_operation_release(struct zt_transcoder_channel *dtc)
goto error_exit;
}
/* If the channel complement (other half of the encoder/decoder pair) is
- * being used... */
+ * being used.*/
if (zt_tc_is_busy(compl_dtc)) {
- res = -EBUSY;
+ res = 0;
goto error_exit;
}
if ((res = wctc4xxp_destroy_channel_pair(wc, cpvt))) {
@@ -1598,7 +1609,6 @@ wctc4xxp_operation_release(struct zt_transcoder_channel *dtc)
compl_cpvt = compl_dtc->pvt;
compl_cpvt->chan_in_num = INVALID;
compl_cpvt->chan_out_num = INVALID;
- cpvt->wctc4xxp_seqno_rcv = 0;
error_exit:
up(&wc->chansem);
return res;
@@ -1676,20 +1686,18 @@ wctc4xxp_read(struct file *file, char __user *frame, size_t count, loff_t *ppos)
atomic_inc(&cpvt->stats.packets_received);
- if (0 == cpvt->wctc4xxp_seqno_rcv) {
- cpvt->wctc4xxp_seqno_rcv = 1;
+ if (!(cpvt->last_dte_seqno)) {
cpvt->last_dte_seqno = be16_to_cpu(packet->rtphdr.seqno);
} else {
rtp_eseq = ++cpvt->last_dte_seqno;
- if ( be16_to_cpu(packet->rtphdr.seqno) != rtp_eseq )
+ cpvt->last_dte_seqno = be16_to_cpu(packet->rtphdr.seqno);
+ if (rtp_eseq != cpvt->last_dte_seqno)
DTE_DEBUG(DTE_DEBUG_GENERAL,
"Bad seqno from DTE! [%04X][%d][%d][%d]\n",
be16_to_cpu(packet->rtphdr.seqno),
(be16_to_cpu(packet->udphdr.dest) - 0x5000),
be16_to_cpu(packet->rtphdr.seqno),
rtp_eseq);
-
- cpvt->last_dte_seqno = be16_to_cpu(packet->rtphdr.seqno);
}
if (unlikely(copy_to_user(frame, &packet->payload[0], payload_bytes))) {