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 @@ #define DRV_NAME "ucc_hdlc" #define TDM_PPPOHT_SLIC_MAXIN +#define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S) static struct ucc_tdm_info utdm_primary_info = { .uf_info = { @@ -430,12 +431,25 @@ static netdev_tx_t ucc_hdlc_tx(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +static int hdlc_tx_restart(struct ucc_hdlc_private *priv) +{ + u32 cecr_subblock; + + cecr_subblock = + ucc_fast_get_qe_cr_subblock(priv->ut_info->uf_info.ucc_num); + + qe_issue_cmd(QE_RESTART_TX, cecr_subblock, + QE_CR_PROTOCOL_UNSPECIFIED, 0); + return 0; +} + static int hdlc_tx_done(struct ucc_hdlc_private *priv) { /* Start from the next BD that should be filled */ struct net_device *dev = priv->ndev; struct qe_bd *bd; /* BD pointer */ u16 bd_status; + int tx_restart = 0; bd = priv->dirty_tx; bd_status = ioread16be(&bd->status); @@ -444,6 +458,15 @@ static int hdlc_tx_done(struct ucc_hdlc_private *priv) while ((bd_status & T_R_S) == 0) { struct sk_buff *skb; + if (bd_status & T_UN_S) { /* Underrun */ + dev->stats.tx_fifo_errors++; + tx_restart = 1; + } + if (bd_status & T_CT_S) { /* Carrier lost */ + dev->stats.tx_carrier_errors++; + tx_restart = 1; + } + /* BD contains already transmitted buffer. */ /* Handle the transmitted buffer and release */ /* the BD to be used with the current frame */ @@ -475,6 +498,9 @@ static int hdlc_tx_done(struct ucc_hdlc_private *priv) } priv->dirty_tx = bd; + if (tx_restart) + hdlc_tx_restart(priv); + return 0; } @@ -493,11 +519,22 @@ static int hdlc_rx_done(struct ucc_hdlc_private *priv, int rx_work_limit) /* while there are received buffers and BD is full (~R_E) */ while (!((bd_status & (R_E_S)) || (--rx_work_limit < 0))) { - if (bd_status & R_OV_S) - dev->stats.rx_over_errors++; - if (bd_status & R_CR_S) { - dev->stats.rx_crc_errors++; - dev->stats.rx_dropped++; + if (bd_status & (RX_BD_ERRORS)) { + dev->stats.rx_errors++; + + if (bd_status & R_CD_S) + dev->stats.collisions++; + if (bd_status & R_OV_S) + dev->stats.rx_fifo_errors++; + if (bd_status & R_CR_S) + dev->stats.rx_crc_errors++; + if (bd_status & R_AB_S) + dev->stats.rx_over_errors++; + if (bd_status & R_NO_S) + dev->stats.rx_frame_errors++; + if (bd_status & R_LG_S) + dev->stats.rx_length_errors++; + goto recycle; } bdbuffer = priv->rx_buffer + @@ -546,7 +583,7 @@ static int hdlc_rx_done(struct ucc_hdlc_private *priv, int rx_work_limit) netif_receive_skb(skb); recycle: - iowrite16be(bd_status | R_E_S | R_I_S, &bd->status); + iowrite16be((bd_status & R_W_S) | R_E_S | R_I_S, &bd->status); /* update to point at the next bd */ if (bd_status & R_W_S) { @@ -622,7 +659,7 @@ static irqreturn_t ucc_hdlc_irq_handler(int irq, void *dev_id) /* Errors and other events */ if (ucce >> 16 & UCC_HDLC_UCCE_BSY) - dev->stats.rx_errors++; + dev->stats.rx_missed_errors++; if (ucce >> 16 & UCC_HDLC_UCCE_TXE) dev->stats.tx_errors++; 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 @@ #define R_L_S 0x0800 /* last */ #define R_F_S 0x0400 /* first */ #define R_CM_S 0x0200 /* continuous mode */ +#define R_LG_S 0x0020 /* frame length */ +#define R_NO_S 0x0010 /* nonoctet */ +#define R_AB_S 0x0008 /* abort */ #define R_CR_S 0x0004 /* crc */ -#define R_OV_S 0x0002 /* crc */ +#define R_OV_S 0x0002 /* overrun */ +#define R_CD_S 0x0001 /* carrier detect */ /* transmit BD's status */ #define T_R_S 0x8000 /* ready bit */ @@ -51,6 +55,8 @@ #define T_L_S 0x0800 /* last */ #define T_TC_S 0x0400 /* crc */ #define T_TM_S 0x0200 /* continuous mode */ +#define T_UN_S 0x0002 /* hdlc underrun */ +#define T_CT_S 0x0001 /* hdlc carrier lost */ /* Rx Data buffer must be 4 bytes aligned in most cases */ #define UCC_FAST_RX_ALIGN 4 |