[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