[zaptel-commits] sruffell: branch 1.4 r4633 - in /branches/1.4/kernel: ./ wctc4xxp/

SVN commits to the Zaptel project zaptel-commits at lists.digium.com
Tue Mar 24 14:59:47 CDT 2009


Author: sruffell
Date: Tue Mar 24 14:59:43 2009
New Revision: 4633

URL: http://svn.digium.com/svn-view/zaptel?view=rev&rev=4633
Log:
Backporting changes to the transcoder from dahdi.

- Fix bug where asterisk could not find a loaded transcoder.
- Do not allow bad packets to corrupt memory.
- Eliminate race condition that could cause asterisk to hang.
- General cleanup and whitespace changes.


Modified:
    branches/1.4/kernel/wctc4xxp/base.c
    branches/1.4/kernel/zaptel.h
    branches/1.4/kernel/zttranscode.c

Modified: branches/1.4/kernel/wctc4xxp/base.c
URL: http://svn.digium.com/svn-view/zaptel/branches/1.4/kernel/wctc4xxp/base.c?view=diff&rev=4633&r1=4632&r2=4633
==============================================================================
--- branches/1.4/kernel/wctc4xxp/base.c (original)
+++ branches/1.4/kernel/wctc4xxp/base.c Tue Mar 24 14:59:43 2009
@@ -1,7 +1,7 @@
 /*
  * Wildcard TC400B Driver
  *
- * Copyright (C) 2006-2008, Digium, Inc.
+ * Copyright (C) 2006-2009, Digium, Inc.
  *
  * All rights reserved.
  *
@@ -30,7 +30,7 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/jiffies.h>
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
@@ -48,7 +48,7 @@
 #define WORKQUEUE 1
 #define TASKLET   2
 
-#ifndef DEFERRED_PROCESSING 
+#ifndef DEFERRED_PROCESSING
 #	define DEFERRED_PROCESSING WORKQUEUE
 #endif
 
@@ -63,16 +63,16 @@
 #define WARN_ALWAYS() WARN_ON(1)
 
 #define DTE_PRINTK(_lvl, _fmt, _args...) \
-	   printk(KERN_##_lvl "%s: %s: " _fmt, THIS_MODULE->name, \
-	          (wc)->board_name, ## _args)
-
-#define DTE_DEBUG(_dbgmask, _fmt, _args...)                                 \
-	if ((debug & _dbgmask) == (_dbgmask)) {                             \
-		printk(KERN_DEBUG "%s: %s: " _fmt, THIS_MODULE->name,       \
-		       (wc)->board_name, ## _args);                         \
-	}                                                                   \
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+	printk(KERN_##_lvl "%s: %s: " _fmt, THIS_MODULE->name, \
+		(wc)->board_name, ## _args)
+
+#define DTE_DEBUG(_dbgmask, _fmt, _args...)				\
+	if ((debug & _dbgmask) == (_dbgmask)) {				\
+		printk(KERN_DEBUG "%s: %s: " _fmt, THIS_MODULE->name,	\
+			(wc)->board_name, ## _args);			\
+	}								\
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
 #ifndef WARN_ON_ONCE
 #define WARN_ON_ONCE(__condition) do {         \
 	static int __once = 1;                 \
@@ -82,12 +82,16 @@
 			WARN_ON(0);            \
 		}                              \
 	}                                      \
-} while(0) 
+} while (0)
 #endif
 #endif
 
+/* The total number of active channels over which the driver will start polling
+ * the card every 10 ms. */
+#define POLLING_CALL_THRESHOLD 40
+
 #define INVALID 999 /* Used to mark invalid channels, commands, etc.. */
-#define MAX_CHANNEL_PACKETS  5 /* Never let more than 5 outstanding packets exist for any channel. */
+#define MAX_CHANNEL_PACKETS  5
 
 #define G729_LENGTH	20
 #define G723_LENGTH	30
@@ -103,16 +107,16 @@
 #define MAX_CAPTURED_PACKETS 5000
 
 /* The following bit fields are used to set the various debug levels. */
-#define DTE_DEBUG_GENERAL          (1 << 0) /* 1  */
-#define DTE_DEBUG_CHANNEL_SETUP    (1 << 1) /* 2  */
-#define DTE_DEBUG_RTP_TX           (1 << 2) /* 4  */
-#define DTE_DEBUG_RTP_RX           (1 << 3) /* 8  */
-#define DTE_DEBUG_RX_TIMEOUT	   (1 << 4) /* 16 */
-#define DTE_DEBUG_NETWORK_IF       (1 << 5) /* 32 */
-#define DTE_DEBUG_NETWORK_EARLY    (1 << 6) /* 64 */
-
-int debug;
-char *mode;
+#define DTE_DEBUG_GENERAL	(1 << 0) /* 1  */
+#define DTE_DEBUG_CHANNEL_SETUP	(1 << 1) /* 2  */
+#define DTE_DEBUG_RTP_TX	(1 << 2) /* 4  */
+#define DTE_DEBUG_RTP_RX	(1 << 3) /* 8  */
+#define DTE_DEBUG_RX_TIMEOUT	(1 << 4) /* 16 */
+#define DTE_DEBUG_NETWORK_IF	(1 << 5) /* 32 */
+#define DTE_DEBUG_NETWORK_EARLY	(1 << 6) /* 64 */
+
+static int debug;
+static char *mode;
 
 static spinlock_t wctc4xxp_list_lock;
 static struct list_head wctc4xxp_list;
@@ -148,7 +152,7 @@
 	struct udphdr udphdr;
 	struct rtphdr rtphdr;
 	__u8   payload[0];
-}__attribute__((packed));
+} __attribute__((packed));
 
 /* Ethernet packet type for communication control information to the DTE. */
 struct csm_encaps_hdr {
@@ -168,165 +172,35 @@
 	__le16 params[0];
 } __attribute__((packed));
 
-struct csm_create_channel_cmd {
-	struct csm_encaps_hdr hdr;
-	__le16 channel_type;
-	__le16 timeslot;
-} __attribute__((packed));
-
-#define CMD_MSG_TDM_SELECT_BUS_MODE_LEN 30
-#define CMD_MSG_TDM_SELECT_BUS_MODE(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x01, 0x00,0x06,0x17,0x04, 0xFF,0xFF, \
-	0x04,0x00 }
-#define CMD_MSG_TDM_ENABLE_BUS_LEN 30
-#define CMD_MSG_TDM_ENABLE_BUS(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x02, 0x00,0x06,0x05,0x04, 0xFF,0xFF, \
-	0x04,0x00 }
-#define CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN 34
-#define CMD_MSG_SUPVSR_SETUP_TDM_PARMS(s,p1,p2,p3) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x10, p1, 0x00,0x06,0x07,0x04, 0xFF,0xFF, \
-	p2,0x83, 0x00,0x0C, 0x00,0x00, p3,0x00 }
-#define CMD_MSG_TDM_OPT_LEN 30
-#define CMD_MSG_TDM_OPT(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x35,0x04, 0xFF,0xFF, \
-	0x00,0x00 }
-#define CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN 30
-#define CMD_MSG_DEVICE_SET_COUNTRY_CODE(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x1B,0x04, 0xFF,0xFF, \
-	0x00,0x00 }
-
-/* CPU Commands */
-#define CMD_MSG_SET_ARM_CLK_LEN 32
-#define CMD_MSG_SET_ARM_CLK(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x11,0x04, 0x00,0x00, \
-	0x2C,0x01, 0x00,0x00 }
-#define CMD_MSG_SET_SPU_CLK_LEN 32
-#define CMD_MSG_SET_SPU_CLK(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x12,0x04, 0x00,0x00, \
-	0x2C,0x01, 0x00,0x00 }
-#define CMD_MSG_SPU_FEATURES_CONTROL_LEN 30
-#define CMD_MSG_SPU_FEATURES_CONTROL(s,p1) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x13,0x00, 0xFF,0xFF, \
-	p1,0x00 }
-#define CMD_MSG_DEVICE_STATUS_CONFIG_LEN 30
-#define CMD_MSG_DEVICE_STATUS_CONFIG(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x0F,0x04, 0xFF,0xFF, \
-	0x05,0x00 }
-
-/* General IP/RTP Commands */
-#define CMD_MSG_SET_ETH_HEADER_LEN 44
-#define CMD_MSG_SET_ETH_HEADER(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x18, 0x00, 0x00,0x06,0x00,0x01, 0xFF,0xFF, \
-	0x01,0x00, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x00,0x11,0x22,0x33,0x44,0x55, 0x08,0x00 }
-#define CMD_MSG_IP_SERVICE_CONFIG_LEN 30
-#define CMD_MSG_IP_SERVICE_CONFIG(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x02,0x03, 0xFF,0xFF, \
-	0x00,0x02 }
-#define CMD_MSG_ARP_SERVICE_CONFIG_LEN 30
-#define CMD_MSG_ARP_SERVICE_CONFIG(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x05,0x01, 0xFF,0xFF, \
-	0x01,0x00 }
-#define CMD_MSG_ICMP_SERVICE_CONFIG_LEN 30
-#define CMD_MSG_ICMP_SERVICE_CONFIG(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x04,0x03, 0xFF,0xFF, \
-	0x01,0xFF }
-#define CMD_MSG_IP_OPTIONS_LEN 30
-#define CMD_MSG_IP_OPTIONS(s) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x06,0x03, 0xFF,0xFF, \
-	0x02,0x00 }
-
 #define CONTROL_PACKET_OPCODE  0x0001
 /* Control bits */
-#define LITTLE_ENDIAN   0x01
-#define SUPPRESS_ACK    0x40
-#define MESSAGE_PACKET  0x80
+#define LITTLE_ENDIAN	0x01
+#define SUPPRESS_ACK	0x40
+#define MESSAGE_PACKET	0x80
 
 #define SUPERVISOR_CHANNEL 0xffff
 
 /* Supervisor function codes */
-#define SUPVSR_CREATE_CHANNEL  0x0010
+#define SUPVSR_CREATE_CHANNEL	0x0010
 
 #define MONITOR_LIVE_INDICATION_TYPE 0x75
-#define CONFIG_CHANGE_TYPE        0x00 
-#define CONFIG_DEVICE_CLASS       0x06
-
-#define CMD_MSG_QUERY_CHANNEL_LEN 30
-#define CMD_MSG_QUERY_CHANNEL(s,t) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x01,0x06,0x10,0x00, 0x00,0x00, \
-	(t&0x00FF), ((t&0xFF00) >> 8) }
-
-#define CMD_MSG_TRANS_CONNECT_LEN 38
-#define CMD_MSG_TRANS_CONNECT(s,e,c1,c2,f1,f2) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x12, 0x00, 0x00,0x06,0x22,0x93, 0x00,0x00, \
-	e,0x00, (c1&0x00FF),((c1&0xFF00)>>8), f1,0x00, (c2&0x00FF),((c2&0xFF00)>>8), f2,0x00 }
-#define CMD_MSG_DESTROY_CHANNEL_LEN 32
-#define CMD_MSG_DESTROY_CHANNEL(s,t) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x11,0x00, 0x00,0x00, \
-	(t&0x00FF),((t&0xFF00)>>8), 0x00, 0x00 }
+#define CONFIG_CHANGE_TYPE	0x00
+#define CONFIG_CHANNEL_CLASS	0x02
+#define CONFIG_DEVICE_CLASS	0x06
 
 /* Individual channel config commands */
-#define CMD_MSG_SET_IP_HDR_CHANNEL_LEN 58
-#define CMD_MSG_SET_IP_HDR_CHANNEL(s,c,t2,t1) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00) >> 8),(c&0x00FF), 0x26, 0x00, 0x00,0x02,0x00,0x90, 0x00,0x00, \
-	0x00,0x00, 0x45,0x00, 0x00,0x00, 0x00,0x00, 0x40,0x00, 0x80,0x11, 0x00,0x00, \
-	0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, \
-	((t2&0xFF00)>>8)+0x50,(t2&0x00FF), ((t1&0xFF00)>>8)+0x50,(t1&0x00FF), 0x00,0x00, 0x00,0x00 }
-#define CMD_MSG_VOIP_VCEOPT_LEN 40
-#define CMD_MSG_VOIP_VCEOPT(s,c,l,w) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x12, 0x00, 0x00,0x02,0x01,0x80, 0x00,0x00, \
-	0x21,l, 0x00,0x1C, 0x04,0x00, 0x00,0x00, w,0x00, 0x80,0x11 }
-#define CMD_MSG_VOIP_VOPENA_LEN 44
-#define CMD_MSG_VOIP_VOPENA(s,c,f) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x16, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \
-	0x01,0x00, 0x80,f, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x12,0x34, 0x56,0x78, 0x00,0x00 }
-#define CMD_MSG_VOIP_VOPENA_CLOSE_LEN 32
-#define CMD_MSG_VOIP_VOPENA_CLOSE(s,c) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \
-	0x00,0x00, 0x00,0x00 }
-#define CMD_MSG_VOIP_INDCTRL_LEN 32
-#define CMD_MSG_VOIP_INDCTRL(s,c) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x84,0x80, 0x00,0x00, \
-	0x07,0x00, 0x00,0x00 }
-#define CMD_MSG_VOIP_DTMFOPT_LEN 32
-#define CMD_MSG_VOIP_DTMFOPT(s,c) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x02,0x80, 0x00,0x00, \
-	0x08,0x00, 0x00,0x00 }
-
-#define CMD_MSG_VOIP_TONECTL_LEN 32
-#define CMD_MSG_VOIP_TONECTL(s,c) { \
-	0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \
-	0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x5B,0x80, 0x00,0x00, \
-	0x00,0x00, 0x00,0x00 }
-
 #define MAX_FRAME_SIZE 1518
-#define SFRAME_SIZE MAX_FRAME_SIZE 
+#define SFRAME_SIZE MAX_FRAME_SIZE
+
+#define DRING_SIZE (1 << 7) /* Must be a power of two */
+#define DRING_MASK (DRING_SIZE-1)
+#define MIN_PACKET_LEN  64
+
+#undef USE_CUSTOM_MEMCACHE
 
 /* Transcoder buffer (tcb) */
 struct tcb {
-	/* First field so that is aligned by default. */
-	u8 cmd[SFRAME_SIZE];
+	void *data;
 	struct list_head node;
 	unsigned long timeout;
 	unsigned long retries;
@@ -336,7 +210,7 @@
 #define TX_COMPLETE             (1 << 1)
 #define DO_NOT_CAPTURE          (1 << 2)
 #define __WAIT_FOR_ACK          (1 << 3)
-#define __WAIT_FOR_RESPONSE     (1 << 4) 
+#define __WAIT_FOR_RESPONSE     (1 << 4)
 #define DTE_CMD_TIMEOUT         (1 << 5)
 #define WAIT_FOR_ACK (__WAIT_FOR_ACK | DO_NOT_AUTO_FREE)
 #define WAIT_FOR_RESPONSE (__WAIT_FOR_RESPONSE | DO_NOT_AUTO_FREE)
@@ -344,72 +218,161 @@
 	struct tcb *response;
 	struct completion complete;
 	struct timer_list timer;
-	void *data;
 	/* The number of bytes available in data. */
-	int data_len; 
+	int data_len;
+	spinlock_t lock;
+#ifdef USE_CUSTOM_MEMCACHE
+	u32 sentinel;
+#endif
 };
 
-static inline void *hdr_from_cmd(struct tcb *cmd) {
-	return cmd->data;
-}
-
-static inline void 
-initialize_cmd(struct tcb *cmd, unsigned long cmd_flags) 
-{
-	memset(cmd, 0, sizeof(*cmd));
+static inline const struct csm_encaps_hdr *
+response_header(struct tcb *cmd)
+{
+	BUG_ON(!cmd->response);
+	return (const struct csm_encaps_hdr *)(cmd)->response->data;
+}
+
+static inline void
+initialize_cmd(struct tcb *cmd, unsigned long cmd_flags)
+{
 	INIT_LIST_HEAD(&cmd->node);
 	init_completion(&cmd->complete);
 	cmd->flags = cmd_flags;
-	cmd->data = &cmd->cmd[0];
-	cmd->data_len = SFRAME_SIZE;
-}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+	spin_lock_init(&cmd->lock);
+#ifdef USE_CUSTOM_MEMCACHE
+	cmd->sentinel = 0xdeadbeef;
+#endif
+}
+
+#ifdef USE_CUSTOM_MEMCACHE
+
+struct my_cache {
+	atomic_t outstanding_count;
+	spinlock_t lock;
+	struct list_head free;
+};
+
+static struct tcb *my_cache_alloc(struct my_cache *c, gfp_t alloc_flags)
+{
+	unsigned long flags;
+	struct tcb *cmd;
+	spin_lock_irqsave(&c->lock, flags);
+	if (!list_empty(&c->free)) {
+		cmd = list_entry(c->free.next, struct tcb, node);
+		list_del_init(&cmd->node);
+		spin_unlock_irqrestore(&c->lock, flags);
+	} else {
+		spin_unlock_irqrestore(&c->lock, flags);
+		cmd = kmalloc(sizeof(*cmd), alloc_flags);
+	}
+	atomic_inc(&c->outstanding_count);
+	return cmd;
+}
+
+static void my_cache_free(struct my_cache *c, struct tcb *cmd)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&c->lock, flags);
+	list_add_tail(&cmd->node, &c->free);
+	spin_unlock_irqrestore(&c->lock, flags);
+	atomic_dec(&c->outstanding_count);
+}
+
+static struct my_cache *my_cache_create(void)
+{
+	struct my_cache *c;
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return NULL;
+	spin_lock_init(&c->lock);
+	INIT_LIST_HEAD(&c->free);
+	return c;
+}
+
+static int my_cache_destroy(struct my_cache *c)
+{
+	struct tcb *cmd;
+	if (atomic_read(&c->outstanding_count)) {
+		DTE_DEBUG(DTE_DEBUG_GENERAL, "Leaked %d commands.\n",
+			atomic_read(&c->outstanding_count));
+	}
+	while (!list_empty(&c->free)) {
+		cmd = list_entry(c->free.next, struct tcb, node);
+		list_del_init(&cmd->node);
+		kfree(cmd);
+	}
+	kfree(c);
+	return 0;
+}
+
+static struct my_cache *cmd_cache;
+
+#else
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
 /*! Used to allocate commands to submit to the dte. */
 kmem_cache_t *cmd_cache;
 #else
 /*! Used to allocate commands to submit to the dte. */
-struct kmem_cache *cmd_cache;
+static struct kmem_cache *cmd_cache;
 #endif
 
+#endif /* USE_CUSTOM_MEMCACHE */
+
 static inline struct tcb *
-__alloc_cmd(unsigned alloc_flags, unsigned long cmd_flags)
+__alloc_cmd(size_t size, gfp_t alloc_flags, unsigned long cmd_flags)
 {
 	struct tcb *cmd;
 
+	if (unlikely(size > SFRAME_SIZE))
+		return NULL;
+	if (size < MIN_PACKET_LEN)
+		size = MIN_PACKET_LEN;
+#ifdef USE_CUSTOM_MEMCACHE
+	cmd = my_cache_alloc(cmd_cache, alloc_flags);
+#else
 	cmd = kmem_cache_alloc(cmd_cache, alloc_flags);
+#endif
 	if (likely(cmd)) {
+		memset(cmd, 0, sizeof(*cmd));
+		cmd->data = kzalloc(size, alloc_flags);
+		if (unlikely(!cmd->data)) {
+			kmem_cache_free(cmd_cache, cmd);
+			return NULL;
+		}
+		cmd->data_len = size;
 		initialize_cmd(cmd, cmd_flags);
 	}
 	return cmd;
 }
 
 static struct tcb *
-alloc_cmd(void)
-{
-	return __alloc_cmd(GFP_KERNEL, 0);
-}
-
-static void 
+alloc_cmd(size_t size)
+{
+	return __alloc_cmd(size, GFP_KERNEL, 0);
+}
+
+static void
 __free_cmd(struct tcb *cmd)
 {
-	if (cmd->data != &cmd->cmd[0]) {
+	if (cmd)
 		kfree(cmd->data);
-	}
+#ifdef USE_CUSTOM_MEMCACHE
+	my_cache_free(cmd_cache, cmd);
+#else
 	kmem_cache_free(cmd_cache, cmd);
+#endif
 	return;
 }
 
-static void 
+static void
 free_cmd(struct tcb *cmd)
 {
-	if (cmd->response) {
+	if (cmd->response)
 		__free_cmd(cmd->response);
-	}
 	__free_cmd(cmd);
 }
-
-typedef enum { DECODER=0, ENCODER, } encode_t;
 
 struct channel_stats {
 	atomic_t packets_sent;
@@ -417,50 +380,48 @@
 };
 
 struct channel_pvt {
-	spinlock_t lock;		/* Lock for this structure */
-	encode_t encoder;		/* If we're an encoder */
+	spinlock_t lock;	/* Lock for this structure */
 	struct wcdte *wc;
-
-	unsigned int timestamp;
-	unsigned int seqno;
-
-	unsigned int cmd_seqno;
-
-	unsigned int timeslot_in_num;	/* DTE channel on which results will be received from */
-	unsigned int timeslot_out_num;	/* DTE channel to send data to */
-
-	unsigned int chan_in_num;	/* DTE channel on which results will be received from */
-	unsigned int chan_out_num;	/* DTE channel to send data to */
-	
+	u16 seqno;
+	u8 cmd_seqno;
+	u8 ssrc;
+	u16 timeslot_in_num;	/* DTE timeslot to receive from */
+	u16 timeslot_out_num;	/* DTE timeslot to send data to */
+	u16 chan_in_num;	/* DTE channel to receive from */
+	u16 chan_out_num;	/* DTE channel to send data to */
+	u32 timestamp;
+	struct {
+		u8 encoder:1;	/* If we're an encoder */
+	};
 	struct channel_stats stats;
-
-	u16 last_dte_seqno;
-	unsigned char ssrc;
-	struct list_head rx_queue;	/* Transcoded packets for this channel. */
+	struct list_head rx_queue; /* Transcoded packets for this channel. */
 };
 
 struct wcdte {
 	char board_name[40];
 	const char *variety;
 	int pos;
-	int cards;
 	struct list_head node;
 	spinlock_t reglock;
 	wait_queue_head_t waitq;
 	struct semaphore chansem;
 #define DTE_READY	1
-#define DTE_SHUTDOWN	2 
+#define DTE_SHUTDOWN	2
+#define DTE_POLLING	3
 	unsigned long flags;
 
-	spinlock_t cmd_list_lock;
-	spinlock_t rx_list_lock;
 	/* This is a device-global list of commands that are waiting to be
 	 * transmited (and did not fit on the transmit descriptor ring) */
+	spinlock_t cmd_list_lock;
 	struct list_head cmd_list;
 	struct list_head waiting_for_response_list;
+
+	spinlock_t rx_list_lock;
 	struct list_head rx_list;
+	spinlock_t rx_lock;
 
 	unsigned int seq_num;
+	int last_rx_seq_num;
 	unsigned char numchannels;
 	unsigned char complexname[40];
 
@@ -471,7 +432,7 @@
 	unsigned long  iobase;
 	struct wctc4xxp_descriptor_ring *txd;
 	struct wctc4xxp_descriptor_ring *rxd;
-	
+
 	struct zt_transcoder *uencode;
 	struct zt_transcoder *udecode;
 	struct channel_pvt *encoders;
@@ -490,46 +451,45 @@
 	struct sk_buff_head captured_packets;
 	struct net_device *netdev;
 	struct net_device_stats net_stats;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 	struct napi_struct napi;
 #endif
 	struct timer_list watchdog;
-
+	atomic_t open_channels;
+	struct timer_list polling;
+#if HZ > 100
+	unsigned long jiffies_at_last_poll;
+#endif
 };
 
-static inline void wctc4xxp_set_ready(struct wcdte *wc) {
+#ifdef HAVE_NETDEV_PRIV
+struct wcdte_netdev_priv {
+	struct wcdte *wc;
+};
+#endif
+
+static inline struct wcdte *
+wcdte_from_netdev(struct net_device *netdev)
+{
+#ifdef HAVE_NETDEV_PRIV
+	struct wcdte_netdev_priv *priv;
+	priv = netdev_priv(netdev);
+	return priv->wc;
+#else
+	return netdev->priv;
+#endif
+}
+
+
+static inline void wctc4xxp_set_ready(struct wcdte *wc)
+{
 	set_bit(DTE_READY, &wc->flags);
 }
-static inline int wctc4xxp_is_ready(struct wcdte *wc) {
+
+static inline int wctc4xxp_is_ready(struct wcdte *wc)
+{
 	return test_bit(DTE_READY, &wc->flags);
 }
-
-#if 1
- /* \todo This macro is a candidate for removal.  It's still here because of
- * how the commands are passed to this zt_send_cmd */
-#define wctc4xxp_send_cmd(wc, command) ({                                         \
-	int __res;                                                           \
-	u8 _cmd[] = command;                                                 \
-	struct tcb *cmd;                                                 \
-	if (!(cmd=__alloc_cmd(GFP_KERNEL, WAIT_FOR_RESPONSE)))               \
-		return -ENOMEM;                                              \
-	BUG_ON(sizeof(_cmd) > SFRAME_SIZE);                                  \
-	memcpy(cmd->data, _cmd, sizeof(_cmd));                               \
-	cmd->data_len = sizeof(_cmd);                                        \
-	__res = __wctc4xxp_send_cmd(wc, cmd);                                     \
-	__res;                                                               \
-})
-#define wctc4xxp_create_cmd(wc, command) ({                                       \
-	u8 _command[] = command;                                             \
-	struct tcb *_cmd;                                                \
-	if (!(_cmd=__alloc_cmd(GFP_KERNEL, WAIT_FOR_RESPONSE)))              \
-		return -ENOMEM;                                              \
-	BUG_ON(sizeof(_command) > SFRAME_SIZE);                              \
-	memcpy(_cmd->data, _command, sizeof(_command));                      \
-	_cmd->data_len = sizeof(_command);                                   \
-	_cmd;                                                                \
-})
-#endif
 
 #define DTE_FORMAT_ULAW   0x00
 #define DTE_FORMAT_G723_1 0x04
@@ -537,33 +497,32 @@
 #define DTE_FORMAT_G729A  0x12
 #define DTE_FORMAT_UNDEF  0xFF
 
-static inline u8 wctc4xxp_zapfmt_to_dtefmt(unsigned int fmt)
+static inline u8 wctc4xxp_dahdifmt_to_dtefmt(unsigned int fmt)
 {
 	u8 pt;
-	
-	switch(fmt) {
-		case ZT_FORMAT_G723_1:
-			pt = DTE_FORMAT_G723_1;
-			break;
-		case ZT_FORMAT_ULAW:
-			pt = DTE_FORMAT_ULAW;
-			break;
-		case ZT_FORMAT_ALAW:
-			pt = DTE_FORMAT_ALAW;
-			break;
-		case ZT_FORMAT_G729A:
-			pt = DTE_FORMAT_G729A;
-			break;
-		default:
-			pt = DTE_FORMAT_UNDEF;
-			break;
+
+	switch (fmt) {
+	case ZT_FORMAT_G723_1:
+		pt = DTE_FORMAT_G723_1;
+		break;
+	case ZT_FORMAT_ULAW:
+		pt = DTE_FORMAT_ULAW;
+		break;
+	case ZT_FORMAT_ALAW:
+		pt = DTE_FORMAT_ALAW;
+		break;
+	case ZT_FORMAT_G729A:
+		pt = DTE_FORMAT_G729A;
+		break;
+	default:
+		pt = DTE_FORMAT_UNDEF;
+		break;
 	}
 
 	return pt;
 }
 
-
-static struct sk_buff * 
+static struct sk_buff *
 tcb_to_skb(struct net_device *netdev, const struct tcb *cmd)
 {
 	struct sk_buff *skb;
@@ -572,12 +531,12 @@
 		skb->dev = netdev;
 		skb_put(skb, cmd->data_len);
 		memcpy(skb->data, cmd->data, cmd->data_len);
-		skb->protocol = eth_type_trans(skb,netdev);
+		skb->protocol = eth_type_trans(skb, netdev);
 	}
 	return skb;
 }
 
-/** 
+/**
  * wctc4xxp_skb_to_cmd - Convert a socket buffer (skb) to a tcb
  * @wc: The transcoder that we're going to send this command to.
  * @skb: socket buffer to convert.
@@ -586,81 +545,72 @@
 static struct tcb *
 wctc4xxp_skb_to_cmd(struct wcdte *wc, const struct sk_buff *skb)
 {
-	const unsigned long alloc_flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+	const gfp_t alloc_flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
 	struct tcb *cmd;
-	/* const static char dev_mac[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; */
-	if ((cmd = __alloc_cmd(alloc_flags, 0))) {
+	cmd = __alloc_cmd(skb->len, alloc_flags, 0);
+	if (cmd) {
 		int res;
 		cmd->data_len = skb->len;
-		if ((res = skb_copy_bits(skb, 0, cmd->data, cmd->data_len))) {
-			DTE_PRINTK(WARNING, 
+		res = skb_copy_bits(skb, 0, cmd->data, cmd->data_len);
+		if (res) {
+			DTE_PRINTK(WARNING,
 			   "Failed call to skb_copy_bits.\n");
 			free_cmd(cmd);
 			cmd = NULL;
 		}
-		/* When we set up our interface we indicated that we do not
-		 * support ARP.  Therefore, the destination MAC on packets
-		 * arriving from the kernel networking components are not
-		 * going to be correct. Let's fix that here.
-		 */
-		/* \todo let us just use whatever was in the packet already... */
-		/* memcpy(&cmd->cmd[6], dev_mac, sizeof(dev_mac)); */
 	}
 	return cmd;
 }
 
-static void 
+static void
 wctc4xxp_net_set_multi(struct net_device *netdev)
 {
-	struct wcdte *wc = netdev->priv;
-	DTE_DEBUG(DTE_DEBUG_GENERAL, "%s promiscuity:%d\n", 
-	   __FUNCTION__, netdev->promiscuity);
-}
-
-static int 
+	struct wcdte *wc = wcdte_from_netdev(netdev);
+	DTE_DEBUG(DTE_DEBUG_GENERAL, "%s promiscuity:%d\n",
+	   __func__, netdev->promiscuity);
+}
+
+static int
 wctc4xxp_net_up(struct net_device *netdev)
 {
-	struct wcdte *wc = netdev->priv;
-	DTE_DEBUG(DTE_DEBUG_GENERAL, "%s\n", __FUNCTION__);
-#if 1
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	struct wcdte *wc = wcdte_from_netdev(netdev);
+	DTE_DEBUG(DTE_DEBUG_GENERAL, "%s\n", __func__);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
 	netif_poll_enable(netdev);
 #else
 	napi_enable(&wc->napi);
 #endif
-#endif
 	return 0;
 }
 
-static int 
+static int
 wctc4xxp_net_down(struct net_device *netdev)
 {
-	struct wcdte *wc = netdev->priv;
-	DTE_DEBUG(DTE_DEBUG_GENERAL, "%s\n", __FUNCTION__);
-#if 1
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	struct wcdte *wc = wcdte_from_netdev(netdev);
+	DTE_DEBUG(DTE_DEBUG_GENERAL, "%s\n", __func__);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
 	netif_poll_disable(netdev);
 #else
 	napi_disable(&wc->napi);
 #endif
-#endif
 	return 0;
 }
 
 static void wctc4xxp_transmit_cmd(struct wcdte *, struct tcb *);
 
-static int 
+static int
 wctc4xxp_net_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
-	struct wcdte *wc = netdev->priv;
+	struct wcdte *wc = wcdte_from_netdev(netdev);
 	struct tcb *cmd;
 
 	/* We set DO_NOT_CAPTURE because this packet was already captured by
 	 * in code higher up in the networking stack.  We don't want to
-	 * capture it twice. 
+	 * capture it twice.
 	 */
-	if ((cmd = wctc4xxp_skb_to_cmd(wc, skb))) {
-		cmd->flags |= DO_NOT_CAPTURE; 
+	cmd = wctc4xxp_skb_to_cmd(wc, skb);
+	if (cmd) {
+		cmd->flags |= DO_NOT_CAPTURE;
 		wctc4xxp_transmit_cmd(wc, cmd);
 	}
 
@@ -668,7 +618,7 @@
 	return NETDEV_TX_OK;
 }
 
-static int 
+static int
 wctc4xxp_net_receive(struct wcdte *wc, int max)
 {
 	int count = 0;
@@ -676,18 +626,17 @@
 	WARN_ON(0 == max);
 	while ((skb = skb_dequeue(&wc->captured_packets))) {
 		netif_receive_skb(skb);
-		if (++count >= max) {
+		if (++count >= max)
 			break;
-		}
 	}
 	return count;
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-static int 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+static int
 wctc4xxp_poll(struct net_device *netdev, int *budget)
 {
-	struct wcdte *wc = netdev->priv;
+	struct wcdte *wc = wcdte_from_netdev(netdev);
 	int count = 0;
 	int quota = min(netdev->quota, *budget);
 
@@ -704,7 +653,7 @@
 	}
 }
 #else
-static int 
+static int
 wctc4xxp_poll(struct napi_struct *napi, int budget)
 {
 	struct wcdte *wc = container_of(napi, struct wcdte, napi);
@@ -713,7 +662,11 @@
 	count = wctc4xxp_net_receive(wc, budget);
 
 	if (!skb_queue_len(&wc->captured_packets)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
 		netif_rx_complete(wc->netdev, &wc->napi);
+#else
+		netif_rx_complete(&wc->napi);
+#endif
 	}
 	return count;
 }
@@ -722,25 +675,25 @@
 static struct net_device_stats *
 wctc4xxp_net_get_stats(struct net_device *netdev)
 {
-	struct wcdte *wc = netdev->priv;
+	struct wcdte *wc = wcdte_from_netdev(netdev);
 	return &wc->net_stats;
 }
 
 /* Wait until this device is put into promiscuous mode, or we timeout. */
-static void 
+static void
 wctc4xxp_net_waitfor_promiscuous(struct wcdte *wc)
 {
 	unsigned int seconds = 15;
 	unsigned long start = jiffies;
 	struct net_device *netdev = wc->netdev;
 
-	DTE_PRINTK(INFO, 
+	DTE_PRINTK(INFO,
 	   "Waiting %d seconds for adapter to be placed in " \
 	   "promiscuous mode for early trace.\n", seconds);
 
 	while (!netdev->promiscuity) {
 		if (signal_pending(current)) {
-			DTE_PRINTK(INFO, 
+			DTE_PRINTK(INFO,
 			   "Aborting wait due to signal.\n");
 			break;
 		}
@@ -756,11 +709,11 @@
 static int  wctc4xxp_turn_off_booted_led(struct wcdte *wc);
 static void wctc4xxp_turn_on_booted_led(struct wcdte *wc);
 
-static int 
+static int
 wctc4xxp_net_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 {
-	struct wcdte *wc = netdev->priv;
-	switch(cmd) {
+	struct wcdte *wc = wcdte_from_netdev(netdev);
+	switch (cmd) {
 	case 0x89f0:
 		down(&wc->chansem);
 		wctc4xxp_turn_off_booted_led(wc);
@@ -775,27 +728,37 @@
 	return 0;
 }
 
-/** 
+/**
  * wctc4xxp_net_register - Register a new network interface.
  * @wc: transcoder card to register the interface for.
  *
  * The network interface is primarily used for debugging in order to watch the
  * traffic between the transcoder and the host.
- * 
+ *
  */
-static int 
+static int
 wctc4xxp_net_register(struct wcdte *wc)
 {
 	int res;
 	struct net_device *netdev;
+#	ifdef HAVE_NETDEV_PRIV
+	struct wcdte_netdev_priv *priv;
+#	endif
 	const char our_mac[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
 
-	if (!(netdev = alloc_netdev(0, wc->board_name, ether_setup))) {
+#	ifdef HAVE_NETDEV_PRIV
+	netdev = alloc_netdev(sizeof(*priv), wc->board_name, ether_setup);
+	if (!netdev)
 		return -ENOMEM;
-	}
-
+	priv = netdev_priv(netdev);
+	priv->wc = wc;
+#	else
+	netdev = alloc_netdev(0, wc->board_name, ether_setup);
+	if (!netdev)
+		return -ENOMEM;
+	netdev->priv = wc;
+#	endif
 	memcpy(netdev->dev_addr, our_mac, sizeof(our_mac));
-	netdev->priv = wc;
 	netdev->set_multicast_list = &wctc4xxp_net_set_multi;
 	netdev->open = &wctc4xxp_net_up;
 	netdev->stop = &wctc4xxp_net_down;
@@ -804,15 +767,16 @@
 	netdev->do_ioctl = &wctc4xxp_net_ioctl;
 	netdev->promiscuity = 0;
 	netdev->flags |= IFF_NOARP;
-#	if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#	if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
 	netdev->poll = &wctc4xxp_poll;
 	netdev->weight = 64;
 #	else
 	netif_napi_add(netdev, &wc->napi, &wctc4xxp_poll, 64);
 #	endif
 
-	if ((res = register_netdev(netdev))) {
-		DTE_PRINTK(WARNING, 
+	res = register_netdev(netdev);
+	if (res) {
+		DTE_PRINTK(WARNING,
 		   "Failed to register network device %s.\n",
 		   wc->board_name);
 		goto error_sw;
@@ -821,33 +785,29 @@
 	wc->netdev = netdev;
 	skb_queue_head_init(&wc->captured_packets);
 
-	if (debug & DTE_DEBUG_NETWORK_EARLY) {
+	if (debug & DTE_DEBUG_NETWORK_EARLY)
 		wctc4xxp_net_waitfor_promiscuous(wc);
-	}
-
-	DTE_PRINTK(DEBUG, 
+
+	DTE_PRINTK(DEBUG,
 	   "Created network device %s for debug.\n", wc->board_name);
 	return 0;
 
 error_sw:
-	if (netdev) free_netdev(netdev);
+	if (netdev)
+		free_netdev(netdev);
 	return res;
 }
 
-static void 
+static void
 wctc4xxp_net_unregister(struct wcdte *wc)
 {
 	struct sk_buff *skb;
-	if (!wc->netdev) {
+
+	if (!wc->netdev)
 		return;
-	}
-
 	unregister_netdev(wc->netdev);
-
-	while ((skb = skb_dequeue(&wc->captured_packets))) {
+	while ((skb = skb_dequeue(&wc->captured_packets)))
 		kfree_skb(skb);
-	}
-	
 	free_netdev(wc->netdev);
 	wc->netdev = NULL;
 }
@@ -859,35 +819,35 @@
  * @cmd: command to send to network stack.
  *
  */
-static void 
+static void
 wctc4xxp_net_capture_cmd(struct wcdte *wc, const struct tcb *cmd)
 {
 	struct sk_buff *skb;
 	struct net_device *netdev = wc->netdev;
 
-	if (!netdev) {
+	if (!netdev)
 		return;
-	}
 
 	/* No need to capture if there isn't anyone listening. */
-	if (!(netdev->flags & IFF_UP)) {
+	if (!(netdev->flags & IFF_UP))
 		return;
-	}
-	
+
 	if (skb_queue_len(&wc->captured_packets) > MAX_CAPTURED_PACKETS) {
 		WARN_ON_ONCE(1);
 		return;
 	}
 
-	if (!(skb = tcb_to_skb(netdev, cmd))) {
+	skb = tcb_to_skb(netdev, cmd);
+	if (!skb)
 		return;
-	}
 
 	skb_queue_tail(&wc->captured_packets, skb);
-#	if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#	if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
 	netif_rx_schedule(netdev);
+#	elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
+	netif_rx_schedule(netdev, &wc->napi);
 #	else
-	netif_rx_schedule(netdev, &wc->napi);
+	netif_rx_schedule(&wc->napi);
 #	endif
 	return;
 }
@@ -901,13 +861,9 @@
 	__le32 container; /* Unused */
 } __attribute__((packed));
 
-#define DRING_SIZE (1 << 5) /* Must be a power of two */
-#define DRING_MASK (DRING_SIZE-1)
-#define MIN_PACKET_LEN  64
-
 struct wctc4xxp_descriptor_ring {
 	/* Pointer to an array of descriptors to give to hardware. */
-	struct wctc4xxp_descriptor* desc;
+	struct wctc4xxp_descriptor *desc;
 	/* Read completed buffers from the head. */
 	unsigned int 	head;
 	/* Write ready buffers to the tail. */
@@ -932,54 +888,52 @@
  * wctc4xxp_descriptor - Returns the desriptor at index.
  * @dr: The descriptor ring we're using.
  * @index: index of the descriptor we want.
- * 
+ *
  * We need this function because we do not know what the padding on the
  * descriptors will be.  Otherwise, we would just use an array.
  */
 static inline struct wctc4xxp_descriptor *
 wctc4xxp_descriptor(struct wctc4xxp_descriptor_ring *dr, int index)
 {
-	return (struct wctc4xxp_descriptor *)((u8*)dr->desc + 
+	return (struct wctc4xxp_descriptor *)((u8 *)dr->desc +
 		((sizeof(*dr->desc) + dr->padding) * index));
 }
 
 static int
-wctc4xxp_initialize_descriptor_ring(struct pci_dev *pdev, struct wctc4xxp_descriptor_ring *dr, 
-	u32 des1, unsigned int direction)
-{
-	int i; 
+wctc4xxp_initialize_descriptor_ring(struct pci_dev *pdev,
+	struct wctc4xxp_descriptor_ring *dr, u32 des1, unsigned int direction)
+{
+	int i;
 	const u32 END_OF_RING = 0x02000000;
 	u8 cache_line_size = 0;
 	struct wctc4xxp_descriptor *d;
+	int add_padding;
 
 	BUG_ON(!pdev);
 	BUG_ON(!dr);
 
-	if (pci_read_config_byte(pdev, 0x0c, &cache_line_size)) {
-		/* \todo Print an error message... */
+	if (pci_read_config_byte(pdev, 0x0c, &cache_line_size))
 		return -EIO;
-	}
 
 	memset(dr, 0, sizeof(*dr));
 
 	/*
 	 * Add some padding to each descriptor to ensure that they are
-	 * aligned on host system cache-line boundaries, but only for the 
+	 * aligned on host system cache-line boundaries, but only for the
 	 * cache-line sizes that we support.
 	 *
 	 */
-	if ((0x08 == cache_line_size) || (0x10 == cache_line_size) ||
-	    (0x20 == cache_line_size)) 
-	{
+	add_padding =   (0x08 == cache_line_size) ||
+			(0x10 == cache_line_size) ||
+			(0x20 == cache_line_size);
+	if (add_padding)
 		dr->padding = (cache_line_size*sizeof(u32)) - sizeof(*d);
-	} 
-
-	dr->desc = pci_alloc_consistent(pdev, 
+
+	dr->desc = pci_alloc_consistent(pdev,
 			(sizeof(*d)+dr->padding)*DRING_SIZE, &dr->desc_dma);
 
-	if (!dr->desc) {
+	if (!dr->desc)
 		return -ENOMEM;
-	}
 
 	memset(dr->desc, 0, (sizeof(*d) + dr->padding) * DRING_SIZE);
 	for (i = 0; i < DRING_SIZE; ++i) {
@@ -996,12 +950,12 @@
 
 #define OWN_BIT cpu_to_le32(0x80000000)
 #define OWNED(_d_) (((_d_)->des0)&OWN_BIT)
-#define SET_OWNED(_d_) do { wmb(); (_d_)->des0 |= OWN_BIT; wmb();} while (0)
-
-const unsigned int BUFFER1_SIZE_MASK = 0x7ff;
-
-static int 
-wctc4xxp_submit(struct wctc4xxp_descriptor_ring* dr, struct tcb *c)
+#define SET_OWNED(_d_) do { wmb(); (_d_)->des0 |= OWN_BIT; wmb(); } while (0)
+
+static const unsigned int BUFFER1_SIZE_MASK = 0x7ff;
+
+static int
+wctc4xxp_submit(struct wctc4xxp_descriptor_ring *dr, struct tcb *c)
 {
 	volatile struct wctc4xxp_descriptor *d;
 	unsigned int len;
@@ -1015,7 +969,7 @@
 	}
 
 	spin_lock_irqsave(&dr->lock, flags);
-	d = wctc4xxp_descriptor(dr, dr->tail); 
+	d = wctc4xxp_descriptor(dr, dr->tail);
 	WARN_ON(!d);
 	if (d->buffer1) {
 		spin_unlock_irqrestore(&dr->lock, flags);
@@ -1024,10 +978,10 @@
 	}
 	d->des1 &= cpu_to_le32(~(BUFFER1_SIZE_MASK));
 	d->des1 |= cpu_to_le32(len & BUFFER1_SIZE_MASK);
-	d->buffer1 = pci_map_single(dr->pdev, c->data, 
-	                            SFRAME_SIZE, dr->direction);
-
-	SET_OWNED(d); /* That's it until the hardware is done with it. */ 
+	d->buffer1 = pci_map_single(dr->pdev, c->data,
+			SFRAME_SIZE, dr->direction);
+
+	SET_OWNED(d); /* That's it until the hardware is done with it. */
 	dr->pending[dr->tail] = c;
 	dr->tail = ++dr->tail & DRING_MASK;
 	++dr->count;
@@ -1035,7 +989,7 @@
 	return 0;
 }
 
-static inline struct tcb* 
+static inline struct tcb*
 wctc4xxp_retrieve(struct wctc4xxp_descriptor_ring *dr)
 {
 	volatile struct wctc4xxp_descriptor *d;
@@ -1045,16 +999,16 @@
 	spin_lock_irqsave(&dr->lock, flags);
 	d = wctc4xxp_descriptor(dr, head);
 	if (d->buffer1 && !OWNED(d)) {
-		pci_unmap_single(dr->pdev, d->buffer1, 
-		                 SFRAME_SIZE, dr->direction);
+		pci_unmap_single(dr->pdev, d->buffer1,
+			SFRAME_SIZE, dr->direction);
 		c = dr->pending[head];
 		WARN_ON(!c);
-		dr->head = (++head) & DRING_MASK; 
+		dr->head = (++head) & DRING_MASK;
 		d->buffer1 = 0;
 		--dr->count;
 		WARN_ON(!c);
 		c->data_len = (d->des0 >> 16) & BUFFER1_SIZE_MASK;
-		c->flags |= TX_COMPLETE;
+		WARN_ON(c->data_len > SFRAME_SIZE);
 	} else {
 		c = NULL;
 	}
@@ -1062,7 +1016,7 @@
 	return c;
 }
 
-static inline int wctc4xxp_getcount(struct wctc4xxp_descriptor_ring *dr) 
+static inline int wctc4xxp_getcount(struct wctc4xxp_descriptor_ring *dr)
 {
 	int count;
 	unsigned long flags;
@@ -1072,35 +1026,38 @@
 	return count;
 }
 
-static inline void 
+static inline void
 __wctc4xxp_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
 {
 	outl(val, wc->iobase + addr);
 }
 
-static inline unsigned int 
+static inline unsigned int
 __wctc4xxp_getctl(struct wcdte *wc, unsigned int addr)
 {
 	return inl(wc->iobase + addr);
 }
 
-static inline void 
+static inline void
 wctc4xxp_setctl(struct wcdte *wc, unsigned int addr, unsigned int val)
 {
-	spin_lock_bh(&wc->reglock);
+	unsigned long flags;
+	spin_lock_irqsave(&wc->reglock, flags);
 	__wctc4xxp_setctl(wc, addr, val);
-	spin_unlock_bh(&wc->reglock);
-}
-
-static inline void 
-wctc4xxp_receive_demand_poll(struct wcdte *wc) 
+	spin_unlock_irqrestore(&wc->reglock, flags);
+}
+
+static inline void
+wctc4xxp_receive_demand_poll(struct wcdte *wc)
 {
 	__wctc4xxp_setctl(wc, 0x0010, 0x00000000);
 }
 
-static inline void 
+static inline void
 wctc4xxp_transmit_demand_poll(struct wcdte *wc)
 {
+	return;
+# if 0
 	__wctc4xxp_setctl(wc, 0x0008, 0x00000000);
 
 	/* \todo Investigate why this register needs to be written twice in
@@ -1110,11 +1067,13 @@
 	 * problem with the dte firmware.
 	 */
 	__wctc4xxp_setctl(wc, 0x0008, 0x00000000);
+#endif
 }
 
 /* Returns the size, in bytes, of a CSM_ENCAPS packet, given the number of
  * parameters used. */
-#define SIZE_WITH_N_PARAMETERS(__n) (sizeof(struct csm_encaps_hdr) + ((__n) * (sizeof(u16))))
+#define SIZE_WITH_N_PARAMETERS(__n) (sizeof(struct csm_encaps_hdr) + \
+	((__n) * (sizeof(u16))))
 
 /* There are 20 bytes in the ethernet header and the common CSM_ENCAPS header
  * that we don't want in the length of the actual CSM_ENCAPS command */
@@ -1123,7 +1082,9 @@
 static const u8 dst_mac[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
 static const u8 src_mac[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
 
-static void 
+static int wctc4xxp_transmit_cmd_and_wait(struct wcdte *wc, struct tcb *cmd);
+
+static void
 setup_common_header(struct wcdte *wc, struct csm_encaps_hdr *hdr)
 {
 	memcpy(hdr->ethhdr.h_dest, dst_mac, sizeof(dst_mac));
@@ -1131,7 +1092,7 @@
 	hdr->ethhdr.h_proto = cpu_to_be16(ETH_P_CSM_ENCAPS);
 }
 
-static void 
+static void
 setup_supervisor_header(struct wcdte *wc, struct csm_encaps_hdr *hdr)
 {
 	setup_common_header(wc, hdr);

[... 3420 lines stripped ...]



More information about the zaptel-commits mailing list