diff options
author | Karsten Keil <kkeil@linux-pingi.de> | 2012-05-15 19:51:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-16 15:22:49 -0400 |
commit | 09e79a777a0c9c3de85abc395b5d984bd4bae19d (patch) | |
tree | c0f2dd0e51503cdfde989e0ac90f691dfa4470e1 /drivers/isdn | |
parent | 8bfddfbe2100862fd39b97001d0559ccd4c77f19 (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.c | 68 |
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 | ||
35 | static int AVM_cnt; | 35 | static int AVM_cnt; |
36 | static int debug; | 36 | static 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 | |||
502 | HDLC_irq(struct bchannel *bch, u32 stat) | 511 | HDLC_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 { |