From e42548f2c5e867f10da339f4ceb5cf158c265bed Mon Sep 17 00:00:00 2001 From: Russ Meyerriecks Date: Fri, 18 Oct 2013 16:21:42 -0500 Subject: [PATCH] wcte13xp: Migrate to wcxb library From: Russ Meyerriecks Removed all the custom logic and replaced with the common platform wcxb stuff. There are also changes in here to standardize the function prefix in this driver to t13x_. Signed-off-by: Shaun Ruffell --- drivers/dahdi/Kbuild | 2 +- drivers/dahdi/wcte13xp-base.c | 1573 ++++++++++----------------------- 2 files changed, 492 insertions(+), 1083 deletions(-) diff --git a/drivers/dahdi/Kbuild b/drivers/dahdi/Kbuild index cc60d2a..15357d1 100644 --- a/drivers/dahdi/Kbuild +++ b/drivers/dahdi/Kbuild @@ -14,7 +14,7 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o -wcte13xp-objs := wcte13xp-base.o +wcte13xp-objs := wcte13xp-base.o wcxb_spi.o wcxb.o wcxb_flash.o CFLAGS_wcte13xp-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api ifeq ($(HOTPLUG_FIRMWARE),yes) CFLAGS_wcte13xp-base.o += -DHOTPLUG_FIRMWARE diff --git a/drivers/dahdi/wcte13xp-base.c b/drivers/dahdi/wcte13xp-base.c index a5573ed..86db245 100644 --- a/drivers/dahdi/wcte13xp-base.c +++ b/drivers/dahdi/wcte13xp-base.c @@ -39,6 +39,13 @@ #include #include "wct4xxp/wct4xxp.h" /* For certain definitions */ +#include "wcxb.h" +#include "wcxb_spi.h" +#include "wcxb_flash.h" + +static const char *TE133_FW_FILENAME = "dahdi-fw-te133.bin"; +static const char *TE134_FW_FILENAME = "dahdi-fw-te134.bin"; +static const u32 TE13X_FW_VERSION = 0x6f0017; #define VPM_SUPPORT #define WC_MAX_IFACES 8 @@ -58,66 +65,17 @@ enum linemode { /* Descriptor ring definitions */ #define DRING_SIZE (1 << 7) /* Must be in multiples of 2 */ -#define DRING_SIZE_MASK (DRING_SIZE-1) -#define DESC_EOR (1 << 0) -#define DESC_INT (1 << 1) -#define DESC_OWN (1 << 31) -#define DESC_DEFAULT_STATUS 0xdeadbeef #define DMA_CHAN_SIZE 128 -/* DMA definitions */ -#define TDM_DRING_ADDR 0x2000 -#define TDM_CONTROL (TDM_DRING_ADDR + 0x4) -#define ENABLE_ECHOCAN_TDM (1 << 0) -#define TDM_RECOVER_CLOCK (1 << 1) -#define ENABLE_DMA (1 << 2) -#define DMA_RUNNING (1 << 3) -#define DMA_LOOPBACK (1 << 4) -#define AUTHENTICATED (1 << 5) -#define TDM_VERSION (TDM_DRING_ADDR + 0x24) - /* Interrupt definitions */ #define INTERRUPT_CONTROL 0x300 -#define ISR (INTERRUPT_CONTROL + 0x0) -#define IPR (INTERRUPT_CONTROL + 0x4) #define IER (INTERRUPT_CONTROL + 0x8) -#define IAR (INTERRUPT_CONTROL + 0xc) -#define SIE (INTERRUPT_CONTROL + 0x10) -#define CIE (INTERRUPT_CONTROL + 0x14) -#define IVR (INTERRUPT_CONTROL + 0x18) -#define MER (INTERRUPT_CONTROL + 0x1c) -#define MER_ME (1<<0) -#define MER_HIE (1<<1) -#define DESC_UNDERRUN (1<<0) -#define DESC_COMPLETE (1<<1) -#define OCT_INT (1<<2) -#define FALC_INT (1<<3) -#define SPI_INT (1<<4) - -struct t13x_hw_desc { - volatile __be32 status; - __be32 tx_buf; - __be32 rx_buf; - volatile __be32 control; -} __packed; - -struct t13x_meta_desc { - void *tx_buf_virt; - void *rx_buf_virt; -}; +#define FALC_INT (1<<3) struct t13x { struct pci_dev *dev; spinlock_t reglock; - unsigned long framecount; - void __iomem *membase; - struct t13x_meta_desc *meta_dring; - struct t13x_hw_desc *hw_dring; - unsigned int dma_head; - unsigned int dma_tail; - dma_addr_t hw_dring_phys; - struct dma_pool *pool; u8 latency; const struct t13x_desc *devtype; @@ -138,7 +96,6 @@ struct t13x { #define INITIALIZED 1 #define SHUTDOWN 2 #define READY 3 -#define LATENCY_LOCKED 4 unsigned long bit_flags; u32 ledstate; struct dahdi_device *ddev; @@ -150,14 +107,22 @@ struct t13x { struct timer_list timer; struct work_struct timer_work; struct workqueue_struct *wq; - unsigned int not_ready; /* 0 when entire card is ready to go */ #ifdef VPM_SUPPORT struct vpm450m *vpm; #endif struct mutex lock; + struct wcxb xb; }; -static void reset_dring(struct t13x *); +static void te13x_handle_transmit(struct wcxb *xb, void *vfp); +static void te13x_handle_receive(struct wcxb *xb, void *vfp); +static void te13x_handle_interrupt(struct wcxb *xb, u32 pending); + +static struct wcxb_operations xb_ops = { + .handle_receive = te13x_handle_receive, + .handle_transmit = te13x_handle_transmit, + .handle_interrupt = te13x_handle_interrupt, +}; /* Maintenance Mode Registers */ #define LIM0 0x36 @@ -192,16 +157,8 @@ static void reset_dring(struct t13x *); #define CCR1 0x09 /* pci memory map offsets */ -#define DMA1 0x00 /* dma addresses */ -#define DMA2 0x04 -#define DMA3 0x08 -#define CNTL 0x0C /* fpga control register */ -#define INT_MASK 0x10 /* interrupt vectors from oct and framer */ -#define INT_STAT 0x14 #define FRAMER_BASE 0x00000800 /* framer's address space */ -#define TE13X_DEFAULT_LATENCY 3 - static int debug; static int alarmdebounce = 2500; /* LOF/LFA def to 2.5s AT&T TR54016*/ static int losalarmdebounce = 2500; /* LOS def to 2.5s AT&T TR54016*/ @@ -209,7 +166,7 @@ static int aisalarmdebounce = 2500; /* AIS(blue) def to 2.5s AT&T TR54016*/ static int yelalarmdebounce = 500; /* RAI(yellow) def to 0.5s AT&T devguide */ static char *default_linemode = "t1"; /* 'e1', 't1', or 'j1' */ static int force_firmware; -static int latency = TE13X_DEFAULT_LATENCY; +static int latency = WCXB_DEFAULT_LATENCY; struct t13x_firm_header { u8 header[6]; @@ -219,8 +176,8 @@ struct t13x_firm_header { } __packed; -static void t1_check_alarms(struct t13x *wc); -static void t1_check_sigbits(struct t13x *wc); +static void t13x_check_alarms(struct t13x *wc); +static void t13x_check_sigbits(struct t13x *wc); #ifdef VPM_SUPPORT #include @@ -246,7 +203,7 @@ static void t1_check_sigbits(struct t13x *wc); #define RIN_STREAM 0 #define SIN_STREAM 2 -#define OCT_OFFSET (wc->membase + 0x10000) +#define OCT_OFFSET (wc->xb.membase + 0x10000) #define OCT_CONTROL_REG (OCT_OFFSET + 0) #define OCT_DATA_REG (OCT_OFFSET + 0x4) #define OCT_ADDRESS_HIGH_REG (OCT_OFFSET + 0x8) @@ -280,31 +237,16 @@ struct vpm450m { static void oct_reset(struct t13x *wc) { - unsigned long flags; - int reg; - spin_lock_irqsave(&wc->reglock, flags); - reg = ioread32be(wc->membase); - iowrite32be((reg & ~OCT_CPU_RESET), wc->membase); - spin_unlock_irqrestore(&wc->reglock, flags); - + wcxb_gpio_clear(&wc->xb, OCT_CPU_RESET); msleep_interruptible(1); + wcxb_gpio_set(&wc->xb, OCT_CPU_RESET); - spin_lock_irqsave(&wc->reglock, flags); - reg = ioread32be(wc->membase); - iowrite32be((reg | OCT_CPU_RESET), wc->membase); - spin_unlock_irqrestore(&wc->reglock, flags); - - dev_info(&wc->dev->dev, "Reset octasic\n"); + dev_info(&wc->xb.pdev->dev, "Reset octasic\n"); } static void oct_enable_dram(struct t13x *wc) { - unsigned long flags; - int reg; - spin_lock_irqsave(&wc->reglock, flags); - reg = ioread32be(wc->membase); - iowrite32be((reg | OCT_CPU_DRAM_CKE), wc->membase); - spin_unlock_irqrestore(&wc->reglock, flags); + wcxb_gpio_set(&wc->xb, OCT_CPU_DRAM_CKE); } static unsigned int oct_get_reg_indirect(void *data, uint32_t address) @@ -576,7 +518,7 @@ static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw, tOCT6100_CHANNEL_OPEN *ChannelOpen; UINT32 ulResult; struct vpm450m *vpm450m; - int x, i, reg; + int x, i; vpm450m = kzalloc(sizeof(struct vpm450m), GFP_KERNEL); if (!vpm450m) { @@ -703,13 +645,8 @@ static struct vpm450m *init_vpm450m(struct t13x *wc, int isalaw, } } - reg = ioread32be(wc->membase + TDM_CONTROL); - if (vpmsupport == 1) - iowrite32be(reg | ENABLE_ECHOCAN_TDM, - wc->membase + TDM_CONTROL); - else - iowrite32be(reg & ~ENABLE_ECHOCAN_TDM, - wc->membase + TDM_CONTROL); + if (vpmsupport != 0) + wcxb_enable_echocan(&wc->xb); kfree(ChipOpen); kfree(ChannelOpen); @@ -840,7 +777,7 @@ static void t13x_vpm_init(struct t13x *wc) } #endif /* VPM_SUPPORT */ -static int t1xxp_clear_maint(struct dahdi_span *span); +static int t13x_clear_maint(struct dahdi_span *span); static struct t13x *ifaces[WC_MAX_IFACES]; @@ -856,130 +793,136 @@ static inline bool is_pcie(const struct t13x *t1) return t1->devtype == &te133; } -static int __t1_pci_get(struct t13x *wc, unsigned int addr) +static int __t13x_pci_get(struct t13x *wc, unsigned int addr) { - unsigned int res = ioread8(wc->membase + addr); + unsigned int res = ioread8(wc->xb.membase + addr); return res; } -static inline int __t1_pci_set(struct t13x *wc, unsigned int addr, int val) +static inline int __t13x_pci_set(struct t13x *wc, unsigned int addr, int val) { - iowrite8(val, wc->membase + addr); - __t1_pci_get(wc, 0); + iowrite8(val, wc->xb.membase + addr); + __t13x_pci_get(wc, 0); return 0; } -static inline int t1_pci_get(struct t13x *wc, int addr) +static inline int t13x_pci_get(struct t13x *wc, int addr) { unsigned int ret; unsigned long flags; spin_lock_irqsave(&wc->reglock, flags); - ret = __t1_pci_get(wc, addr); + ret = __t13x_pci_get(wc, addr); spin_unlock_irqrestore(&wc->reglock, flags); return ret; } -static inline int t1_pci_set(struct t13x *wc, int addr, int val) +static inline int t13x_pci_set(struct t13x *wc, int addr, int val) { unsigned long flags; unsigned int ret; spin_lock_irqsave(&wc->reglock, flags); - ret = __t1_pci_set(wc, addr, val); + ret = __t13x_pci_set(wc, addr, val); spin_unlock_irqrestore(&wc->reglock, flags); return ret; } -static inline int __t1_framer_set(struct t13x *wc, int addr, int val) +static inline int __t13x_framer_set(struct t13x *wc, int addr, int val) { - return __t1_pci_set(wc, FRAMER_BASE + addr, val); + return __t13x_pci_set(wc, FRAMER_BASE + addr, val); } -static inline int t1_framer_set(struct t13x *wc, int addr, int val) +static inline int t13x_framer_set(struct t13x *wc, int addr, int val) { - return t1_pci_set(wc, FRAMER_BASE + addr, val); + return t13x_pci_set(wc, FRAMER_BASE + addr, val); } -static inline int __t1_framer_get(struct t13x *wc, int addr) +static inline int __t13x_framer_get(struct t13x *wc, int addr) { - return __t1_pci_get(wc, FRAMER_BASE + addr); + return __t13x_pci_get(wc, FRAMER_BASE + addr); } -static inline int t1_framer_get(struct t13x *wc, int addr) +static inline int t13x_framer_get(struct t13x *wc, int addr) { - return t1_pci_get(wc, FRAMER_BASE + addr); + return t13x_pci_get(wc, FRAMER_BASE + addr); } -static void t1_framer_reset(struct t13x *wc) +static void t13x_framer_reset(struct t13x *wc) { - unsigned long flags; - u32 scratch; - spin_lock_irqsave(&wc->reglock, flags); - scratch = ioread32be(wc->membase); - iowrite32be(scratch & ~(1UL << 11), wc->membase); - ioread32be(wc->membase); - udelay(100); - iowrite32be(scratch, wc->membase); - ioread32be(wc->membase); - spin_unlock_irqrestore(&wc->reglock, flags); + /* + * When the framer is reset, RCLK will stop. The FPGA must be switched + * to it's internal clock when this happens, but it's only safe to + * switch the clock source on the FPGA when the DMA engine is stopped. + * + */ + wcxb_stop_dma(&wc->xb); + wcxb_wait_for_stop(&wc->xb, 50); + wcxb_set_clksrc(&wc->xb, WCXB_CLOCK_SELF); + wcxb_gpio_clear(&wc->xb, FALC_CPU_RESET); + msleep_interruptible(100); + wcxb_gpio_set(&wc->xb, FALC_CPU_RESET); } -static void t1_setleds(struct t13x *wc, u32 leds) +static void t13x_setleds(struct t13x *wc, u32 leds) { - unsigned long flags; static const u32 LED_MASK = 0x600; - u32 scratch; - spin_lock_irqsave(&wc->reglock, flags); - scratch = ((ioread32be(wc->membase) & ~LED_MASK) | (leds & LED_MASK)); - iowrite32be(scratch, wc->membase); - spin_unlock_irqrestore(&wc->reglock, flags); + wcxb_gpio_set(&wc->xb, leds & LED_MASK); + wcxb_gpio_clear(&wc->xb, ~leds & LED_MASK); } -static void __t1xxp_set_clear(struct t13x *wc) +static void __t13x_set_clear(struct t13x *wc) { int i, offset; int reg; - unsigned char ccb[3] = {0, 0, 0}; unsigned long flags; + bool span_has_cas_channel = false; - /* Calculate all states on all 24 channels using the channel - flags, then write all 3 clear channel registers at once */ + if (dahdi_is_e1_span(&wc->span)) { + span_has_cas_channel = !(wc->span.lineconfig&DAHDI_CONFIG_CCS); + } else { + unsigned char ccb[3] = {0, 0, 0}; + /* Sort out channels that use CAS signalling */ + for (i = 0; i < wc->span.channels; i++) { + offset = i/8; + if (offset >= ARRAY_SIZE(ccb)) { + WARN_ON(1); + break; + } + if (wc->span.chans[i]->flags & DAHDI_FLAG_CLEAR) + ccb[offset] |= 1 << (7 - (i % 8)); + else + ccb[offset] &= ~(1 << (7 - (i % 8))); + } - for (i = 0; i < wc->span.channels; i++) { - offset = i/8; - if (wc->span.chans[i]->flags & DAHDI_FLAG_CLEAR) - ccb[offset] |= 1 << (7 - (i % 8)); - else - ccb[offset] &= ~(1 << (7 - (i % 8))); + spin_lock_irqsave(&wc->reglock, flags); + __t13x_framer_set(wc, CCB1, ccb[0]); + __t13x_framer_set(wc, CCB2, ccb[1]); + __t13x_framer_set(wc, CCB3, ccb[2]); + spin_unlock_irqrestore(&wc->reglock, flags); + + if ((~ccb[0]) | (~ccb[1]) | (~ccb[2])) + span_has_cas_channel = true; } + /* Unmask CAS RX interrupt if any single channel is in CAS mode */ + /* This interrupt is called RSC in T1 and CASC in E1 */ spin_lock_irqsave(&wc->reglock, flags); - - __t1_framer_set(wc, CCB1, ccb[0]); - __t1_framer_set(wc, CCB2, ccb[1]); - __t1_framer_set(wc, CCB3, ccb[2]); - - reg = __t1_framer_get(wc, IMR0); - if ((~ccb[0]) | (~ccb[1]) | (~ccb[2])) - __t1_framer_set(wc, IMR0, reg & ~0x08); + reg = __t13x_framer_get(wc, IMR0); + if (span_has_cas_channel) + __t13x_framer_set(wc, IMR0, reg & ~0x08); else - __t1_framer_set(wc, IMR0, reg | 0x08); - - /* set RSCC */ - reg = __t1_framer_get(wc, CCR1); - __t1_framer_set(wc, CCR1, reg | 0x80); - + __t13x_framer_set(wc, IMR0, reg | 0x08); spin_unlock_irqrestore(&wc->reglock, flags); } /** - * _t1_free_channels - Free the memory allocated for the channels. + * _t13x_free_channels - Free the memory allocated for the channels. * * Must be called with wc->reglock held. * */ -static void _t1_free_channels(struct t13x *wc) +static void _t13x_free_channels(struct t13x *wc) { int x; for (x = 0; x < ARRAY_SIZE(wc->chans); x++) { @@ -996,7 +939,7 @@ static void free_wc(struct t13x *wc) LIST_HEAD(list); spin_lock_irqsave(&wc->reglock, flags); - _t1_free_channels(wc); + _t13x_free_channels(wc); spin_unlock_irqrestore(&wc->reglock, flags); if (wc->wq) @@ -1011,69 +954,69 @@ static void free_wc(struct t13x *wc) kfree(wc); } -static void t1_serial_setup(struct t13x *wc) +static void t13x_serial_setup(struct t13x *wc) { unsigned long flags; spin_lock_irqsave(&wc->reglock, flags); - __t1_framer_set(wc, 0x85, 0xe0); /* GPC1: Multiplex mode + __t13x_framer_set(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ - __t1_framer_set(wc, 0x08, 0x05); /* IPC: Interrupt push/pull + __t13x_framer_set(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */ /* Global clocks (8.192 Mhz CLK) */ - __t1_framer_set(wc, 0x92, 0x00); - __t1_framer_set(wc, 0x93, 0x18); - __t1_framer_set(wc, 0x94, 0xfb); - __t1_framer_set(wc, 0x95, 0x0b); - __t1_framer_set(wc, 0x96, 0x00); - __t1_framer_set(wc, 0x97, 0x0b); - __t1_framer_set(wc, 0x98, 0xdb); - __t1_framer_set(wc, 0x99, 0xdf); + __t13x_framer_set(wc, 0x92, 0x00); + __t13x_framer_set(wc, 0x93, 0x18); + __t13x_framer_set(wc, 0x94, 0xfb); + __t13x_framer_set(wc, 0x95, 0x0b); + __t13x_framer_set(wc, 0x96, 0x00); + __t13x_framer_set(wc, 0x97, 0x0b); + __t13x_framer_set(wc, 0x98, 0xdb); + __t13x_framer_set(wc, 0x99, 0xdf); /* Configure interrupts */ - __t1_framer_set(wc, 0x46, 0xc0); /* GCR: Interrupt on + __t13x_framer_set(wc, 0x46, 0xc0); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ /* Configure system interface */ - __t1_framer_set(wc, 0x3e, 0xc2); /* SIC1: 8.192 Mhz clock/bus, + __t13x_framer_set(wc, 0x3e, 0xc2); /* SIC1: 8.192 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ - __t1_framer_set(wc, 0x3f, 0x02); /* SIC2: No FFS, no center + __t13x_framer_set(wc, 0x3f, 0x02); /* SIC2: No FFS, no center receive eliastic buffer, phase 1 */ - __t1_framer_set(wc, 0x40, 0x04); /* SIC3: Edges for capture */ - __t1_framer_set(wc, 0x44, 0x30); /* CMR1: RCLK is at 8.192 Mhz + __t13x_framer_set(wc, 0x40, 0x04); /* SIC3: Edges for capture */ + __t13x_framer_set(wc, 0x44, 0x30); /* CMR1: RCLK is at 8.192 Mhz dejittered */ - __t1_framer_set(wc, 0x45, 0x00); /* CMR2: We provide sync and + __t13x_framer_set(wc, 0x45, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ - __t1_framer_set(wc, 0x22, 0x00); /* XC0: Normal operation of + __t13x_framer_set(wc, 0x22, 0x00); /* XC0: Normal operation of Sa-bits */ - __t1_framer_set(wc, 0x23, 0x02); /* XC1: 0 offset */ - __t1_framer_set(wc, 0x24, 0x00); /* RC0: Just shy of 255 */ - __t1_framer_set(wc, 0x25, 0x03); /* RC1: The rest of RC0 */ + __t13x_framer_set(wc, 0x23, 0x02); /* XC1: 0 offset */ + __t13x_framer_set(wc, 0x24, 0x00); /* RC0: Just shy of 255 */ + __t13x_framer_set(wc, 0x25, 0x03); /* RC1: The rest of RC0 */ /* Configure ports */ - __t1_framer_set(wc, 0x80, 0x00); /* PC1: SPYR/SPYX input on + __t13x_framer_set(wc, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ - __t1_framer_set(wc, 0x81, 0x22); /* PC2: RMFB/XSIG output/input + __t13x_framer_set(wc, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ - __t1_framer_set(wc, 0x82, 0x65); /* PC3: Unused stuff */ - __t1_framer_set(wc, 0x83, 0x35); /* PC4: Unused stuff */ - __t1_framer_set(wc, 0x84, 0x31); /* PC5: XMFS active low, SCLKR + __t13x_framer_set(wc, 0x82, 0x65); /* PC3: Unused stuff */ + __t13x_framer_set(wc, 0x83, 0x35); /* PC4: Unused stuff */ + __t13x_framer_set(wc, 0x84, 0x31); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ - __t1_framer_set(wc, 0x86, 0x03); /* PC6: CLK1 is Tx Clock + __t13x_framer_set(wc, 0x86, 0x03); /* PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R */ - __t1_framer_set(wc, 0x3b, 0x00); /* Clear LCR1 */ + __t13x_framer_set(wc, 0x3b, 0x00); /* Clear LCR1 */ spin_unlock_irqrestore(&wc->reglock, flags); } -static void t1_configure_t1(struct t13x *wc, int lineconfig, int txlevel) +static void t13x_configure_t1(struct t13x *wc, int lineconfig, int txlevel) { unsigned int fmr4, fmr2, fmr1, fmr0, lim2; char *framing, *line; @@ -1100,8 +1043,8 @@ static void t1_configure_t1(struct t13x *wc, int lineconfig, int txlevel) spin_lock_irqsave(&wc->reglock, flags); - __t1_framer_set(wc, 0x1d, fmr1); - __t1_framer_set(wc, 0x1e, fmr2); + __t13x_framer_set(wc, 0x1d, fmr1); + __t13x_framer_set(wc, 0x1e, fmr2); /* Configure line interface */ if (lineconfig & DAHDI_CONFIG_AMI) { @@ -1118,73 +1061,73 @@ static void t1_configure_t1(struct t13x *wc, int lineconfig, int txlevel) fmr4 |= 0x2; fmr2 |= 0xc0; } - __t1_framer_set(wc, 0x1c, fmr0); + __t13x_framer_set(wc, 0x1c, fmr0); - __t1_framer_set(wc, 0x20, fmr4); - __t1_framer_set(wc, 0x21, 0x40); /* FMR5: Enable RBS mode */ + __t13x_framer_set(wc, 0x20, fmr4); + __t13x_framer_set(wc, 0x21, 0x40); /* FMR5: Enable RBS mode */ - __t1_framer_set(wc, 0x37, 0xf8); /* LIM1: Clear data in case of + __t13x_framer_set(wc, 0x37, 0xf8); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ - __t1_framer_set(wc, 0x36, 0x08); /* LIM0: Enable auto long haul + __t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ - __t1_framer_set(wc, 0x02, 0x50); /* CMDR: Reset the receiver and + __t13x_framer_set(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ - __t1_framer_set(wc, 0x02, 0x00); /* CMDR: Reset the receiver and + __t13x_framer_set(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ - __t1_framer_set(wc, 0x3a, lim2); /* LIM2: 50% peak amplitude is + __t13x_framer_set(wc, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ - __t1_framer_set(wc, 0x38, 0x0a); /* PCD: LOS after 176 + __t13x_framer_set(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ - __t1_framer_set(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + __t13x_framer_set(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ if (SPANTYPE_DIGITAL_J1 == wc->span.spantype) - __t1_framer_set(wc, 0x24, 0x80); /* J1 overide */ + __t13x_framer_set(wc, 0x24, 0x80); /* J1 overide */ /* Generate pulse mask for T1 */ switch (mytxlevel) { case 3: - __t1_framer_set(wc, 0x26, 0x07); /* XPM0 */ - __t1_framer_set(wc, 0x27, 0x01); /* XPM1 */ - __t1_framer_set(wc, 0x28, 0x00); /* XPM2 */ + __t13x_framer_set(wc, 0x26, 0x07); /* XPM0 */ + __t13x_framer_set(wc, 0x27, 0x01); /* XPM1 */ + __t13x_framer_set(wc, 0x28, 0x00); /* XPM2 */ break; case 2: - __t1_framer_set(wc, 0x26, 0x8c); /* XPM0 */ - __t1_framer_set(wc, 0x27, 0x11); /* XPM1 */ - __t1_framer_set(wc, 0x28, 0x01); /* XPM2 */ + __t13x_framer_set(wc, 0x26, 0x8c); /* XPM0 */ + __t13x_framer_set(wc, 0x27, 0x11); /* XPM1 */ + __t13x_framer_set(wc, 0x28, 0x01); /* XPM2 */ break; case 1: - __t1_framer_set(wc, 0x26, 0x8c); /* XPM0 */ - __t1_framer_set(wc, 0x27, 0x01); /* XPM1 */ - __t1_framer_set(wc, 0x28, 0x00); /* XPM2 */ + __t13x_framer_set(wc, 0x26, 0x8c); /* XPM0 */ + __t13x_framer_set(wc, 0x27, 0x01); /* XPM1 */ + __t13x_framer_set(wc, 0x28, 0x00); /* XPM2 */ break; case 0: default: - __t1_framer_set(wc, 0x26, 0x1a); /* XPM0 */ - __t1_framer_set(wc, 0x27, 0x1f); /* XPM1 */ - __t1_framer_set(wc, 0x28, 0x01); /* XPM2 */ + __t13x_framer_set(wc, 0x26, 0x1a); /* XPM0 */ + __t13x_framer_set(wc, 0x27, 0x1f); /* XPM1 */ + __t13x_framer_set(wc, 0x28, 0x01); /* XPM2 */ break; } - __t1_framer_set(wc, 0x14, 0xff); /* IMR0 */ - __t1_framer_set(wc, 0x15, 0xff); /* IMR1 */ + __t13x_framer_set(wc, 0x14, 0xff); /* IMR0 */ + __t13x_framer_set(wc, 0x15, 0xff); /* IMR1 */ - __t1_framer_set(wc, 0x16, 0x00); /* IMR2: All the alarms */ - __t1_framer_set(wc, 0x17, 0x34); /* IMR3: + __t13x_framer_set(wc, 0x16, 0x00); /* IMR2: All the alarms */ + __t13x_framer_set(wc, 0x17, 0x34); /* IMR3: ES, SEC, LLBSC, rx slips */ - __t1_framer_set(wc, 0x18, 0x3f); /* IMR4: Slips on transmit */ + __t13x_framer_set(wc, 0x18, 0x3f); /* IMR4: Slips on transmit */ spin_unlock_irqrestore(&wc->reglock, flags); dev_info(&wc->dev->dev, "Span configured for %s/%s\n", framing, line); } -static void t1_configure_e1(struct t13x *wc, int lineconfig) +static void t13x_configure_e1(struct t13x *wc, int lineconfig) { unsigned int fmr2, fmr1, fmr0; unsigned int cas = 0; @@ -1206,8 +1149,8 @@ static void t1_configure_e1(struct t13x *wc, int lineconfig) spin_lock_irqsave(&wc->reglock, flags); - __t1_framer_set(wc, 0x1d, fmr1); - __t1_framer_set(wc, 0x1e, fmr2); + __t13x_framer_set(wc, 0x1d, fmr1); + __t13x_framer_set(wc, 0x1e, fmr2); /* Configure line interface */ if (lineconfig & DAHDI_CONFIG_AMI) { @@ -1224,59 +1167,59 @@ static void t1_configure_e1(struct t13x *wc, int lineconfig) framing = "CAS"; cas = 0x40; } - __t1_framer_set(wc, 0x1c, fmr0); + __t13x_framer_set(wc, 0x1c, fmr0); - __t1_framer_set(wc, 0x37, 0xf0); /* LIM1: Clear data in case of + __t13x_framer_set(wc, 0x37, 0xf0); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ - __t1_framer_set(wc, 0x36, 0x08); /* LIM0: Enable auto long haul + __t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ - __t1_framer_set(wc, 0x02, 0x50); /* CMDR: Reset the receiver and + __t13x_framer_set(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ - __t1_framer_set(wc, 0x02, 0x00); /* CMDR: Reset the receiver and + __t13x_framer_set(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ /* Condition receive line interface for E1 after reset */ - __t1_framer_set(wc, 0xbb, 0x17); - __t1_framer_set(wc, 0xbc, 0x55); - __t1_framer_set(wc, 0xbb, 0x97); - __t1_framer_set(wc, 0xbb, 0x11); - __t1_framer_set(wc, 0xbc, 0xaa); - __t1_framer_set(wc, 0xbb, 0x91); - __t1_framer_set(wc, 0xbb, 0x12); - __t1_framer_set(wc, 0xbc, 0x55); - __t1_framer_set(wc, 0xbb, 0x92); - __t1_framer_set(wc, 0xbb, 0x0c); - __t1_framer_set(wc, 0xbb, 0x00); - __t1_framer_set(wc, 0xbb, 0x8c); + __t13x_framer_set(wc, 0xbb, 0x17); + __t13x_framer_set(wc, 0xbc, 0x55); + __t13x_framer_set(wc, 0xbb, 0x97); + __t13x_framer_set(wc, 0xbb, 0x11); + __t13x_framer_set(wc, 0xbc, 0xaa); + __t13x_framer_set(wc, 0xbb, 0x91); + __t13x_framer_set(wc, 0xbb, 0x12); + __t13x_framer_set(wc, 0xbc, 0x55); + __t13x_framer_set(wc, 0xbb, 0x92); + __t13x_framer_set(wc, 0xbb, 0x0c); + __t13x_framer_set(wc, 0xbb, 0x00); + __t13x_framer_set(wc, 0xbb, 0x8c); - __t1_framer_set(wc, 0x3a, 0x20); /* LIM2: 50% peak amplitude is + __t13x_framer_set(wc, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ - __t1_framer_set(wc, 0x38, 0x0a); /* PCD: LOS after 176 + __t13x_framer_set(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ - __t1_framer_set(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + __t13x_framer_set(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ - __t1_framer_set(wc, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ - __t1_framer_set(wc, 0x21, 0x1c|cas); /* XSP: E-bit set when async. + __t13x_framer_set(wc, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ + __t13x_framer_set(wc, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ /* Generate pulse mask for E1 */ - __t1_framer_set(wc, 0x26, 0x74); /* XPM0 */ - __t1_framer_set(wc, 0x27, 0x02); /* XPM1 */ - __t1_framer_set(wc, 0x28, 0x00); /* XPM2 */ + __t13x_framer_set(wc, 0x26, 0x74); /* XPM0 */ + __t13x_framer_set(wc, 0x27, 0x02); /* XPM1 */ + __t13x_framer_set(wc, 0x28, 0x00); /* XPM2 */ - __t1_framer_set(wc, 0x14, 0xff); /* IMR0 */ - __t1_framer_set(wc, 0x15, 0xff); /* IMR1 */ + __t13x_framer_set(wc, 0x14, 0xff); /* IMR0 */ + __t13x_framer_set(wc, 0x15, 0xff); /* IMR1 */ - __t1_framer_set(wc, 0x16, 0x00); /* IMR2: all the + __t13x_framer_set(wc, 0x16, 0x00); /* IMR2: all the alarm stuff! */ - __t1_framer_set(wc, 0x17, 0x04 | imr3extra); /* IMR3: AIS */ - __t1_framer_set(wc, 0x18, 0x3f); /* IMR4: slips on + __t13x_framer_set(wc, 0x17, 0x04 | imr3extra); /* IMR3: AIS */ + __t13x_framer_set(wc, 0x18, 0x3f); /* IMR4: slips on transmit */ spin_unlock_irqrestore(&wc->reglock, flags); @@ -1284,15 +1227,17 @@ static void t1_configure_e1(struct t13x *wc, int lineconfig) "Span configured for %s/%s%s\n", framing, line, crc4); } -static void t1xxp_framer_start(struct t13x *wc) +static void t13x_framer_start(struct t13x *wc) { if (dahdi_is_e1_span(&wc->span)) { - t1_configure_e1(wc, wc->span.lineconfig); + t13x_configure_e1(wc, wc->span.lineconfig); } else { /* is a T1 card */ - t1_configure_t1(wc, wc->span.lineconfig, wc->span.txlevel); - __t1xxp_set_clear(wc); + t13x_configure_t1(wc, wc->span.lineconfig, wc->span.txlevel); } + __t13x_set_clear(wc); + /* Give RCLK a short bit of time to settle */ + udelay(1); set_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags); } @@ -1315,67 +1260,94 @@ static void set_span_devicetype(struct t13x *wc) kfree(olddevicetype); } -static int t1xxp_startup(struct file *file, struct dahdi_span *span) +/** + * te13xp_check_for_interrupts - Return 0 if the card is generating interrupts. + * @wc: The card to check. + * + * If the card is not generating interrupts, this function will also place all + * the spans on the card into red alarm. + * + */ +static int te13xp_check_for_interrupts(struct t13x *wc) +{ + unsigned int starting_framecount = wc->xb.framecount; + unsigned long stop_time = jiffies + HZ*2; + unsigned long flags; + + msleep(20); + spin_lock_irqsave(&wc->reglock, flags); + while (starting_framecount == wc->xb.framecount) { + spin_unlock_irqrestore(&wc->reglock, flags); + if (time_after(jiffies, stop_time)) { + wc->span.alarms = DAHDI_ALARM_RED; + dev_err(&wc->dev->dev, "Interrupts not detected.\n"); + return -EIO; + } + msleep(100); + spin_lock_irqsave(&wc->reglock, flags); + } + spin_unlock_irqrestore(&wc->reglock, flags); + + return 0; +} + +static int t13x_startup(struct file *file, struct dahdi_span *span) { struct t13x *wc = container_of(span, struct t13x, span); unsigned long flags; + int ret; set_span_devicetype(wc); + /* Stop the DMA since the clock source may have changed. */ + wcxb_stop_dma(&wc->xb); + ret = wcxb_wait_for_stop(&wc->xb, 50); + if (ret) { + dev_err(&wc->dev->dev, "Timeout waiting for DMA to stop.\n"); + return ret; + } + /* Reset framer with proper parameters and start */ - t1xxp_framer_start(wc); + t13x_framer_start(wc); + + /* Do we want to SYNC on receive or not. This must always happen after + * the framer is fully reset. */ + wcxb_set_clksrc(&wc->xb, + (span->syncsrc) ? WCXB_CLOCK_RECOVER : WCXB_CLOCK_SELF); + + wcxb_start(&wc->xb); + ret = te13xp_check_for_interrupts(wc); + if (ret) + return ret; + dev_info(&wc->dev->dev, "Calling startup (flags is %lu)\n", span->flags); /* Get this party started */ local_irq_save(flags); - t1_check_alarms(wc); - t1_check_sigbits(wc); + t13x_check_alarms(wc); + t13x_check_sigbits(wc); local_irq_restore(flags); return 0; } -static inline bool is_initialized(struct t13x *wc) -{ - WARN_ON(wc->not_ready < 0); - return (wc->not_ready == 0); -} - -/** - * t1_wait_for_ready - * - * Check if the board has finished any setup and is ready to start processing - * calls. - */ -static int t1_wait_for_ready(struct t13x *wc) -{ - while (!is_initialized(wc)) { - if (fatal_signal_pending(current)) - return -EIO; - msleep_interruptible(250); - } - return 0; -} - -static int t1xxp_chanconfig(struct file *file, +static int t13x_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype) { struct t13x *wc = chan->pvt; - if (file->f_flags & O_NONBLOCK && !is_initialized(wc)) + if (file->f_flags & O_NONBLOCK) return -EAGAIN; - else - t1_wait_for_ready(wc); if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags) && dahdi_is_t1_span(&wc->span)) { - __t1xxp_set_clear(wc); + __t13x_set_clear(wc); } return 0; } -static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits) +static int t13x_rbsbits(struct dahdi_chan *chan, int bits) { u_char m, c; int n, b; @@ -1397,7 +1369,7 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits) c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ wc->txsigs[b] = c; /* output them to the chip */ - __t1_framer_set(wc, 0x71 + b, c); + __t13x_framer_set(wc, 0x71 + b, c); spin_unlock_irqrestore(&wc->reglock, flags); } else if (wc->span.lineconfig & DAHDI_CONFIG_D4) { n = chan->chanpos - 1; @@ -1409,8 +1381,8 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits) c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ wc->txsigs[b] = c; /* output them to the chip */ - __t1_framer_set(wc, 0x70 + b, c); - __t1_framer_set(wc, 0x70 + b + 6, c); + __t13x_framer_set(wc, 0x70 + b, c); + __t13x_framer_set(wc, 0x70 + b + 6, c); spin_unlock_irqrestore(&wc->reglock, flags); } else if (wc->span.lineconfig & DAHDI_CONFIG_ESF) { n = chan->chanpos - 1; @@ -1422,14 +1394,14 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits) c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ wc->txsigs[b] = c; /* output them to the chip */ - __t1_framer_set(wc, 0x70 + b, c); + __t13x_framer_set(wc, 0x70 + b, c); spin_unlock_irqrestore(&wc->reglock, flags); } return 0; } -static void t1_check_sigbits(struct t13x *wc) +static void t13x_check_sigbits(struct t13x *wc) { int a, i, rxs; @@ -1437,7 +1409,7 @@ static void t1_check_sigbits(struct t13x *wc) return; if (dahdi_is_e1_span(&wc->span)) { for (i = 0; i < 15; i++) { - a = t1_framer_get(wc, 0x71 + i); + a = t13x_framer_get(wc, 0x71 + i); if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0xf); @@ -1453,7 +1425,7 @@ static void t1_check_sigbits(struct t13x *wc) } } else if (wc->span.lineconfig & DAHDI_CONFIG_D4) { for (i = 0; i < 24; i += 4) { - a = t1_framer_get(wc, 0x70 + (i>>2)); + a = t13x_framer_get(wc, 0x70 + (i>>2)); if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0x3) << 2; @@ -1479,7 +1451,7 @@ static void t1_check_sigbits(struct t13x *wc) } } else { for (i = 0; i < 24; i += 2) { - a = t1_framer_get(wc, 0x70 + (i>>1)); + a = t13x_framer_get(wc, 0x70 + (i>>1)); if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0xf); @@ -1504,11 +1476,11 @@ struct maint_work_struct { }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -static void t1xxp_maint_work(void *data) +static void t13x_maint_work(void *data) { struct maint_work_struct *w = data; #else -static void t1xxp_maint_work(struct work_struct *work) +static void t13x_maint_work(struct work_struct *work) { struct maint_work_struct *w = container_of(work, struct maint_work_struct, work); @@ -1524,44 +1496,44 @@ static void t1xxp_maint_work(struct work_struct *work) switch (cmd) { case DAHDI_MAINT_NONE: dev_info(&wc->dev->dev, "Clearing all maint modes\n"); - t1xxp_clear_maint(span); + t13x_clear_maint(span); break; case DAHDI_MAINT_LOCALLOOP: dev_info(&wc->dev->dev, "Turning on local loopback\n"); - t1xxp_clear_maint(span); + t13x_clear_maint(span); spin_lock_irqsave(&wc->reglock, flags); - reg = __t1_framer_get(wc, LIM0); + reg = __t13x_framer_get(wc, LIM0); if (reg < 0) { spin_unlock_irqrestore(&wc->reglock, flags); goto cleanup; } - __t1_framer_set(wc, LIM0, reg | LIM0_LL); + __t13x_framer_set(wc, LIM0, reg | LIM0_LL); spin_unlock_irqrestore(&wc->reglock, flags); break; case DAHDI_MAINT_NETWORKLINELOOP: dev_info(&wc->dev->dev, "Turning on network line loopback\n"); - t1xxp_clear_maint(span); + t13x_clear_maint(span); spin_lock_irqsave(&wc->reglock, flags); - reg = __t1_framer_get(wc, LIM1); + reg = __t13x_framer_get(wc, LIM1); if (reg < 0) { spin_unlock_irqrestore(&wc->reglock, flags); goto cleanup; } - __t1_framer_set(wc, LIM1, reg | LIM1_RL); + __t13x_framer_set(wc, LIM1, reg | LIM1_RL); spin_unlock_irqrestore(&wc->reglock, flags); break; case DAHDI_MAINT_NETWORKPAYLOADLOOP: dev_info(&wc->dev->dev, "Turning on network payload loopback\n"); - t1xxp_clear_maint(span); + t13x_clear_maint(span); spin_lock_irqsave(&wc->reglock, flags); - reg = __t1_framer_get(wc, LIM1); + reg = __t13x_framer_get(wc, LIM1); if (reg < 0) { spin_unlock_irqrestore(&wc->reglock, flags); goto cleanup; } - __t1_framer_set(wc, LIM1, reg | (LIM1_RL | LIM1_JATT)); + __t13x_framer_set(wc, LIM1, reg | (LIM1_RL | LIM1_JATT)); spin_unlock_irqrestore(&wc->reglock, flags); break; default: @@ -1573,55 +1545,55 @@ static void t1xxp_maint_work(struct work_struct *work) switch (cmd) { case DAHDI_MAINT_NONE: dev_info(&wc->dev->dev, "Clearing all maint modes\n"); - t1xxp_clear_maint(span); + t13x_clear_maint(span); break; case DAHDI_MAINT_LOCALLOOP: dev_info(&wc->dev->dev, "Turning on local loopback\n"); - t1xxp_clear_maint(span); + t13x_clear_maint(span); spin_lock_irqsave(&wc->reglock, flags); - reg = __t1_framer_get(wc, LIM0); + reg = __t13x_framer_get(wc, LIM0); if (reg < 0) { spin_unlock_irqrestore(&wc->reglock, flags); goto cleanup; } - __t1_framer_set(wc, LIM0, reg | LIM0_LL); + __t13x_framer_set(wc, LIM0, reg | LIM0_LL); spin_unlock_irqrestore(&wc->reglock, flags); break; case DAHDI_MAINT_NETWORKLINELOOP: dev_info(&wc->dev->dev, "Turning on network line loopback\n"); - t1xxp_clear_maint(span); + t13x_clear_maint(span); spin_lock_irqsave(&wc->reglock, flags); - reg = __t1_framer_get(wc, LIM1); + reg = __t13x_framer_get(wc, LIM1); if (reg < 0) { spin_unlock_irqrestore(&wc->reglock, flags); goto cleanup; } - __t1_framer_set(wc, LIM1, reg | LIM1_RL); + __t13x_framer_set(wc, LIM1, reg | LIM1_RL); spin_unlock_irqrestore(&wc->reglock, flags); break; case DAHDI_MAINT_NETWORKPAYLOADLOOP: dev_info(&wc->dev->dev, "Turning on network payload loopback\n"); - t1xxp_clear_maint(span); + t13x_clear_maint(span); spin_lock_irqsave(&wc->reglock, flags); - reg = __t1_framer_get(wc, LIM1); + reg = __t13x_framer_get(wc, LIM1); if (reg < 0) { spin_unlock_irqrestore(&wc->reglock, flags); goto cleanup; } - __t1_framer_set(wc, LIM1, reg | (LIM1_RL | LIM1_JATT)); + __t13x_framer_set(wc, LIM1, reg | (LIM1_RL | LIM1_JATT)); spin_unlock_irqrestore(&wc->reglock, flags); break; case DAHDI_MAINT_LOOPUP: dev_info(&wc->dev->dev, "Transmitting loopup code\n"); - t1xxp_clear_maint(span); - t1_framer_set(wc, 0x21, 0x50); + t13x_clear_maint(span); + t13x_framer_set(wc, 0x21, 0x50); break; case DAHDI_MAINT_LOOPDOWN: dev_info(&wc->dev->dev, "Transmitting loopdown code\n"); - t1xxp_clear_maint(span); - t1_framer_set(wc, 0x21, 0x60); + t13x_clear_maint(span); + t13x_framer_set(wc, 0x21, 0x60); break; default: dev_info(&wc->dev->dev, @@ -1642,7 +1614,7 @@ cleanup: return; } -static int t1xxp_maint(struct dahdi_span *span, int cmd) +static int t13x_maint(struct dahdi_span *span, int cmd) { struct maint_work_struct *work; struct t13x *wc = container_of(span, struct t13x, span); @@ -1692,15 +1664,15 @@ static int t1xxp_maint(struct dahdi_span *span, int cmd) work->cmd = cmd; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - INIT_WORK(&work->work, t1xxp_maint_work, work); + INIT_WORK(&work->work, t13x_maint_work, work); #else - INIT_WORK(&work->work, t1xxp_maint_work); + INIT_WORK(&work->work, t13x_maint_work); #endif queue_work(wc->wq, &work->work); return 0; } -static int t1xxp_clear_maint(struct dahdi_span *span) +static int t13x_clear_maint(struct dahdi_span *span) { struct t13x *wc = container_of(span, struct t13x, span); int reg = 0; @@ -1708,29 +1680,29 @@ static int t1xxp_clear_maint(struct dahdi_span *span) /* Turn off local loop */ spin_lock_irqsave(&wc->reglock, flags); - reg = __t1_framer_get(wc, LIM0); + reg = __t13x_framer_get(wc, LIM0); if (reg < 0) { spin_unlock_irqrestore(&wc->reglock, flags); return -EIO; } - __t1_framer_set(wc, LIM0, reg & ~LIM0_LL); + __t13x_framer_set(wc, LIM0, reg & ~LIM0_LL); /* Turn off remote loop & jitter attenuator */ - reg = __t1_framer_get(wc, LIM1); + reg = __t13x_framer_get(wc, LIM1); if (reg < 0) { spin_unlock_irqrestore(&wc->reglock, flags); return -EIO; } - __t1_framer_set(wc, LIM1, reg & ~(LIM1_RL | LIM1_JATT)); + __t13x_framer_set(wc, LIM1, reg & ~(LIM1_RL | LIM1_JATT)); /* Clear loopup/loopdown signals on the line */ - __t1_framer_set(wc, 0x21, 0x40); + __t13x_framer_set(wc, 0x21, 0x40); spin_unlock_irqrestore(&wc->reglock, flags); return 0; } -static int t1xxp_ioctl(struct dahdi_chan *chan, unsigned int cmd, +static int t13x_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) { struct t4_regs regs; @@ -1741,7 +1713,7 @@ static int t1xxp_ioctl(struct dahdi_chan *chan, unsigned int cmd, case WCT4_GET_REGS: wc = chan->pvt; for (x = 0; x < sizeof(regs.regs) / sizeof(regs.regs[0]); x++) - regs.regs[x] = t1_framer_get(wc, x); + regs.regs[x] = t13x_framer_get(wc, x); if (copy_to_user((void __user *) data, ®s, sizeof(regs))) return -EFAULT; @@ -1752,7 +1724,7 @@ static int t1xxp_ioctl(struct dahdi_chan *chan, unsigned int cmd, return 0; } -static void t1_chan_set_sigcap(struct dahdi_span *span, int x) +static void t13x_chan_set_sigcap(struct dahdi_span *span, int x) { struct t13x *wc = container_of(span, struct t13x, span); struct dahdi_chan *chan = wc->chans[x]; @@ -1788,51 +1760,28 @@ static void t1_chan_set_sigcap(struct dahdi_span *span, int x) } static int -t1xxp_spanconfig(struct file *file, struct dahdi_span *span, +t13x_spanconfig(struct file *file, struct dahdi_span *span, struct dahdi_lineconfig *lc) { struct t13x *wc = container_of(span, struct t13x, span); - int i, reg; + int i; - if (file->f_flags & O_NONBLOCK) { - if (!is_initialized(wc)) - return -EAGAIN; - } else { - t1_wait_for_ready(wc); - } - - reg = ioread32be(wc->membase + TDM_CONTROL); - iowrite32be(reg & ~ENABLE_DMA, wc->membase+TDM_CONTROL); - msleep(200); - - /* Do we want to SYNC on receive or not */ - if (lc->sync) { - reg = ioread32be(wc->membase + TDM_CONTROL); - iowrite32be(reg | TDM_RECOVER_CLOCK, wc->membase+TDM_CONTROL); - span->syncsrc = span->spanno; - } else { - reg = ioread32be(wc->membase + TDM_CONTROL); - iowrite32be(reg & ~TDM_RECOVER_CLOCK, wc->membase+TDM_CONTROL); - span->syncsrc = 0; - } - - reset_dring(wc); - reg = ioread32be(wc->membase + TDM_CONTROL); - iowrite32be(reg | ENABLE_DMA, wc->membase+TDM_CONTROL); + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; /* make sure that sigcaps gets updated if necessary */ for (i = 0; i < wc->span.channels; i++) - t1_chan_set_sigcap(span, i); + t13x_chan_set_sigcap(span, i); /* If already running, apply changes immediately */ if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags)) - return t1xxp_startup(file, span); + return t13x_startup(file, span); return 0; } /** - * t1_software_init - Initialize the board for the given type. + * t13x_software_init - Initialize the board for the given type. * @wc: The board to initialize. * @type: The type of board we are, T1 / E1 * @@ -1840,7 +1789,7 @@ t1xxp_spanconfig(struct file *file, struct dahdi_span *span, * via the dahdi_device before the span is assigned a number. * */ -static int t1_software_init(struct t13x *wc, enum linemode type) +static int t13x_software_init(struct t13x *wc, enum linemode type) { int x; struct dahdi_chan *chans[32] = {NULL,}; @@ -1864,7 +1813,7 @@ static int t1_software_init(struct t13x *wc, enum linemode type) /* Because the interrupt handler is running, we need to atomically * swap the channel arrays. */ spin_lock_irqsave(&wc->reglock, flags); - _t1_free_channels(wc); + _t13x_free_channels(wc); memcpy(wc->chans, chans, sizeof(wc->chans)); memcpy(wc->ec, ec, sizeof(wc->ec)); memset(chans, 0, sizeof(chans)); @@ -1903,11 +1852,11 @@ static int t1_software_init(struct t13x *wc, enum linemode type) dev_info(&wc->dev->dev, "Setting up global serial parameters for %s\n", dahdi_spantype2str(wc->span.spantype)); - t1_serial_setup(wc); + t13x_serial_setup(wc); set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags); for (x = 0; x < wc->span.channels; x++) { sprintf(wc->chans[x]->name, "%s/%d", wc->span.name, x + 1); - t1_chan_set_sigcap(&wc->span, x); + t13x_chan_set_sigcap(&wc->span, x); wc->chans[x]->pvt = wc; wc->chans[x]->chanpos = x + 1; } @@ -1925,7 +1874,7 @@ error_exit: } /** - * t1xx_set_linemode - Change the type of span before assignment. + * t13x_set_linemode - Change the type of span before assignment. * @span: The span to change. * @linemode: Text string for the line mode. * @@ -1934,54 +1883,50 @@ error_exit: * DAHDI). * */ -static int t1xxp_set_linemode(struct dahdi_span *span, enum spantypes linemode) +static int t13x_set_linemode(struct dahdi_span *span, enum spantypes linemode) { int res; struct t13x *wc = container_of(span, struct t13x, span); - u32 saved_ier; /* We may already be set to the requested type. */ - if (span->spantype == linemode) + if (span->spantype == linemode) { + span->alarms = DAHDI_ALARM_NONE; return 0; - - res = t1_wait_for_ready(wc); - if (res) - return res; - - saved_ier = ioread32be(wc->membase + IER); + } mutex_lock(&wc->lock); /* Stop the processing of the channels since we're going to change * them. */ clear_bit(INITIALIZED, &wc->bit_flags); - iowrite32be(0, wc->membase + IER); + disable_irq(wc->xb.pdev->irq); + synchronize_irq(wc->dev->irq); smp_mb__after_clear_bit(); del_timer_sync(&wc->timer); flush_workqueue(wc->wq); - t1_framer_reset(wc); - t1_serial_setup(wc); + t13x_framer_reset(wc); + t13x_serial_setup(wc); switch (linemode) { case SPANTYPE_DIGITAL_T1: dev_info(&wc->dev->dev, "Changing from %s to T1 line mode.\n", dahdi_spantype2str(wc->span.spantype)); - res = t1_software_init(wc, T1); + res = t13x_software_init(wc, T1); break; case SPANTYPE_DIGITAL_E1: dev_info(&wc->dev->dev, "Changing from %s to E1 line mode.\n", dahdi_spantype2str(wc->span.spantype)); - res = t1_software_init(wc, E1); + res = t13x_software_init(wc, E1); break; case SPANTYPE_DIGITAL_J1: dev_info(&wc->dev->dev, "Changing from %s to E1 line mode.\n", dahdi_spantype2str(wc->span.spantype)); - res = t1_software_init(wc, J1); + res = t13x_software_init(wc, J1); default: dev_err(&wc->dev->dev, "Got invalid linemode '%s' from dahdi\n", @@ -1996,17 +1941,15 @@ static int t1xxp_set_linemode(struct dahdi_span *span, enum spantypes linemode) set_bit(INITIALIZED, &wc->bit_flags); mod_timer(&wc->timer, jiffies + HZ/5); } - /* The LATENCY_LOCKED auto-clears the first interrupt - * after it was set. This prevents the driver from bumping up - * the latency after we disabled interrupts while reconfiguring - * the board. */ - set_bit(LATENCY_LOCKED, &wc->bit_flags); - iowrite32be(saved_ier, wc->membase + IER); + wcxb_lock_latency(&wc->xb); + enable_irq(wc->xb.pdev->irq); mutex_unlock(&wc->lock); + msleep(10); + wcxb_unlock_latency(&wc->xb); return res; } -static int t1_hardware_post_init(struct t13x *wc, enum linemode *type) +static int t13x_hardware_post_init(struct t13x *wc, enum linemode *type) { int reg; int x; @@ -2030,9 +1973,8 @@ static int t1_hardware_post_init(struct t13x *wc, enum linemode *type) } /* what version of the FALC are we using? */ - reg = ioread32be(wc->membase); - iowrite32be(reg | FALC_CPU_RESET, wc->membase); - reg = t1_framer_get(wc, 0x4a); + wcxb_gpio_set(&wc->xb, FALC_CPU_RESET); + reg = t13x_framer_get(wc, 0x4a); if (reg < 0) { dev_info(&wc->dev->dev, "Failed to read FALC version (%x)\n", reg); @@ -2042,8 +1984,8 @@ static int t1_hardware_post_init(struct t13x *wc, enum linemode *type) /* make sure reads and writes work */ for (x = 0; x < 256; x++) { - t1_framer_set(wc, 0x14, x); - reg = t1_framer_get(wc, 0x14); + t13x_framer_set(wc, 0x14, x); + reg = t13x_framer_get(wc, 0x14); if (reg < 0) { dev_info(&wc->dev->dev, "Failed register read (%d)\n", reg); @@ -2058,12 +2000,12 @@ static int t1_hardware_post_init(struct t13x *wc, enum linemode *type) } /* Enable all the GPIO outputs. */ - t1_setleds(wc, wc->ledstate); + t13x_setleds(wc, wc->ledstate); return 0; } -static void t1_check_alarms(struct t13x *wc) +static void t13x_check_alarms(struct t13x *wc) { unsigned char c, d; int alarms; @@ -2074,8 +2016,8 @@ static void t1_check_alarms(struct t13x *wc) spin_lock(&wc->reglock); - c = __t1_framer_get(wc, 0x4c); - d = __t1_framer_get(wc, 0x4d); + c = __t13x_framer_get(wc, 0x4c); + d = __t13x_framer_get(wc, 0x4d); /* start with existing span alarms */ alarms = wc->span.alarms; @@ -2087,17 +2029,17 @@ static void t1_check_alarms(struct t13x *wc) * frame */ if (!wc->flags.nmf) { /* LIM0: Force RAI High */ - __t1_framer_set(wc, 0x20, 0x9f | 0x20); + __t13x_framer_set(wc, 0x20, 0x9f | 0x20); wc->flags.nmf = 1; dev_info(&wc->dev->dev, "NMF workaround on!\n"); } - __t1_framer_set(wc, 0x1e, 0xc3); /* Reset to CRC4 mode */ - __t1_framer_set(wc, 0x1c, 0xf2); /* Force Resync */ - __t1_framer_set(wc, 0x1c, 0xf0); /* Force Resync */ + __t13x_framer_set(wc, 0x1e, 0xc3); /* Reset to CRC4 mode */ + __t13x_framer_set(wc, 0x1c, 0xf2); /* Force Resync */ + __t13x_framer_set(wc, 0x1c, 0xf0); /* Force Resync */ } else if (!(c & 0x02)) { if (wc->flags.nmf) { /* LIM0: Clear forced RAI */ - __t1_framer_set(wc, 0x20, 0x9f); + __t13x_framer_set(wc, 0x20, 0x9f); wc->flags.nmf = 0; dev_info(&wc->dev->dev, "NMF workaround off!\n"); @@ -2162,17 +2104,18 @@ static void t1_check_alarms(struct t13x *wc) if (wc->span.alarms != alarms) { wc->span.alarms = alarms; + spin_unlock(&wc->reglock); dahdi_alarm_notify(&wc->span); + } else { + spin_unlock(&wc->reglock); } - - spin_unlock(&wc->reglock); } -static void t1_check_loopcodes(struct t13x *wc) +static void t13x_check_loopcodes(struct t13x *wc) { unsigned char frs1; - frs1 = t1_framer_get(wc, 0x4d); + frs1 = t13x_framer_get(wc, 0x4d); /* Detect loopup code if we're not sending one */ if ((wc->span.maintstat != DAHDI_MAINT_LOOPUP) && (frs1 & 0x08)) { @@ -2195,7 +2138,7 @@ static void t1_check_loopcodes(struct t13x *wc) } } -static void t1_debounce_alarms(struct t13x *wc) +static void t13x_debounce_alarms(struct t13x *wc) { int alarms; unsigned long flags; @@ -2236,7 +2179,9 @@ static void t1_debounce_alarms(struct t13x *wc) if (alarms != wc->span.alarms) { wc->span.alarms = alarms; + spin_unlock_irqrestore(&wc->reglock, flags); dahdi_alarm_notify(&wc->span); + spin_lock_irqsave(&wc->reglock, flags); } /* If receiving alarms (except Yellow), go into Yellow alarm state */ @@ -2246,16 +2191,16 @@ static void t1_debounce_alarms(struct t13x *wc) dev_info(&wc->dev->dev, "Setting yellow alarm\n"); /* We manually do yellow alarm to handle RECOVER * and NOTOPEN, otherwise it's auto anyway */ - fmr4 = __t1_framer_get(wc, 0x20); - __t1_framer_set(wc, 0x20, fmr4 | 0x20); + fmr4 = __t13x_framer_get(wc, 0x20); + __t13x_framer_set(wc, 0x20, fmr4 | 0x20); wc->flags.sendingyellow = 1; } } else { if (wc->flags.sendingyellow) { dev_info(&wc->dev->dev, "Clearing yellow alarm\n"); /* We manually do yellow alarm to handle RECOVER */ - fmr4 = __t1_framer_get(wc, 0x20); - __t1_framer_set(wc, 0x20, fmr4 & ~0x20); + fmr4 = __t13x_framer_get(wc, 0x20); + __t13x_framer_set(wc, 0x20, fmr4 & ~0x20); wc->flags.sendingyellow = 0; } } @@ -2263,7 +2208,7 @@ static void t1_debounce_alarms(struct t13x *wc) spin_unlock_irqrestore(&wc->reglock, flags); } -static void t1_debounce_loopcodes(struct t13x *wc) +static void t13x_debounce_loopcodes(struct t13x *wc) { unsigned long flags; @@ -2271,25 +2216,29 @@ static void t1_debounce_loopcodes(struct t13x *wc) if (wc->loopuptimer && time_after(jiffies, wc->loopuptimer)) { /* Loop-up code debounced */ dev_info(&wc->dev->dev, "Loopup detected, enabling remote loop\n"); - __t1_framer_set(wc, 0x36, 0x08); /* LIM0: Disable + __t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Disable any local loop */ - __t1_framer_set(wc, 0x37, 0xf6); /* LIM1: Enable + __t13x_framer_set(wc, 0x37, 0xf6); /* LIM1: Enable remote loop */ wc->span.maintstat = DAHDI_MAINT_REMOTELOOP; wc->loopuptimer = 0; + spin_unlock_irqrestore(&wc->reglock, flags); dahdi_alarm_notify(&wc->span); + spin_lock_irqsave(&wc->reglock, flags); } if (wc->loopdntimer && time_after(jiffies, wc->loopdntimer)) { /* Loop-down code debounced */ dev_info(&wc->dev->dev, "Loopdown detected, disabling remote loop\n"); - __t1_framer_set(wc, 0x36, 0x08); /* LIM0: Disable + __t13x_framer_set(wc, 0x36, 0x08); /* LIM0: Disable any local loop */ - __t1_framer_set(wc, 0x37, 0xf0); /* LIM1: Disable + __t13x_framer_set(wc, 0x37, 0xf0); /* LIM1: Disable remote loop */ wc->span.maintstat = DAHDI_MAINT_NONE; wc->loopdntimer = 0; + spin_unlock_irqrestore(&wc->reglock, flags); dahdi_alarm_notify(&wc->span); + spin_lock_irqsave(&wc->reglock, flags); } spin_unlock_irqrestore(&wc->reglock, flags); } @@ -2323,157 +2272,51 @@ static void handle_leds(struct t13x *wc) if (led != wc->ledstate) { wc->blinktimer = jiffies + HZ/2; - /* TODO: set ledstate in t1_setleds() */ + /* TODO: set ledstate in t13x_setleds() */ spin_lock_irqsave(&wc->reglock, flags); wc->ledstate = led; spin_unlock_irqrestore(&wc->reglock, flags); - t1_setleds(wc, led); + t13x_setleds(wc, led); } } -/* Called once at startup, the number of tx and rx buffs may grow - * during runtime, but these heaps stay the same */ -static int alloc_dring(struct t13x *wc) +static void te13x_handle_receive(struct wcxb *xb, void *vfp) { - wc->meta_dring = - kzalloc(sizeof(struct t13x_meta_desc) * DRING_SIZE, - GFP_KERNEL); - if (!wc->meta_dring) - return -ENOMEM; - - wc->hw_dring = dma_alloc_coherent(&wc->dev->dev, - sizeof(struct t13x_hw_desc) * DRING_SIZE, - &wc->hw_dring_phys, - GFP_KERNEL); - if (!wc->hw_dring) { - kfree(wc->meta_dring); - return -ENOMEM; - } - - wc->pool = dma_pool_create(wc->name, &wc->dev->dev, - PAGE_SIZE, PAGE_SIZE, 0); - if (!wc->pool) { - kfree(wc->meta_dring); - dma_free_coherent(&wc->dev->dev, - sizeof(struct t13x_hw_desc) * DRING_SIZE, - wc->hw_dring, - wc->hw_dring_phys); - return -ENOMEM; - } - return 0; -} - -static void free_dring(struct t13x *wc) -{ - struct t13x_meta_desc *mdesc; - struct t13x_hw_desc *hdesc; - int i; - - /* Free tx/rx buffs */ - for (i = 0; i < DRING_SIZE; i++) { - mdesc = &wc->meta_dring[i]; - hdesc = &wc->hw_dring[i]; - if (mdesc->tx_buf_virt) { - dma_pool_free(wc->pool, - mdesc->tx_buf_virt, - be32_to_cpu(hdesc->tx_buf)); - dma_pool_free(wc->pool, - mdesc->rx_buf_virt, - be32_to_cpu(hdesc->rx_buf)); - } - } - - dma_pool_destroy(wc->pool); - dma_free_coherent(&wc->dev->dev, - sizeof(struct t13x_hw_desc) * DRING_SIZE, - wc->hw_dring, - wc->hw_dring_phys); - kfree(wc->meta_dring); -} - -/* Sets up all DMA read/write chunks up to size wc->latency */ -static void reset_dring(struct t13x *wc) -{ - int x; - struct t13x_meta_desc *mdesc; - struct t13x_hw_desc *hdesc = NULL; - - wc->dma_head = wc->dma_tail = 0; - - if (unlikely(wc->latency > DRING_SIZE)) { - dev_info(&wc->dev->dev, - "Oops! Tried to increase latency past buffer size.\n"); - wc->latency = DRING_SIZE; - } - - for (x = 0; x < wc->latency; x++) { - dma_addr_t dma_tmp; - - mdesc = &wc->meta_dring[x]; - hdesc = &wc->hw_dring[x]; - - hdesc->status = cpu_to_be32(DESC_DEFAULT_STATUS); - if (!mdesc->tx_buf_virt) { - mdesc->tx_buf_virt = - dma_pool_alloc(wc->pool, GFP_ATOMIC, &dma_tmp); - hdesc->tx_buf = cpu_to_be32(dma_tmp); - mdesc->rx_buf_virt = - dma_pool_alloc(wc->pool, GFP_ATOMIC, &dma_tmp); - hdesc->rx_buf = cpu_to_be32(dma_tmp); - } - hdesc->control = cpu_to_be32(DESC_INT|DESC_OWN); - BUG_ON(!mdesc->tx_buf_virt || !mdesc->rx_buf_virt); - } - - BUG_ON(!hdesc); - /* Set end of ring bit in last descriptor to force hw to loop around */ - hdesc->control |= cpu_to_be32(DESC_EOR); - iowrite32be(wc->hw_dring_phys, wc->membase + TDM_DRING_ADDR); -} - -static void handle_dma(struct t13x *wc) -{ - struct t13x_meta_desc *mdesc; int i, j; + u_char *frame = (u_char *) vfp; + struct t13x *wc = container_of(xb, struct t13x, xb); - while (!(wc->hw_dring[wc->dma_tail].control & cpu_to_be32(DESC_OWN))) { - u_char *frame; - - mdesc = &wc->meta_dring[wc->dma_tail]; - frame = mdesc->rx_buf_virt; - - for (j = 0; j < DAHDI_CHUNKSIZE; j++) - for (i = 0; i < wc->span.channels; i++) - wc->chans[i]->readchunk[j] = - frame[j*DMA_CHAN_SIZE+(1+i*4)]; - - if (0 == vpmsupport) { - for (i = 0; i < wc->span.channels; i++) { - struct dahdi_chan *const c = wc->span.chans[i]; - __dahdi_ec_chunk(c, c->readchunk, c->readchunk, - c->writechunk); - } + for (j = 0; j < DAHDI_CHUNKSIZE; j++) { + for (i = 0; i < wc->span.channels; i++) { + wc->chans[i]->readchunk[j] = + frame[j*DMA_CHAN_SIZE+(1+i*4)]; } + } - _dahdi_receive(&wc->span); + if (0 == vpmsupport) { + for (i = 0; i < wc->span.channels; i++) { + struct dahdi_chan *const c = wc->span.chans[i]; + __dahdi_ec_chunk(c, c->readchunk, c->readchunk, + c->writechunk); + } + } - wc->dma_tail = - (wc->dma_tail == wc->latency-1) ? 0 : wc->dma_tail + 1; + _dahdi_receive(&wc->span); +} - mdesc = &wc->meta_dring[wc->dma_head]; - frame = mdesc->tx_buf_virt; +static void te13x_handle_transmit(struct wcxb *xb, void *vfp) +{ + int i, j; + u_char *frame = (u_char *) vfp; + struct t13x *wc = container_of(xb, struct t13x, xb); - _dahdi_transmit(&wc->span); + _dahdi_transmit(&wc->span); - for (j = 0; j < DAHDI_CHUNKSIZE; j++) - for (i = 0; i < wc->span.channels; i++) - frame[j*DMA_CHAN_SIZE+(1+i*4)] = - wc->chans[i]->writechunk[j]; - - wmb(); - wc->hw_dring[wc->dma_head].control |= cpu_to_be32(DESC_OWN); - wc->dma_head = - (wc->dma_head == wc->latency-1) ? 0 : wc->dma_head + 1; + for (j = 0; j < DAHDI_CHUNKSIZE; j++) { + for (i = 0; i < wc->span.channels; i++) { + frame[j*DMA_CHAN_SIZE+(1+i*4)] = + wc->chans[i]->writechunk[j]; + } } } @@ -2500,9 +2343,9 @@ static void timer_work_func(struct work_struct *work) if (debug) dev_notice(&wc->dev->dev, "Timer work: %d!\n", ++work_count); - t1_debounce_alarms(wc); + t13x_debounce_alarms(wc); if (!dahdi_is_e1_span(&wc->span)) - t1_debounce_loopcodes(wc); + t13x_debounce_loopcodes(wc); handle_leds(wc); if (test_bit(INITIALIZED, &wc->bit_flags)) { if (SPAN_DEBOUNCE || SPAN_ALARMS) @@ -2516,17 +2359,18 @@ static void handle_falc_int(struct t13x *wc) unsigned long flags; static int intcount; bool start_timer; + bool recheck_sigbits = false; intcount++; start_timer = FALSE; spin_lock_irqsave(&wc->reglock, flags); - gis = __t1_framer_get(wc, FRMR_GIS); - isr0 = (gis & FRMR_GIS_ISR0) ? __t1_framer_get(wc, FRMR_ISR0) : 0; - isr1 = (gis & FRMR_GIS_ISR1) ? __t1_framer_get(wc, FRMR_ISR1) : 0; - isr2 = (gis & FRMR_GIS_ISR2) ? __t1_framer_get(wc, FRMR_ISR2) : 0; - isr3 = (gis & FRMR_GIS_ISR3) ? __t1_framer_get(wc, FRMR_ISR3) : 0; - isr4 = (gis & FRMR_GIS_ISR4) ? __t1_framer_get(wc, FRMR_ISR4) : 0; + gis = __t13x_framer_get(wc, FRMR_GIS); + isr0 = (gis & FRMR_GIS_ISR0) ? __t13x_framer_get(wc, FRMR_ISR0) : 0; + isr1 = (gis & FRMR_GIS_ISR1) ? __t13x_framer_get(wc, FRMR_ISR1) : 0; + isr2 = (gis & FRMR_GIS_ISR2) ? __t13x_framer_get(wc, FRMR_ISR2) : 0; + isr3 = (gis & FRMR_GIS_ISR3) ? __t13x_framer_get(wc, FRMR_ISR3) : 0; + isr4 = (gis & FRMR_GIS_ISR4) ? __t13x_framer_get(wc, FRMR_ISR4) : 0; if ((debug) && !(isr3 & ISR3_SEC)) { dev_info(&wc->dev->dev, "gis: %02x, isr0: %02x, isr1: %02x, "\ @@ -2536,12 +2380,15 @@ static void handle_falc_int(struct t13x *wc) /* Collect performance counters once per second */ if (isr3 & ISR3_SEC) { - wc->span.count.fe += __t1_framer_get(wc, FECL_T); - wc->span.count.crc4 += __t1_framer_get(wc, CEC1L_T); - wc->span.count.cv += __t1_framer_get(wc, CVCL_T); - wc->span.count.ebit += __t1_framer_get(wc, EBCL_T); - wc->span.count.be += __t1_framer_get(wc, BECL_T); - wc->span.count.prbs = __t1_framer_get(wc, FRS1_T); + wc->span.count.fe += __t13x_framer_get(wc, FECL_T); + wc->span.count.crc4 += __t13x_framer_get(wc, CEC1L_T); + wc->span.count.cv += __t13x_framer_get(wc, CVCL_T); + wc->span.count.ebit += __t13x_framer_get(wc, EBCL_T); + wc->span.count.be += __t13x_framer_get(wc, BECL_T); + wc->span.count.prbs = __t13x_framer_get(wc, FRS1_T); + + if (DAHDI_RXSIG_INITIAL == wc->span.chans[0]->rxhooksig) + recheck_sigbits = true; } spin_unlock_irqrestore(&wc->reglock, flags); @@ -2549,23 +2396,23 @@ static void handle_falc_int(struct t13x *wc) if (isr3 & ISR3_ES) wc->span.count.errsec += 1; - if (isr0 & 0x08) - t1_check_sigbits(wc); + if ((isr0 & 0x08) || recheck_sigbits) + t13x_check_sigbits(wc); if (dahdi_is_e1_span(&wc->span)) { /* E1 checks */ if ((isr3 & 0x68) || isr2 || (isr1 & 0x7f)) { - t1_check_alarms(wc); + t13x_check_alarms(wc); start_timer = TRUE; } } else { /* T1 checks */ if (isr2) { - t1_check_alarms(wc); + t13x_check_alarms(wc); start_timer = TRUE; } if (isr3 & 0x08) { /* T1 LLBSC */ - t1_check_loopcodes(wc); + t13x_check_loopcodes(wc); start_timer = TRUE; } } @@ -2576,66 +2423,19 @@ static void handle_falc_int(struct t13x *wc) } else wc->span.count.timingslips = 0; - if (start_timer && !timer_pending(&wc->timer)) + if (start_timer && !timer_pending(&wc->timer) && + test_bit(INITIALIZED, &wc->bit_flags)) { mod_timer(&wc->timer, jiffies + HZ/10); + } } -static irqreturn_t _te13xp_isr(int irq, void *dev_id) +static void te13x_handle_interrupt(struct wcxb *xb, u32 pending) { - struct t13x *wc = dev_id; - u32 pending; - int tdmc; - - pending = ioread32be(wc->membase + ISR); - if (!pending) - return IRQ_NONE; - - if (pending & DESC_UNDERRUN) { - /* acknowledge underrun and descriptor interrupts */ - iowrite32be(DESC_UNDERRUN | DESC_COMPLETE, wc->membase + IAR); - - if (!test_bit(LATENCY_LOCKED, &wc->bit_flags)) { - /* bump latency */ - wc->latency++; - dev_info(&wc->dev->dev, - "Underrun detected by hardware. Latency bumped to: %dms\n", - wc->latency); - } else { - clear_bit(LATENCY_LOCKED, &wc->bit_flags); - } - - /* re-setup dma ring */ - reset_dring(wc); - - /* set dma enable bit */ - tdmc = ioread32be(wc->membase + TDM_CONTROL); - iowrite32be(tdmc | ENABLE_DMA, wc->membase + TDM_CONTROL); - - } else if (pending & DESC_COMPLETE) { - /* acknowledge descriptor interrupt */ - iowrite32be(DESC_COMPLETE, wc->membase + IAR); - - wc->framecount++; - handle_dma(wc); - } + struct t13x *wc = container_of(xb, struct t13x, xb); if (pending & FALC_INT) { - iowrite32be(FALC_INT, wc->membase + IAR); handle_falc_int(wc); } - - ioread32be(wc->membase + ISR); - return IRQ_HANDLED; -} - -DAHDI_IRQ_HANDLER(te13xp_isr) -{ - irqreturn_t ret; - unsigned long flags; - local_irq_save(flags); - ret = _te13xp_isr(irq, dev_id); - local_irq_restore(flags); - return ret; } static void te13xp_timer(unsigned long data) @@ -2652,52 +2452,21 @@ static void te13xp_timer(unsigned long data) static inline void create_sysfs_files(struct t13x *wc) { return; } static inline void remove_sysfs_files(struct t13x *wc) { return; } -static const struct dahdi_span_ops t1_span_ops = { +static const struct dahdi_span_ops t13x_span_ops = { .owner = THIS_MODULE, - .spanconfig = t1xxp_spanconfig, - .chanconfig = t1xxp_chanconfig, - .startup = t1xxp_startup, - .rbsbits = t1xxp_rbsbits, - .maint = t1xxp_maint, - .ioctl = t1xxp_ioctl, - .set_spantype = t1xxp_set_linemode, + .spanconfig = t13x_spanconfig, + .chanconfig = t13x_chanconfig, + .startup = t13x_startup, + .rbsbits = t13x_rbsbits, + .maint = t13x_maint, + .ioctl = t13x_ioctl, + .set_spantype = t13x_set_linemode, #ifdef VPM_SUPPORT .echocan_create = t13x_echocan_create, .echocan_name = t13x_echocan_name, #endif /* VPM_SUPPORT */ }; -/** - * te13xp_check_for_interrupts - Return 0 if the card is generating interrupts. - * @wc: The card to check. - * - * If the card is not generating interrupts, this function will also place all - * the spans on the card into red alarm. - * - */ -static int te13xp_check_for_interrupts(struct t13x *wc) -{ - unsigned int starting_framecount = wc->framecount; - unsigned long stop_time = jiffies + HZ*2; - unsigned long flags; - - msleep(20); - spin_lock_irqsave(&wc->reglock, flags); - while (starting_framecount == wc->framecount) { - spin_unlock_irqrestore(&wc->reglock, flags); - if (time_after(jiffies, stop_time)) { - wc->span.alarms = DAHDI_ALARM_RED; - dev_err(&wc->dev->dev, "Interrupts not detected.\n"); - return -EIO; - } - msleep(100); - spin_lock_irqsave(&wc->reglock, flags); - } - spin_unlock_irqrestore(&wc->reglock, flags); - - return 0; -} - #define SPI_BASE 0x200 #define SPISRR (SPI_BASE + 0x40) #define SPICR (SPI_BASE + 0x60) @@ -2706,210 +2475,6 @@ static int te13xp_check_for_interrupts(struct t13x *wc) #define SPIDRR (SPI_BASE + 0x6c) #define SPISSR (SPI_BASE + 0x70) -static void flash_write(struct t13x *wc, int val) -{ - u32 ret; - unsigned long stop = jiffies + HZ/10; - - /* Wait if xmit fifo is full */ - do { - ret = ioread32be(wc->membase + SPISR); - } while ((ret & 0x08) && time_before(jiffies, stop)); - - WARN_ON_ONCE(time_after_eq(jiffies, stop)); - - iowrite32be(val, wc->membase + SPIDTR); -} - -static int flash_read(struct t13x *wc) -{ - u32 ret; - unsigned long stop = jiffies + HZ/10; - - do { - ret = ioread32be(wc->membase + SPISR); - } while ((ret & 0x01) && time_before(jiffies, stop)); - - WARN_ON_ONCE(time_after_eq(jiffies, stop)); - - return ioread32be(wc->membase + SPIDRR); -} - -/* Busy wait until the transmit fifo is flushed - * This was implemented to slow down a race condition with - * a chip select deassertion before flash command transmission - */ -static void clear_xmit_fifo(struct t13x *wc) -{ - u32 ret; - unsigned long stop = jiffies + HZ/100; - - do { - ret = ioread32be(wc->membase + SPISR); - } while (!(ret & 0x4) && time_before(jiffies, stop)); - - WARN_ON_ONCE(time_after_eq(jiffies, stop)); -} - -static void chip_select(struct t13x *wc, int slave) -{ - if (slave) - iowrite32be(0xfffffffe, wc->membase + SPISSR); - else - iowrite32be(0xffffffff, wc->membase + SPISSR); -} - -static void clear_busy(struct t13x *wc) -{ - unsigned long stop = jiffies + HZ/10; - - chip_select(wc, 0); - iowrite32be(0x186, wc->membase + SPICR); - chip_select(wc, 1); - iowrite32be(0x086, wc->membase + SPICR); - - flash_write(wc, 0x05); - clear_xmit_fifo(wc); - flash_read(wc); - - do { - flash_write(wc, 0xff); - } while ((flash_read(wc) & 0x01) && time_before(jiffies, stop)); - - WARN_ON_ONCE(time_after_eq(jiffies, stop)); - - chip_select(wc, 0); -} - -static void write_enable(struct t13x *wc) -{ - iowrite32be(0xa, wc->membase + SPISRR); - msleep(10); - - flash_write(wc, 0x06); - - chip_select(wc, 0); - iowrite32be(0x186, wc->membase + SPICR); - chip_select(wc, 1); - iowrite32be(0x086, wc->membase + SPICR); - - clear_xmit_fifo(wc); - chip_select(wc, 0); - - flash_read(wc); - clear_busy(wc); -} - -static void clear_flash_wip(struct t13x *wc) -{ - /* Hold here until flash chip is done writing */ - iowrite32be(0xe6, wc->membase + SPICR); - chip_select(wc, 1); - flash_write(wc, 0x05); - flash_write(wc, 0xff); - do { } while (!(ioread32be(wc->membase + SPISR) & 0x04)); - flash_read(wc); - - while (flash_read(wc) & 0x1) - flash_write(wc, 0xff); - chip_select(wc, 0); -} - -static void erase_64kb_sector(struct t13x *wc, int offset) -{ - iowrite32be(0xe6, wc->membase + SPICR); - - chip_select(wc, 1); - flash_write(wc, 0xd8); - flash_write(wc, (offset >> 16) & 0xff); - flash_write(wc, 0x00); - flash_write(wc, 0x00); - do { } while (!(ioread32be(wc->membase + SPISR) & 0x04)); - chip_select(wc, 0); - - clear_flash_wip(wc); -} - -static int t13x_get_firmware_version(struct t13x *wc) -{ - u32 version = 0; - - /* Two version registers are read and catenated into one */ - /* Firmware version goes in bits upper byte */ - version = ((ioread32be(wc->membase + 0x400) & 0xffff)<<16); - - /* Microblaze version goes in lower word */ - version += ioread32be(wc->membase + 0x2018); - - return version; -} - -static int t13x_update_firmware(struct t13x *wc, const struct firmware *fw, - const char *filename) -{ - int res; - int offset = 0x200000; - const u8 *data, *end; - int i = 0; - - dev_info(&wc->dev->dev, - "Uploading %s. This can take up to 30 seconds.\n", filename); - - data = &fw->data[sizeof(struct t13x_firm_header)]; - end = &fw->data[fw->size]; - - while (data < end) { - /* Erase sectors */ - clear_busy(wc); - write_enable(wc); - erase_64kb_sector(wc, offset); - data += 0x10000; - offset += 0x10000; - } - - data = &fw->data[sizeof(struct t13x_firm_header)]; - offset = 0x200000; - - while ((data+i) < end) { - /* Page in program as we fill page buffers */ - if (!(offset % 0x0100)) { - write_enable(wc); - chip_select(wc, 0); - iowrite32be(0x186, wc->membase + SPICR); - chip_select(wc, 1); - - flash_write(wc, 0x02); - flash_write(wc, (offset >> 16) & 0xff); - flash_write(wc, (offset >> 8) & 0xff); - flash_write(wc, 0x00); - } - - flash_write(wc, data[i] & 0xff); - iowrite32be(0x086, wc->membase + SPICR); - clear_xmit_fifo(wc); - iowrite32be(0x186, wc->membase + SPICR); - - i++; - offset++; - - if (!((offset) % (0x0100))) - clear_busy(wc); - } - clear_xmit_fifo(wc); - chip_select(wc, 0); - clear_busy(wc); - - /* Reset te13x fpga after loading firmware */ - dev_info(&wc->dev->dev, "Firmware load complete. Reseting device.\n"); - res = pci_save_state(wc->dev); - iowrite32be(0xe00, wc->membase + TDM_CONTROL); - msleep(2000); - pci_restore_state(wc->dev); - iowrite32be(0, wc->membase + 0x04); - - return 0; -} - /** * t13x_read_serial - Returns the serial number of the board. * @wc: The board whos serial number we are reading. @@ -2919,158 +2484,57 @@ static int t13x_update_firmware(struct t13x *wc, const struct firmware *fw, * * Must be called in process context. * + * TODO: Move this up into wcxb.c */ static char *t13x_read_serial(struct t13x *wc) { int i; static const int MAX_SERIAL = 20*5; - unsigned char c; + const unsigned int SERIAL_ADDRESS = 0x1f0000; unsigned char *serial = kzalloc(MAX_SERIAL + 1, GFP_KERNEL); + struct wcxb const *xb = &wc->xb; + struct wcxb_spi_master *flash_spi_master = NULL; + struct wcxb_spi_device *flash_spi_device = NULL; if (!serial) return NULL; - /* Setup read flash byte command */ - iowrite32be(0xa, wc->membase + SPICR); - iowrite32be(0x086, wc->membase + SPICR); - chip_select(wc, 1); - flash_write(wc, 0x03); - flash_write(wc, 0x1f); - flash_write(wc, 0x00); - flash_write(wc, 0x00); - clear_xmit_fifo(wc); - flash_read(wc); - flash_read(wc); - flash_read(wc); - flash_read(wc); + flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev, + xb->membase + SPI_BASE, + false); + if (!flash_spi_master) + return NULL; + + flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0); + if (!flash_spi_device) + goto error_exit; + + wcxb_flash_read(flash_spi_device, SERIAL_ADDRESS, + serial, MAX_SERIAL); for (i = 0; i < MAX_SERIAL; ++i) { - flash_write(wc, 0xff); - c = flash_read(wc); - if (c >= 0x20 && c <= 0x7e) - serial[i] = c; - else + if ((serial[i] < 0x20) || (serial[i] > 0x7e)) { + serial[i] = '\0'; break; - + } } if (!i) { kfree(serial); serial = NULL; - } - - return serial; -} - -static int t13x_check_firmware(struct t13x *wc) -{ - const struct firmware *fw; - char *te133_firmware = "dahdi-fw-te133.bin"; - char *te134_firmware = "dahdi-fw-te134.bin"; - char *filename; - const struct t13x_firm_header *header; - int res = 0; - u32 crc; - u32 version = 0; - const u32 FIRMWARE_VERSION = 0x6f0017; - - version = t13x_get_firmware_version(wc); - - if ((FIRMWARE_VERSION == version) && !force_firmware) { - dev_info(&wc->dev->dev, "Firmware version: %x\n", version); - return 0; - } - - if (force_firmware) { - dev_info(&wc->dev->dev, - "force_firmware module parameter is set. Forcing firmware load, regardless of version\n"); - } else if (is_pcie(wc)) { - dev_info(&wc->dev->dev, - "Firmware %x is running, but we require %x. ERROR: This version of dahdi temporarily disabled field upgradeable firmware. Please upgrade your dahdi revision.\n", - version, FIRMWARE_VERSION); - return -EIO; } else { - dev_info(&wc->dev->dev, - "Firmware %x is running, but we require %x\n", - version, FIRMWARE_VERSION); + /* Limit the size of the buffer to just what is needed to + * actually hold the serial number. */ + unsigned char *new_serial; + new_serial = kasprintf(GFP_KERNEL, "%s", serial); + kfree(serial); + serial = new_serial; } - if (is_pcie(wc)) - filename = te133_firmware; - else - filename = te134_firmware; - - res = request_firmware(&fw, filename, &wc->dev->dev); - if (res) { - dev_info(&wc->dev->dev, - "firmware %s not available from userspace\n", filename); - goto cleanup; - } - - header = (const struct t13x_firm_header *)fw->data; - - /* Check the crc */ - crc = crc32(~0, &fw->data[10], fw->size - 10) ^ ~0; - if (memcmp("DIGIUM", header->header, sizeof(header->header)) || - (le32_to_cpu(header->chksum) != crc)) { - dev_info(&wc->dev->dev, - "%s is invalid. Please reinstall.\n", filename); - goto cleanup; - } - - /* Check the file vs required firmware versions */ - if (le32_to_cpu(header->version) != FIRMWARE_VERSION) { - dev_err(&wc->dev->dev, - "Existing firmware file %s is version %x, but we require %x. Please install the correct firmware file.\n", - filename, le32_to_cpu(header->version), - FIRMWARE_VERSION); - res = -EIO; - goto cleanup; - } - - dev_info(&wc->dev->dev, "Found %s (version: %x) Preparing for flash\n", - filename, header->version); - - res = t13x_update_firmware(wc, fw, filename); - - version = t13x_get_firmware_version(wc); - dev_info(&wc->dev->dev, "Reset into firmware version: %x\n", version); - - if ((FIRMWARE_VERSION != version) && !force_firmware) { - dev_err(&wc->dev->dev, - "Improper firmware version is running\n"); - res = -EIO; - goto cleanup; - } - - if (res) { - dev_info(&wc->dev->dev, "Failed to load firmware %s\n", - filename); - } - -cleanup: - release_firmware(fw); - return res; -} - -static void soft_reset_fpga(struct t13x *wc) -{ - /* digium_gpo */ - iowrite32be(0x0, wc->membase); - - /* xps_intc */ - iowrite32be(0x0, wc->membase + 0x300); - iowrite32be(0x0, wc->membase + 0x308); - iowrite32be(0x0, wc->membase + 0x310); - iowrite32be(0x0, wc->membase + 0x31C); - - /* xps_spi_config_flash */ - iowrite32be(0xA, wc->membase + 0x200); - - /* tdm engine */ - iowrite32be(0x0, wc->membase + 0x2000); - iowrite32be(0x0, wc->membase + 0x2000); - iowrite32be(0x0, wc->membase + 0x2000); +error_exit: + wcxb_spi_device_destroy(flash_spi_device); + wcxb_spi_master_destroy(flash_spi_master); + return serial; } static int __devinit te13xp_init_one(struct pci_dev *pdev, @@ -3083,9 +2547,6 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev, unsigned int index = -1; enum linemode type; - if (pci_enable_device(pdev)) - return -EIO; - for (x = 0; x < ARRAY_SIZE(ifaces); x++) { if (!ifaces[x]) { index = x; @@ -3101,7 +2562,6 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev, wc = kzalloc(sizeof(*wc), GFP_KERNEL); if (!wc) { - pci_disable_device(pdev); return -ENOMEM; } @@ -3118,7 +2578,6 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev, sprintf(wc->span.name, "WCT13x/%d", index); snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", d->name, index); - wc->not_ready = 1; wc->ledstate = -1; spin_lock_init(&wc->reglock); mutex_init(&wc->lock); @@ -3144,30 +2603,35 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev, goto fail_exit; } - wc->membase = pci_iomap(pdev, 0, 0); - if (pci_request_regions(pdev, wc->devtype->name)) - dev_info(&wc->dev->dev, "Unable to request regions\n"); - - /* Reset entire fpga */ - soft_reset_fpga(wc); - - /* Enable writes to fpga status register */ - iowrite32be(0, wc->membase + 0x04); - wc->name = kasprintf(GFP_KERNEL, "wcte13xp%d", index); if (!wc->name) { res = -ENOMEM; goto fail_exit; } - pci_set_master(pdev); pci_set_drvdata(pdev, wc); - /* Check for field updatable firmware */ - res = t13x_check_firmware(wc); + /* Setup wcxb library */ + wc->xb.pdev = pdev; + wc->xb.ops = &xb_ops; + wc->xb.debug = &debug; + res = wcxb_init(&wc->xb, wc->name, 1); if (res) goto fail_exit; + /* Check for field updatable firmware */ + if (is_pcie(wc)) { + res = wcxb_check_firmware(&wc->xb, TE13X_FW_VERSION, + TE133_FW_FILENAME, force_firmware); + if (res) + goto fail_exit; + } else { + res = wcxb_check_firmware(&wc->xb, TE13X_FW_VERSION, + TE134_FW_FILENAME, force_firmware); + if (res) + goto fail_exit; + } + wc->ddev->hardware_id = t13x_read_serial(wc); wc->wq = create_singlethread_workqueue(wc->name); @@ -3179,8 +2643,8 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev, /* Initial buffer latency size, adjustable on load by modparam "latency" */ if (latency > 0 && latency < DRING_SIZE) { - wc->latency = latency; - if (TE13X_DEFAULT_LATENCY != latency) + wcxb_set_minlatency(&wc->xb, latency); + if (WCXB_DEFAULT_LATENCY != latency) dev_info(&wc->dev->dev, "latency manually overridden to %d\n", latency); @@ -3192,22 +2656,15 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev, goto fail_exit; } - if (alloc_dring(wc)) { - res = -ENOMEM; - goto fail_exit; - } - - reset_dring(wc); - create_sysfs_files(wc); - res = t1_hardware_post_init(wc, &type); + res = t13x_hardware_post_init(wc, &type); if (res) goto fail_exit; wc->span.chans = wc->chans; - res = t1_software_init(wc, type); + res = t13x_software_init(wc, type); if (res) goto fail_exit; @@ -3216,7 +2673,7 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev, t13x_vpm_init(wc); #endif - wc->span.ops = &t1_span_ops; + wc->span.ops = &t13x_span_ops; list_add_tail(&wc->span.device_node, &wc->ddev->spans); /* Span is in red alarm by default */ @@ -3228,17 +2685,6 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev, goto fail_exit; } - - pci_enable_msi(pdev); - - if (request_irq(pdev->irq, te13xp_isr, - DAHDI_IRQ_SHARED, "te13xp", wc)) { - dev_notice(&wc->dev->dev, - "Unable to request IRQ %d\n", pdev->irq); - res = -EIO; - goto fail_exit; - } - set_bit(INITIALIZED, &wc->bit_flags); mod_timer(&wc->timer, jiffies + HZ/5); @@ -3250,32 +2696,13 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev, wc->devtype->name); } - /* Enable hardware interrupts */ - iowrite32be(-1, wc->membase + IAR); - /* Don't enable FALC_INT. Just look for the bit when DESC_COMPLETE interrupts. */ - iowrite32be(DESC_UNDERRUN|DESC_COMPLETE, wc->membase + IER); - iowrite32be(MER_ME|MER_HIE, wc->membase + MER); - - /* Enable hardware DMA engine */ - if (vpmsupport == 1) { - iowrite32be(ENABLE_DMA|ENABLE_ECHOCAN_TDM, - wc->membase + TDM_CONTROL); - } else { - iowrite32be(ENABLE_DMA, wc->membase + TDM_CONTROL); - } - - wc->not_ready--; - - te13xp_check_for_interrupts(wc); - return 0; fail_exit: - if (wc->membase) - pci_iounmap(wc->dev, wc->membase); - pci_release_regions(wc->dev); + if (&wc->xb) + wcxb_release(&wc->xb); + free_wc(wc); - pci_disable_device(pdev); return res; } @@ -3289,21 +2716,15 @@ static void __devexit te13xp_remove_one(struct pci_dev *pdev) clear_bit(INITIALIZED, &wc->bit_flags); smp_mb__after_clear_bit(); + /* Quiesce DMA engine interrupts */ + wcxb_stop(&wc->xb); + del_timer_sync(&wc->timer); flush_workqueue(wc->wq); del_timer_sync(&wc->timer); - /* Quiesce DMA engine interrupts */ - iowrite32be(0, wc->membase + TDM_CONTROL); - iowrite32be(0, wc->membase + IER); - iowrite32be(0, wc->membase + MER); - iowrite32be(-1, wc->membase + IAR); - msleep_interruptible(2); - free_irq(pdev->irq, wc); - pci_disable_msi(pdev); - /* Turn off status LED */ - t1_setleds(wc, 0); + t13x_setleds(wc, 0); #ifdef VPM_SUPPORT if (wc->vpm) @@ -3315,14 +2736,8 @@ static void __devexit te13xp_remove_one(struct pci_dev *pdev) remove_sysfs_files(wc); - if (wc->membase) - pci_iounmap(wc->dev, wc->membase); - pci_release_regions(wc->dev); - - free_dring(wc); + wcxb_release(&wc->xb); free_wc(wc); - - pci_disable_device(pdev); } static DEFINE_PCI_DEVICE_TABLE(te13xp_pci_tbl) = { @@ -3339,13 +2754,7 @@ static void te13xp_shutdown(struct pci_dev *pdev) return; /* Quiesce and mask DMA engine interrupts */ - iowrite32be(0, wc->membase + TDM_CONTROL); - iowrite32be(0, wc->membase + IER); - iowrite32be(0, wc->membase + MER); - iowrite32be(-1, wc->membase + IAR); - - /* Flush quiesce commands before exit */ - ioread32be(wc->membase); + wcxb_stop(&wc->xb); } static int te13xp_suspend(struct pci_dev *pdev, pm_message_t state)