diff options
-rw-r--r-- | drivers/net/wan/fsl_ucc_hdlc.c | 51 | ||||
-rw-r--r-- | include/soc/fsl/qe/ucc_fast.h | 8 |
2 files changed, 51 insertions, 8 deletions
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 8523ade16030..4d6409605207 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #define DRV_NAME "ucc_hdlc" | 36 | #define DRV_NAME "ucc_hdlc" |
37 | 37 | ||
38 | #define TDM_PPPOHT_SLIC_MAXIN | 38 | #define TDM_PPPOHT_SLIC_MAXIN |
39 | #define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S) | ||
39 | 40 | ||
40 | static struct ucc_tdm_info utdm_primary_info = { | 41 | static struct ucc_tdm_info utdm_primary_info = { |
41 | .uf_info = { | 42 | .uf_info = { |
@@ -430,12 +431,25 @@ static netdev_tx_t ucc_hdlc_tx(struct sk_buff *skb, struct net_device *dev) | |||
430 | return NETDEV_TX_OK; | 431 | return NETDEV_TX_OK; |
431 | } | 432 | } |
432 | 433 | ||
434 | static int hdlc_tx_restart(struct ucc_hdlc_private *priv) | ||
435 | { | ||
436 | u32 cecr_subblock; | ||
437 | |||
438 | cecr_subblock = | ||
439 | ucc_fast_get_qe_cr_subblock(priv->ut_info->uf_info.ucc_num); | ||
440 | |||
441 | qe_issue_cmd(QE_RESTART_TX, cecr_subblock, | ||
442 | QE_CR_PROTOCOL_UNSPECIFIED, 0); | ||
443 | return 0; | ||
444 | } | ||
445 | |||
433 | static int hdlc_tx_done(struct ucc_hdlc_private *priv) | 446 | static int hdlc_tx_done(struct ucc_hdlc_private *priv) |
434 | { | 447 | { |
435 | /* Start from the next BD that should be filled */ | 448 | /* Start from the next BD that should be filled */ |
436 | struct net_device *dev = priv->ndev; | 449 | struct net_device *dev = priv->ndev; |
437 | struct qe_bd *bd; /* BD pointer */ | 450 | struct qe_bd *bd; /* BD pointer */ |
438 | u16 bd_status; | 451 | u16 bd_status; |
452 | int tx_restart = 0; | ||
439 | 453 | ||
440 | bd = priv->dirty_tx; | 454 | bd = priv->dirty_tx; |
441 | bd_status = ioread16be(&bd->status); | 455 | bd_status = ioread16be(&bd->status); |
@@ -444,6 +458,15 @@ static int hdlc_tx_done(struct ucc_hdlc_private *priv) | |||
444 | while ((bd_status & T_R_S) == 0) { | 458 | while ((bd_status & T_R_S) == 0) { |
445 | struct sk_buff *skb; | 459 | struct sk_buff *skb; |
446 | 460 | ||
461 | if (bd_status & T_UN_S) { /* Underrun */ | ||
462 | dev->stats.tx_fifo_errors++; | ||
463 | tx_restart = 1; | ||
464 | } | ||
465 | if (bd_status & T_CT_S) { /* Carrier lost */ | ||
466 | dev->stats.tx_carrier_errors++; | ||
467 | tx_restart = 1; | ||
468 | } | ||
469 | |||
447 | /* BD contains already transmitted buffer. */ | 470 | /* BD contains already transmitted buffer. */ |
448 | /* Handle the transmitted buffer and release */ | 471 | /* Handle the transmitted buffer and release */ |
449 | /* the BD to be used with the current frame */ | 472 | /* the BD to be used with the current frame */ |
@@ -475,6 +498,9 @@ static int hdlc_tx_done(struct ucc_hdlc_private *priv) | |||
475 | } | 498 | } |
476 | priv->dirty_tx = bd; | 499 | priv->dirty_tx = bd; |
477 | 500 | ||
501 | if (tx_restart) | ||
502 | hdlc_tx_restart(priv); | ||
503 | |||
478 | return 0; | 504 | return 0; |
479 | } | 505 | } |
480 | 506 | ||
@@ -493,11 +519,22 @@ static int hdlc_rx_done(struct ucc_hdlc_private *priv, int rx_work_limit) | |||
493 | 519 | ||
494 | /* while there are received buffers and BD is full (~R_E) */ | 520 | /* while there are received buffers and BD is full (~R_E) */ |
495 | while (!((bd_status & (R_E_S)) || (--rx_work_limit < 0))) { | 521 | while (!((bd_status & (R_E_S)) || (--rx_work_limit < 0))) { |
496 | if (bd_status & R_OV_S) | 522 | if (bd_status & (RX_BD_ERRORS)) { |
497 | dev->stats.rx_over_errors++; | 523 | dev->stats.rx_errors++; |
498 | if (bd_status & R_CR_S) { | 524 | |
499 | dev->stats.rx_crc_errors++; | 525 | if (bd_status & R_CD_S) |
500 | dev->stats.rx_dropped++; | 526 | dev->stats.collisions++; |
527 | if (bd_status & R_OV_S) | ||
528 | dev->stats.rx_fifo_errors++; | ||
529 | if (bd_status & R_CR_S) | ||
530 | dev->stats.rx_crc_errors++; | ||
531 | if (bd_status & R_AB_S) | ||
532 | dev->stats.rx_over_errors++; | ||
533 | if (bd_status & R_NO_S) | ||
534 | dev->stats.rx_frame_errors++; | ||
535 | if (bd_status & R_LG_S) | ||
536 | dev->stats.rx_length_errors++; | ||
537 | |||
501 | goto recycle; | 538 | goto recycle; |
502 | } | 539 | } |
503 | bdbuffer = priv->rx_buffer + | 540 | bdbuffer = priv->rx_buffer + |
@@ -546,7 +583,7 @@ static int hdlc_rx_done(struct ucc_hdlc_private *priv, int rx_work_limit) | |||
546 | netif_receive_skb(skb); | 583 | netif_receive_skb(skb); |
547 | 584 | ||
548 | recycle: | 585 | recycle: |
549 | iowrite16be(bd_status | R_E_S | R_I_S, &bd->status); | 586 | iowrite16be((bd_status & R_W_S) | R_E_S | R_I_S, &bd->status); |
550 | 587 | ||
551 | /* update to point at the next bd */ | 588 | /* update to point at the next bd */ |
552 | if (bd_status & R_W_S) { | 589 | if (bd_status & R_W_S) { |
@@ -622,7 +659,7 @@ static irqreturn_t ucc_hdlc_irq_handler(int irq, void *dev_id) | |||
622 | 659 | ||
623 | /* Errors and other events */ | 660 | /* Errors and other events */ |
624 | if (ucce >> 16 & UCC_HDLC_UCCE_BSY) | 661 | if (ucce >> 16 & UCC_HDLC_UCCE_BSY) |
625 | dev->stats.rx_errors++; | 662 | dev->stats.rx_missed_errors++; |
626 | if (ucce >> 16 & UCC_HDLC_UCCE_TXE) | 663 | if (ucce >> 16 & UCC_HDLC_UCCE_TXE) |
627 | dev->stats.tx_errors++; | 664 | dev->stats.tx_errors++; |
628 | 665 | ||
diff --git a/include/soc/fsl/qe/ucc_fast.h b/include/soc/fsl/qe/ucc_fast.h index 3ee9e7c1a7d7..dcd6b865b590 100644 --- a/include/soc/fsl/qe/ucc_fast.h +++ b/include/soc/fsl/qe/ucc_fast.h | |||
@@ -41,8 +41,12 @@ | |||
41 | #define R_L_S 0x0800 /* last */ | 41 | #define R_L_S 0x0800 /* last */ |
42 | #define R_F_S 0x0400 /* first */ | 42 | #define R_F_S 0x0400 /* first */ |
43 | #define R_CM_S 0x0200 /* continuous mode */ | 43 | #define R_CM_S 0x0200 /* continuous mode */ |
44 | #define R_LG_S 0x0020 /* frame length */ | ||
45 | #define R_NO_S 0x0010 /* nonoctet */ | ||
46 | #define R_AB_S 0x0008 /* abort */ | ||
44 | #define R_CR_S 0x0004 /* crc */ | 47 | #define R_CR_S 0x0004 /* crc */ |
45 | #define R_OV_S 0x0002 /* crc */ | 48 | #define R_OV_S 0x0002 /* overrun */ |
49 | #define R_CD_S 0x0001 /* carrier detect */ | ||
46 | 50 | ||
47 | /* transmit BD's status */ | 51 | /* transmit BD's status */ |
48 | #define T_R_S 0x8000 /* ready bit */ | 52 | #define T_R_S 0x8000 /* ready bit */ |
@@ -51,6 +55,8 @@ | |||
51 | #define T_L_S 0x0800 /* last */ | 55 | #define T_L_S 0x0800 /* last */ |
52 | #define T_TC_S 0x0400 /* crc */ | 56 | #define T_TC_S 0x0400 /* crc */ |
53 | #define T_TM_S 0x0200 /* continuous mode */ | 57 | #define T_TM_S 0x0200 /* continuous mode */ |
58 | #define T_UN_S 0x0002 /* hdlc underrun */ | ||
59 | #define T_CT_S 0x0001 /* hdlc carrier lost */ | ||
54 | 60 | ||
55 | /* Rx Data buffer must be 4 bytes aligned in most cases */ | 61 | /* Rx Data buffer must be 4 bytes aligned in most cases */ |
56 | #define UCC_FAST_RX_ALIGN 4 | 62 | #define UCC_FAST_RX_ALIGN 4 |