diff options
author | Suresh Reddy <suresh.reddy@broadcom.com> | 2018-02-06 08:52:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-02-06 11:48:33 -0500 |
commit | ffc39620102dfe62711fadb9a297b66aee816013 (patch) | |
tree | bd4cd5c737e6671c4a9d6df536eec18a3dee7171 /drivers/net/ethernet/emulex/benet/be_main.c | |
parent | 3df40aad1a864af124bd50a1371ef16089ac9af2 (diff) | |
download | linux-ffc39620102dfe62711fadb9a297b66aee816013.tar.bz2 |
be2net: Handle transmit completion errors in Lancer
If the driver receives a TX CQE with status as 0x1 or 0x9 or 0xb,
the completion indexes should not be used. The driver must stop
consuming CQEs from this TXQ/CQ. The TXQ from this point on-wards
to be in a bad state. Driver should destroy and recreate the TXQ.
0x1: LANCER_TX_COMP_LSO_ERR
0x9 LANCER_TX_COMP_SGE_ERR
0xb: LANCER_TX_COMP_PARITY_ERR
Reset the adapter if driver sees this error in TX completion. Also
adding sge error counter in ethtool stats.
Signed-off-by: Suresh Reddy <suresh.reddy@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 108 |
1 files changed, 62 insertions, 46 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 286d591c574e..5774fb6f8aa0 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -2583,7 +2583,48 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp, u32 frags_needed) } } -static struct be_tx_compl_info *be_tx_compl_get(struct be_tx_obj *txo) +static inline void be_update_tx_err(struct be_tx_obj *txo, u8 status) +{ + switch (status) { + case BE_TX_COMP_HDR_PARSE_ERR: + tx_stats(txo)->tx_hdr_parse_err++; + break; + case BE_TX_COMP_NDMA_ERR: + tx_stats(txo)->tx_dma_err++; + break; + case BE_TX_COMP_ACL_ERR: + tx_stats(txo)->tx_spoof_check_err++; + break; + } +} + +static inline void lancer_update_tx_err(struct be_tx_obj *txo, u8 status) +{ + switch (status) { + case LANCER_TX_COMP_LSO_ERR: + tx_stats(txo)->tx_tso_err++; + break; + case LANCER_TX_COMP_HSW_DROP_MAC_ERR: + case LANCER_TX_COMP_HSW_DROP_VLAN_ERR: + tx_stats(txo)->tx_spoof_check_err++; + break; + case LANCER_TX_COMP_QINQ_ERR: + tx_stats(txo)->tx_qinq_err++; + break; + case LANCER_TX_COMP_PARITY_ERR: + tx_stats(txo)->tx_internal_parity_err++; + break; + case LANCER_TX_COMP_DMA_ERR: + tx_stats(txo)->tx_dma_err++; + break; + case LANCER_TX_COMP_SGE_ERR: + tx_stats(txo)->tx_sge_err++; + break; + } +} + +static struct be_tx_compl_info *be_tx_compl_get(struct be_adapter *adapter, + struct be_tx_obj *txo) { struct be_queue_info *tx_cq = &txo->cq; struct be_tx_compl_info *txcp = &txo->txcp; @@ -2599,6 +2640,24 @@ static struct be_tx_compl_info *be_tx_compl_get(struct be_tx_obj *txo) txcp->status = GET_TX_COMPL_BITS(status, compl); txcp->end_index = GET_TX_COMPL_BITS(wrb_index, compl); + if (txcp->status) { + if (lancer_chip(adapter)) { + lancer_update_tx_err(txo, txcp->status); + /* Reset the adapter incase of TSO, + * SGE or Parity error + */ + if (txcp->status == LANCER_TX_COMP_LSO_ERR || + txcp->status == LANCER_TX_COMP_PARITY_ERR || + txcp->status == LANCER_TX_COMP_SGE_ERR) + be_set_error(adapter, BE_ERROR_TX); + } else { + be_update_tx_err(txo, txcp->status); + } + } + + if (be_check_error(adapter, BE_ERROR_TX)) + return NULL; + compl->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] = 0; queue_tail_inc(tx_cq); return txcp; @@ -2741,7 +2800,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter) cmpl = 0; num_wrbs = 0; txq = &txo->q; - while ((txcp = be_tx_compl_get(txo))) { + while ((txcp = be_tx_compl_get(adapter, txo))) { num_wrbs += be_tx_compl_process(adapter, txo, txcp->end_index); @@ -3120,42 +3179,6 @@ loop_continue: return work_done; } -static inline void be_update_tx_err(struct be_tx_obj *txo, u8 status) -{ - switch (status) { - case BE_TX_COMP_HDR_PARSE_ERR: - tx_stats(txo)->tx_hdr_parse_err++; - break; - case BE_TX_COMP_NDMA_ERR: - tx_stats(txo)->tx_dma_err++; - break; - case BE_TX_COMP_ACL_ERR: - tx_stats(txo)->tx_spoof_check_err++; - break; - } -} - -static inline void lancer_update_tx_err(struct be_tx_obj *txo, u8 status) -{ - switch (status) { - case LANCER_TX_COMP_LSO_ERR: - tx_stats(txo)->tx_tso_err++; - break; - case LANCER_TX_COMP_HSW_DROP_MAC_ERR: - case LANCER_TX_COMP_HSW_DROP_VLAN_ERR: - tx_stats(txo)->tx_spoof_check_err++; - break; - case LANCER_TX_COMP_QINQ_ERR: - tx_stats(txo)->tx_qinq_err++; - break; - case LANCER_TX_COMP_PARITY_ERR: - tx_stats(txo)->tx_internal_parity_err++; - break; - case LANCER_TX_COMP_DMA_ERR: - tx_stats(txo)->tx_dma_err++; - break; - } -} static void be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, int idx) @@ -3163,16 +3186,9 @@ static void be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, int num_wrbs = 0, work_done = 0; struct be_tx_compl_info *txcp; - while ((txcp = be_tx_compl_get(txo))) { + while ((txcp = be_tx_compl_get(adapter, txo))) { num_wrbs += be_tx_compl_process(adapter, txo, txcp->end_index); work_done++; - - if (txcp->status) { - if (lancer_chip(adapter)) - lancer_update_tx_err(txo, txcp->status); - else - be_update_tx_err(txo, txcp->status); - } } if (work_done) { |