aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorKarsten Keil <kkeil@linux-pingi.de>2012-05-15 19:51:03 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-16 15:22:49 -0400
commit09e79a777a0c9c3de85abc395b5d984bd4bae19d (patch)
treec0f2dd0e51503cdfde989e0ac90f691dfa4470e1 /drivers/isdn
parent8bfddfbe2100862fd39b97001d0559ccd4c77f19 (diff)
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>
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/hardware/mISDN/avmfritz.c68
1 files changed, 41 insertions, 27 deletions
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 788b9a7c4df5..cc782646886c 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -30,7 +30,7 @@
30#include "ipac.h" 30#include "ipac.h"
31 31
32 32
33#define AVMFRITZ_REV "2.1" 33#define AVMFRITZ_REV "2.2"
34 34
35static int AVM_cnt; 35static int AVM_cnt;
36static int debug; 36static int debug;
@@ -69,6 +69,7 @@ enum {
69#define HDLC_MODE_TRANS 0x02 69#define HDLC_MODE_TRANS 0x02
70#define HDLC_MODE_CCR_7 0x04 70#define HDLC_MODE_CCR_7 0x04
71#define HDLC_MODE_CCR_16 0x08 71#define HDLC_MODE_CCR_16 0x08
72#define HDLC_FIFO_SIZE_128 0x20
72#define HDLC_MODE_TESTLOOP 0x80 73#define HDLC_MODE_TESTLOOP 0x80
73 74
74#define HDLC_INT_XPR 0x80 75#define HDLC_INT_XPR 0x80
@@ -80,13 +81,16 @@ enum {
80#define HDLC_STAT_RDO 0x10 81#define HDLC_STAT_RDO 0x10
81#define HDLC_STAT_CRCVFRRAB 0x0E 82#define HDLC_STAT_CRCVFRRAB 0x0E
82#define HDLC_STAT_CRCVFR 0x06 83#define HDLC_STAT_CRCVFR 0x06
83#define HDLC_STAT_RML_MASK 0x3f00 84#define HDLC_STAT_RML_MASK_V1 0x3f00
85#define HDLC_STAT_RML_MASK_V2 0x7f00
84 86
85#define HDLC_CMD_XRS 0x80 87#define HDLC_CMD_XRS 0x80
86#define HDLC_CMD_XME 0x01 88#define HDLC_CMD_XME 0x01
87#define HDLC_CMD_RRS 0x20 89#define HDLC_CMD_RRS 0x20
88#define HDLC_CMD_XML_MASK 0x3f00 90#define HDLC_CMD_XML_MASK 0x3f00
89#define HDLC_FIFO_SIZE 32 91
92#define HDLC_FIFO_SIZE_V1 32
93#define HDLC_FIFO_SIZE_V2 128
90 94
91/* Fritz PCI v2.0 */ 95/* Fritz PCI v2.0 */
92 96
@@ -346,11 +350,14 @@ modehdlc(struct bchannel *bch, int protocol)
346{ 350{
347 struct fritzcard *fc = bch->hw; 351 struct fritzcard *fc = bch->hw;
348 struct hdlc_hw *hdlc; 352 struct hdlc_hw *hdlc;
353 u8 mode;
349 354
350 hdlc = &fc->hdlc[(bch->nr - 1) & 1]; 355 hdlc = &fc->hdlc[(bch->nr - 1) & 1];
351 pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name, 356 pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name,
352 '@' + bch->nr, bch->state, protocol, bch->nr); 357 '@' + bch->nr, bch->state, protocol, bch->nr);
353 hdlc->ctrl.ctrl = 0; 358 hdlc->ctrl.ctrl = 0;
359 mode = (fc->type == AVM_FRITZ_PCIV2) ? HDLC_FIFO_SIZE_128 : 0;
360
354 switch (protocol) { 361 switch (protocol) {
355 case -1: /* used for init */ 362 case -1: /* used for init */
356 bch->state = -1; 363 bch->state = -1;
@@ -358,7 +365,7 @@ modehdlc(struct bchannel *bch, int protocol)
358 if (bch->state == ISDN_P_NONE) 365 if (bch->state == ISDN_P_NONE)
359 break; 366 break;
360 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; 367 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
361 hdlc->ctrl.sr.mode = HDLC_MODE_TRANS; 368 hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
362 write_ctrl(bch, 5); 369 write_ctrl(bch, 5);
363 bch->state = ISDN_P_NONE; 370 bch->state = ISDN_P_NONE;
364 test_and_clear_bit(FLG_HDLC, &bch->Flags); 371 test_and_clear_bit(FLG_HDLC, &bch->Flags);
@@ -367,7 +374,7 @@ modehdlc(struct bchannel *bch, int protocol)
367 case ISDN_P_B_RAW: 374 case ISDN_P_B_RAW:
368 bch->state = protocol; 375 bch->state = protocol;
369 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; 376 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
370 hdlc->ctrl.sr.mode = HDLC_MODE_TRANS; 377 hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
371 write_ctrl(bch, 5); 378 write_ctrl(bch, 5);
372 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS; 379 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
373 write_ctrl(bch, 1); 380 write_ctrl(bch, 1);
@@ -377,7 +384,7 @@ modehdlc(struct bchannel *bch, int protocol)
377 case ISDN_P_B_HDLC: 384 case ISDN_P_B_HDLC:
378 bch->state = protocol; 385 bch->state = protocol;
379 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; 386 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
380 hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG; 387 hdlc->ctrl.sr.mode = mode | HDLC_MODE_ITF_FLG;
381 write_ctrl(bch, 5); 388 write_ctrl(bch, 5);
382 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS; 389 hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
383 write_ctrl(bch, 1); 390 write_ctrl(bch, 1);
@@ -416,7 +423,7 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
416 } 423 }
417 p = skb_put(bch->rx_skb, count); 424 p = skb_put(bch->rx_skb, count);
418 ptr = (u32 *)p; 425 ptr = (u32 *)p;
419 if (AVM_FRITZ_PCIV2 == fc->type) 426 if (fc->type == AVM_FRITZ_PCIV2)
420 addr = fc->addr + (bch->nr == 2 ? 427 addr = fc->addr + (bch->nr == 2 ?
421 AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1); 428 AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
422 else { 429 else {
@@ -441,7 +448,7 @@ hdlc_fill_fifo(struct bchannel *bch)
441{ 448{
442 struct fritzcard *fc = bch->hw; 449 struct fritzcard *fc = bch->hw;
443 struct hdlc_hw *hdlc; 450 struct hdlc_hw *hdlc;
444 int count, cnt = 0; 451 int count, fs, cnt = 0;
445 u8 *p; 452 u8 *p;
446 u32 *ptr, val, addr; 453 u32 *ptr, val, addr;
447 454
@@ -451,10 +458,12 @@ hdlc_fill_fifo(struct bchannel *bch)
451 count = bch->tx_skb->len - bch->tx_idx; 458 count = bch->tx_skb->len - bch->tx_idx;
452 if (count <= 0) 459 if (count <= 0)
453 return; 460 return;
461 fs = (fc->type == AVM_FRITZ_PCIV2) ?
462 HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1;
454 p = bch->tx_skb->data + bch->tx_idx; 463 p = bch->tx_skb->data + bch->tx_idx;
455 hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME; 464 hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
456 if (count > HDLC_FIFO_SIZE) { 465 if (count > fs) {
457 count = HDLC_FIFO_SIZE; 466 count = fs;
458 } else { 467 } else {
459 if (test_bit(FLG_HDLC, &bch->Flags)) 468 if (test_bit(FLG_HDLC, &bch->Flags))
460 hdlc->ctrl.sr.cmd |= HDLC_CMD_XME; 469 hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
@@ -463,8 +472,8 @@ hdlc_fill_fifo(struct bchannel *bch)
463 bch->tx_idx, bch->tx_skb->len); 472 bch->tx_idx, bch->tx_skb->len);
464 ptr = (u32 *)p; 473 ptr = (u32 *)p;
465 bch->tx_idx += count; 474 bch->tx_idx += count;
466 hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count); 475 hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count);
467 if (AVM_FRITZ_PCIV2 == fc->type) { 476 if (fc->type == AVM_FRITZ_PCIV2) {
468 __write_ctrl_pciv2(fc, hdlc, bch->nr); 477 __write_ctrl_pciv2(fc, hdlc, bch->nr);
469 addr = fc->addr + (bch->nr == 2 ? 478 addr = fc->addr + (bch->nr == 2 ?
470 AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1); 479 AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
@@ -502,13 +511,23 @@ static void
502HDLC_irq(struct bchannel *bch, u32 stat) 511HDLC_irq(struct bchannel *bch, u32 stat)
503{ 512{
504 struct fritzcard *fc = bch->hw; 513 struct fritzcard *fc = bch->hw;
505 int len; 514 int len, fs;
515 u32 rmlMask;
506 struct hdlc_hw *hdlc; 516 struct hdlc_hw *hdlc;
507 517
508 hdlc = &fc->hdlc[(bch->nr - 1) & 1]; 518 hdlc = &fc->hdlc[(bch->nr - 1) & 1];
509 pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat); 519 pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat);
520 if (fc->type == AVM_FRITZ_PCIV2) {
521 rmlMask = HDLC_STAT_RML_MASK_V2;
522 fs = HDLC_FIFO_SIZE_V2;
523 } else {
524 rmlMask = HDLC_STAT_RML_MASK_V1;
525 fs = HDLC_FIFO_SIZE_V1;
526 }
510 if (stat & HDLC_INT_RPR) { 527 if (stat & HDLC_INT_RPR) {
511 if (stat & HDLC_STAT_RDO) { 528 if (stat & HDLC_STAT_RDO) {
529 pr_warning("%s: ch%d stat %x RDO\n",
530 fc->name, bch->nr, stat);
512 hdlc->ctrl.sr.xml = 0; 531 hdlc->ctrl.sr.xml = 0;
513 hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS; 532 hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;
514 write_ctrl(bch, 1); 533 write_ctrl(bch, 1);
@@ -517,21 +536,21 @@ HDLC_irq(struct bchannel *bch, u32 stat)
517 if (bch->rx_skb) 536 if (bch->rx_skb)
518 skb_trim(bch->rx_skb, 0); 537 skb_trim(bch->rx_skb, 0);
519 } else { 538 } else {
520 len = (stat & HDLC_STAT_RML_MASK) >> 8; 539 len = (stat & rmlMask) >> 8;
521 if (!len) 540 if (!len)
522 len = 32; 541 len = fs;
523 hdlc_empty_fifo(bch, len); 542 hdlc_empty_fifo(bch, len);
524 if (!bch->rx_skb) 543 if (!bch->rx_skb)
525 goto handle_tx; 544 goto handle_tx;
526 if ((stat & HDLC_STAT_RME) || test_bit(FLG_TRANSPARENT, 545 if (test_bit(FLG_TRANSPARENT, &bch->Flags) ||
527 &bch->Flags)) { 546 (stat & HDLC_STAT_RME)) {
528 if (((stat & HDLC_STAT_CRCVFRRAB) == 547 if (((stat & HDLC_STAT_CRCVFRRAB) ==
529 HDLC_STAT_CRCVFR) || 548 HDLC_STAT_CRCVFR) ||
530 test_bit(FLG_TRANSPARENT, &bch->Flags)) { 549 test_bit(FLG_TRANSPARENT, &bch->Flags)) {
531 recv_Bchannel(bch, 0); 550 recv_Bchannel(bch, 0);
532 } else { 551 } else {
533 pr_debug("%s: got invalid frame\n", 552 pr_warning("%s: got invalid frame\n",
534 fc->name); 553 fc->name);
535 skb_trim(bch->rx_skb, 0); 554 skb_trim(bch->rx_skb, 0);
536 } 555 }
537 } 556 }
@@ -543,13 +562,8 @@ handle_tx:
543 * restart transmitting the whole frame on HDLC 562 * restart transmitting the whole frame on HDLC
544 * in transparent mode we send the next data 563 * in transparent mode we send the next data
545 */ 564 */
546 if (bch->tx_skb) 565 pr_warning("%s: ch%d stat %x XDU %s\n", fc->name, bch->nr,
547 pr_debug("%s: ch%d XDU len(%d) idx(%d) Flags(%lx)\n", 566 stat, bch->tx_skb ? "tx_skb" : "no tx_skb");
548 fc->name, bch->nr, bch->tx_skb->len,
549 bch->tx_idx, bch->Flags);
550 else
551 pr_debug("%s: ch%d XDU no tx_skb Flags(%lx)\n",
552 fc->name, bch->nr, bch->Flags);
553 if (bch->tx_skb && bch->tx_skb->len) { 567 if (bch->tx_skb && bch->tx_skb->len) {
554 if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) 568 if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
555 bch->tx_idx = 0; 569 bch->tx_idx = 0;
@@ -774,7 +788,7 @@ init_card(struct fritzcard *fc)
774 inithdlc(fc); 788 inithdlc(fc);
775 enable_hwirq(fc); 789 enable_hwirq(fc);
776 /* RESET Receiver and Transmitter */ 790 /* RESET Receiver and Transmitter */
777 if (AVM_FRITZ_PCIV2 == fc->type) { 791 if (fc->type == AVM_FRITZ_PCIV2) {
778 WriteISAC_V2(fc, ISACX_MASK, 0); 792 WriteISAC_V2(fc, ISACX_MASK, 0);
779 WriteISAC_V2(fc, ISACX_CMDRD, 0x41); 793 WriteISAC_V2(fc, ISACX_CMDRD, 0x41);
780 } else { 794 } else {