aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.c51
-rw-r--r--include/soc/fsl/qe/ucc_fast.h8
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
40static struct ucc_tdm_info utdm_primary_info = { 41static 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
434static 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
433static int hdlc_tx_done(struct ucc_hdlc_private *priv) 446static 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
548recycle: 585recycle:
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