Commit 09e79a77 authored by Karsten Keil's avatar Karsten Keil Committed by David S. Miller

mISDN: avmfritz use the bigger fifo of chip version 2

If we detect the latest hardware revision we should use the bigger fifo
to avoid TX underruns and have less interrupts.
TX underruns should be logged as warning.
Signed-off-by: default avatarKarsten Keil <kkeil@linux-pingi.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8bfddfbe
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "ipac.h" #include "ipac.h"
#define AVMFRITZ_REV "2.1" #define AVMFRITZ_REV "2.2"
static int AVM_cnt; static int AVM_cnt;
static int debug; static int debug;
...@@ -69,6 +69,7 @@ enum { ...@@ -69,6 +69,7 @@ enum {
#define HDLC_MODE_TRANS 0x02 #define HDLC_MODE_TRANS 0x02
#define HDLC_MODE_CCR_7 0x04 #define HDLC_MODE_CCR_7 0x04
#define HDLC_MODE_CCR_16 0x08 #define HDLC_MODE_CCR_16 0x08
#define HDLC_FIFO_SIZE_128 0x20
#define HDLC_MODE_TESTLOOP 0x80 #define HDLC_MODE_TESTLOOP 0x80
#define HDLC_INT_XPR 0x80 #define HDLC_INT_XPR 0x80
...@@ -80,13 +81,16 @@ enum { ...@@ -80,13 +81,16 @@ enum {
#define HDLC_STAT_RDO 0x10 #define HDLC_STAT_RDO 0x10
#define HDLC_STAT_CRCVFRRAB 0x0E #define HDLC_STAT_CRCVFRRAB 0x0E
#define HDLC_STAT_CRCVFR 0x06 #define HDLC_STAT_CRCVFR 0x06
#define HDLC_STAT_RML_MASK 0x3f00 #define HDLC_STAT_RML_MASK_V1 0x3f00
#define HDLC_STAT_RML_MASK_V2 0x7f00
#define HDLC_CMD_XRS 0x80 #define HDLC_CMD_XRS 0x80
#define HDLC_CMD_XME 0x01 #define HDLC_CMD_XME 0x01
#define HDLC_CMD_RRS 0x20 #define HDLC_CMD_RRS 0x20
#define HDLC_CMD_XML_MASK 0x3f00 #define HDLC_CMD_XML_MASK 0x3f00
#define HDLC_FIFO_SIZE 32
#define HDLC_FIFO_SIZE_V1 32
#define HDLC_FIFO_SIZE_V2 128
/* Fritz PCI v2.0 */ /* Fritz PCI v2.0 */
...@@ -346,11 +350,14 @@ modehdlc(struct bchannel *bch, int protocol) ...@@ -346,11 +350,14 @@ modehdlc(struct bchannel *bch, int protocol)
{ {
struct fritzcard *fc = bch->hw; struct fritzcard *fc = bch->hw;
struct hdlc_hw *hdlc; struct hdlc_hw *hdlc;
u8 mode;
hdlc = &fc->hdlc[(bch->nr - 1) & 1]; hdlc = &fc->hdlc[(bch->nr - 1) & 1];
pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name, pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name,
'@' + bch->nr, bch->state, protocol, bch->nr); '@' + bch->nr, bch->state, protocol, bch->nr);
hdlc->ctrl.ctrl = 0; hdlc->ctrl.ctrl = 0;
mode = (fc->type == AVM_FRITZ_PCIV2) ? HDLC_FIFO_SIZE_128 : 0;
switch (protocol) { switch (protocol) {
case -1: /* used for init */ case -1: /* used for init */
bch->state = -1; bch->state = -1;
...@@ -358,7 +365,7 @@ modehdlc(struct bchannel *bch, int protocol) ...@@ -358,7 +365,7 @@ modehdlc(struct bchannel *bch, int protocol)
if (bch->state == ISDN_P_NONE) if (bch->state == ISDN_P_NONE)
break; break;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
hdlc->ctrl.sr.mode = HDLC_MODE_TRANS; hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
write_ctrl(bch, 5); write_ctrl(bch, 5);
bch->state = ISDN_P_NONE; bch->state = ISDN_P_NONE;
test_and_clear_bit(FLG_HDLC, &bch->Flags); test_and_clear_bit(FLG_HDLC, &bch->Flags);
...@@ -367,7 +374,7 @@ modehdlc(struct bchannel *bch, int protocol) ...@@ -367,7 +374,7 @@ modehdlc(struct bchannel *bch, int protocol)
case ISDN_P_B_RAW: case ISDN_P_B_RAW:
bch->state = protocol; bch->state = protocol;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
hdlc->ctrl.sr.mode = HDLC_MODE_TRANS; hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
write_ctrl(bch, 5); write_ctrl(bch, 5);
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS; hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
write_ctrl(bch, 1); write_ctrl(bch, 1);
...@@ -377,7 +384,7 @@ modehdlc(struct bchannel *bch, int protocol) ...@@ -377,7 +384,7 @@ modehdlc(struct bchannel *bch, int protocol)
case ISDN_P_B_HDLC: case ISDN_P_B_HDLC:
bch->state = protocol; bch->state = protocol;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG; hdlc->ctrl.sr.mode = mode | HDLC_MODE_ITF_FLG;
write_ctrl(bch, 5); write_ctrl(bch, 5);
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS; hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
write_ctrl(bch, 1); write_ctrl(bch, 1);
...@@ -416,7 +423,7 @@ hdlc_empty_fifo(struct bchannel *bch, int count) ...@@ -416,7 +423,7 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
} }
p = skb_put(bch->rx_skb, count); p = skb_put(bch->rx_skb, count);
ptr = (u32 *)p; ptr = (u32 *)p;
if (AVM_FRITZ_PCIV2 == fc->type) if (fc->type == AVM_FRITZ_PCIV2)
addr = fc->addr + (bch->nr == 2 ? addr = fc->addr + (bch->nr == 2 ?
AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1); AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
else { else {
...@@ -441,7 +448,7 @@ hdlc_fill_fifo(struct bchannel *bch) ...@@ -441,7 +448,7 @@ hdlc_fill_fifo(struct bchannel *bch)
{ {
struct fritzcard *fc = bch->hw; struct fritzcard *fc = bch->hw;
struct hdlc_hw *hdlc; struct hdlc_hw *hdlc;
int count, cnt = 0; int count, fs, cnt = 0;
u8 *p; u8 *p;
u32 *ptr, val, addr; u32 *ptr, val, addr;
...@@ -451,10 +458,12 @@ hdlc_fill_fifo(struct bchannel *bch) ...@@ -451,10 +458,12 @@ hdlc_fill_fifo(struct bchannel *bch)
count = bch->tx_skb->len - bch->tx_idx; count = bch->tx_skb->len - bch->tx_idx;
if (count <= 0) if (count <= 0)
return; return;
fs = (fc->type == AVM_FRITZ_PCIV2) ?
HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1;
p = bch->tx_skb->data + bch->tx_idx; p = bch->tx_skb->data + bch->tx_idx;
hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME; hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
if (count > HDLC_FIFO_SIZE) { if (count > fs) {
count = HDLC_FIFO_SIZE; count = fs;
} else { } else {
if (test_bit(FLG_HDLC, &bch->Flags)) if (test_bit(FLG_HDLC, &bch->Flags))
hdlc->ctrl.sr.cmd |= HDLC_CMD_XME; hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
...@@ -463,8 +472,8 @@ hdlc_fill_fifo(struct bchannel *bch) ...@@ -463,8 +472,8 @@ hdlc_fill_fifo(struct bchannel *bch)
bch->tx_idx, bch->tx_skb->len); bch->tx_idx, bch->tx_skb->len);
ptr = (u32 *)p; ptr = (u32 *)p;
bch->tx_idx += count; bch->tx_idx += count;
hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count); hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count);
if (AVM_FRITZ_PCIV2 == fc->type) { if (fc->type == AVM_FRITZ_PCIV2) {
__write_ctrl_pciv2(fc, hdlc, bch->nr); __write_ctrl_pciv2(fc, hdlc, bch->nr);
addr = fc->addr + (bch->nr == 2 ? addr = fc->addr + (bch->nr == 2 ?
AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1); AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
...@@ -502,13 +511,23 @@ static void ...@@ -502,13 +511,23 @@ static void
HDLC_irq(struct bchannel *bch, u32 stat) HDLC_irq(struct bchannel *bch, u32 stat)
{ {
struct fritzcard *fc = bch->hw; struct fritzcard *fc = bch->hw;
int len; int len, fs;
u32 rmlMask;
struct hdlc_hw *hdlc; struct hdlc_hw *hdlc;
hdlc = &fc->hdlc[(bch->nr - 1) & 1]; hdlc = &fc->hdlc[(bch->nr - 1) & 1];
pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat); pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat);
if (fc->type == AVM_FRITZ_PCIV2) {
rmlMask = HDLC_STAT_RML_MASK_V2;
fs = HDLC_FIFO_SIZE_V2;
} else {
rmlMask = HDLC_STAT_RML_MASK_V1;
fs = HDLC_FIFO_SIZE_V1;
}
if (stat & HDLC_INT_RPR) { if (stat & HDLC_INT_RPR) {
if (stat & HDLC_STAT_RDO) { if (stat & HDLC_STAT_RDO) {
pr_warning("%s: ch%d stat %x RDO\n",
fc->name, bch->nr, stat);
hdlc->ctrl.sr.xml = 0; hdlc->ctrl.sr.xml = 0;
hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS; hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;
write_ctrl(bch, 1); write_ctrl(bch, 1);
...@@ -517,21 +536,21 @@ HDLC_irq(struct bchannel *bch, u32 stat) ...@@ -517,21 +536,21 @@ HDLC_irq(struct bchannel *bch, u32 stat)
if (bch->rx_skb) if (bch->rx_skb)
skb_trim(bch->rx_skb, 0); skb_trim(bch->rx_skb, 0);
} else { } else {
len = (stat & HDLC_STAT_RML_MASK) >> 8; len = (stat & rmlMask) >> 8;
if (!len) if (!len)
len = 32; len = fs;
hdlc_empty_fifo(bch, len); hdlc_empty_fifo(bch, len);
if (!bch->rx_skb) if (!bch->rx_skb)
goto handle_tx; goto handle_tx;
if ((stat & HDLC_STAT_RME) || test_bit(FLG_TRANSPARENT, if (test_bit(FLG_TRANSPARENT, &bch->Flags) ||
&bch->Flags)) { (stat & HDLC_STAT_RME)) {
if (((stat & HDLC_STAT_CRCVFRRAB) == if (((stat & HDLC_STAT_CRCVFRRAB) ==
HDLC_STAT_CRCVFR) || HDLC_STAT_CRCVFR) ||
test_bit(FLG_TRANSPARENT, &bch->Flags)) { test_bit(FLG_TRANSPARENT, &bch->Flags)) {
recv_Bchannel(bch, 0); recv_Bchannel(bch, 0);
} else { } else {
pr_debug("%s: got invalid frame\n", pr_warning("%s: got invalid frame\n",
fc->name); fc->name);
skb_trim(bch->rx_skb, 0); skb_trim(bch->rx_skb, 0);
} }
} }
...@@ -543,13 +562,8 @@ HDLC_irq(struct bchannel *bch, u32 stat) ...@@ -543,13 +562,8 @@ HDLC_irq(struct bchannel *bch, u32 stat)
* restart transmitting the whole frame on HDLC * restart transmitting the whole frame on HDLC
* in transparent mode we send the next data * in transparent mode we send the next data
*/ */
if (bch->tx_skb) pr_warning("%s: ch%d stat %x XDU %s\n", fc->name, bch->nr,
pr_debug("%s: ch%d XDU len(%d) idx(%d) Flags(%lx)\n", stat, bch->tx_skb ? "tx_skb" : "no tx_skb");
fc->name, bch->nr, bch->tx_skb->len,
bch->tx_idx, bch->Flags);
else
pr_debug("%s: ch%d XDU no tx_skb Flags(%lx)\n",
fc->name, bch->nr, bch->Flags);
if (bch->tx_skb && bch->tx_skb->len) { if (bch->tx_skb && bch->tx_skb->len) {
if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
bch->tx_idx = 0; bch->tx_idx = 0;
...@@ -774,7 +788,7 @@ init_card(struct fritzcard *fc) ...@@ -774,7 +788,7 @@ init_card(struct fritzcard *fc)
inithdlc(fc); inithdlc(fc);
enable_hwirq(fc); enable_hwirq(fc);
/* RESET Receiver and Transmitter */ /* RESET Receiver and Transmitter */
if (AVM_FRITZ_PCIV2 == fc->type) { if (fc->type == AVM_FRITZ_PCIV2) {
WriteISAC_V2(fc, ISACX_MASK, 0); WriteISAC_V2(fc, ISACX_MASK, 0);
WriteISAC_V2(fc, ISACX_CMDRD, 0x41); WriteISAC_V2(fc, ISACX_CMDRD, 0x41);
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment