forked from Minki/linux
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: Karsten Keil <kkeil@linux-pingi.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8bfddfbe21
commit
09e79a777a
@ -30,7 +30,7 @@
|
||||
#include "ipac.h"
|
||||
|
||||
|
||||
#define AVMFRITZ_REV "2.1"
|
||||
#define AVMFRITZ_REV "2.2"
|
||||
|
||||
static int AVM_cnt;
|
||||
static int debug;
|
||||
@ -69,6 +69,7 @@ enum {
|
||||
#define HDLC_MODE_TRANS 0x02
|
||||
#define HDLC_MODE_CCR_7 0x04
|
||||
#define HDLC_MODE_CCR_16 0x08
|
||||
#define HDLC_FIFO_SIZE_128 0x20
|
||||
#define HDLC_MODE_TESTLOOP 0x80
|
||||
|
||||
#define HDLC_INT_XPR 0x80
|
||||
@ -80,13 +81,16 @@ enum {
|
||||
#define HDLC_STAT_RDO 0x10
|
||||
#define HDLC_STAT_CRCVFRRAB 0x0E
|
||||
#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_XME 0x01
|
||||
#define HDLC_CMD_RRS 0x20
|
||||
#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 */
|
||||
|
||||
@ -346,11 +350,14 @@ modehdlc(struct bchannel *bch, int protocol)
|
||||
{
|
||||
struct fritzcard *fc = bch->hw;
|
||||
struct hdlc_hw *hdlc;
|
||||
u8 mode;
|
||||
|
||||
hdlc = &fc->hdlc[(bch->nr - 1) & 1];
|
||||
pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name,
|
||||
'@' + bch->nr, bch->state, protocol, bch->nr);
|
||||
hdlc->ctrl.ctrl = 0;
|
||||
mode = (fc->type == AVM_FRITZ_PCIV2) ? HDLC_FIFO_SIZE_128 : 0;
|
||||
|
||||
switch (protocol) {
|
||||
case -1: /* used for init */
|
||||
bch->state = -1;
|
||||
@ -358,7 +365,7 @@ modehdlc(struct bchannel *bch, int protocol)
|
||||
if (bch->state == ISDN_P_NONE)
|
||||
break;
|
||||
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);
|
||||
bch->state = ISDN_P_NONE;
|
||||
test_and_clear_bit(FLG_HDLC, &bch->Flags);
|
||||
@ -367,7 +374,7 @@ modehdlc(struct bchannel *bch, int protocol)
|
||||
case ISDN_P_B_RAW:
|
||||
bch->state = protocol;
|
||||
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);
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
|
||||
write_ctrl(bch, 1);
|
||||
@ -377,7 +384,7 @@ modehdlc(struct bchannel *bch, int protocol)
|
||||
case ISDN_P_B_HDLC:
|
||||
bch->state = protocol;
|
||||
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);
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
|
||||
write_ctrl(bch, 1);
|
||||
@ -416,7 +423,7 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
|
||||
}
|
||||
p = skb_put(bch->rx_skb, count);
|
||||
ptr = (u32 *)p;
|
||||
if (AVM_FRITZ_PCIV2 == fc->type)
|
||||
if (fc->type == AVM_FRITZ_PCIV2)
|
||||
addr = fc->addr + (bch->nr == 2 ?
|
||||
AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
|
||||
else {
|
||||
@ -441,7 +448,7 @@ hdlc_fill_fifo(struct bchannel *bch)
|
||||
{
|
||||
struct fritzcard *fc = bch->hw;
|
||||
struct hdlc_hw *hdlc;
|
||||
int count, cnt = 0;
|
||||
int count, fs, cnt = 0;
|
||||
u8 *p;
|
||||
u32 *ptr, val, addr;
|
||||
|
||||
@ -451,10 +458,12 @@ hdlc_fill_fifo(struct bchannel *bch)
|
||||
count = bch->tx_skb->len - bch->tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
fs = (fc->type == AVM_FRITZ_PCIV2) ?
|
||||
HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1;
|
||||
p = bch->tx_skb->data + bch->tx_idx;
|
||||
hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
|
||||
if (count > HDLC_FIFO_SIZE) {
|
||||
count = HDLC_FIFO_SIZE;
|
||||
if (count > fs) {
|
||||
count = fs;
|
||||
} else {
|
||||
if (test_bit(FLG_HDLC, &bch->Flags))
|
||||
hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
|
||||
@ -463,8 +472,8 @@ hdlc_fill_fifo(struct bchannel *bch)
|
||||
bch->tx_idx, bch->tx_skb->len);
|
||||
ptr = (u32 *)p;
|
||||
bch->tx_idx += count;
|
||||
hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count);
|
||||
if (AVM_FRITZ_PCIV2 == fc->type) {
|
||||
hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count);
|
||||
if (fc->type == AVM_FRITZ_PCIV2) {
|
||||
__write_ctrl_pciv2(fc, hdlc, bch->nr);
|
||||
addr = fc->addr + (bch->nr == 2 ?
|
||||
AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
|
||||
@ -502,13 +511,23 @@ static void
|
||||
HDLC_irq(struct bchannel *bch, u32 stat)
|
||||
{
|
||||
struct fritzcard *fc = bch->hw;
|
||||
int len;
|
||||
int len, fs;
|
||||
u32 rmlMask;
|
||||
struct hdlc_hw *hdlc;
|
||||
|
||||
hdlc = &fc->hdlc[(bch->nr - 1) & 1];
|
||||
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_STAT_RDO) {
|
||||
pr_warning("%s: ch%d stat %x RDO\n",
|
||||
fc->name, bch->nr, stat);
|
||||
hdlc->ctrl.sr.xml = 0;
|
||||
hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;
|
||||
write_ctrl(bch, 1);
|
||||
@ -517,20 +536,20 @@ HDLC_irq(struct bchannel *bch, u32 stat)
|
||||
if (bch->rx_skb)
|
||||
skb_trim(bch->rx_skb, 0);
|
||||
} else {
|
||||
len = (stat & HDLC_STAT_RML_MASK) >> 8;
|
||||
len = (stat & rmlMask) >> 8;
|
||||
if (!len)
|
||||
len = 32;
|
||||
len = fs;
|
||||
hdlc_empty_fifo(bch, len);
|
||||
if (!bch->rx_skb)
|
||||
goto handle_tx;
|
||||
if ((stat & HDLC_STAT_RME) || test_bit(FLG_TRANSPARENT,
|
||||
&bch->Flags)) {
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags) ||
|
||||
(stat & HDLC_STAT_RME)) {
|
||||
if (((stat & HDLC_STAT_CRCVFRRAB) ==
|
||||
HDLC_STAT_CRCVFR) ||
|
||||
test_bit(FLG_TRANSPARENT, &bch->Flags)) {
|
||||
recv_Bchannel(bch, 0);
|
||||
} else {
|
||||
pr_debug("%s: got invalid frame\n",
|
||||
pr_warning("%s: got invalid frame\n",
|
||||
fc->name);
|
||||
skb_trim(bch->rx_skb, 0);
|
||||
}
|
||||
@ -543,13 +562,8 @@ handle_tx:
|
||||
* restart transmitting the whole frame on HDLC
|
||||
* in transparent mode we send the next data
|
||||
*/
|
||||
if (bch->tx_skb)
|
||||
pr_debug("%s: ch%d XDU len(%d) idx(%d) Flags(%lx)\n",
|
||||
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);
|
||||
pr_warning("%s: ch%d stat %x XDU %s\n", fc->name, bch->nr,
|
||||
stat, bch->tx_skb ? "tx_skb" : "no tx_skb");
|
||||
if (bch->tx_skb && bch->tx_skb->len) {
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
bch->tx_idx = 0;
|
||||
@ -774,7 +788,7 @@ init_card(struct fritzcard *fc)
|
||||
inithdlc(fc);
|
||||
enable_hwirq(fc);
|
||||
/* 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_CMDRD, 0x41);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user