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 | |
parent | 3df40aad1a864af124bd50a1371ef16089ac9af2 (diff) |
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')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_ethtool.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_hw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 108 |
4 files changed, 69 insertions, 48 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 8984c4938881..382891f81e09 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -248,6 +248,7 @@ struct be_tx_stats { u32 tx_spoof_check_err; u32 tx_qinq_err; u32 tx_internal_parity_err; + u32 tx_sge_err; struct u64_stats_sync sync; struct u64_stats_sync sync_compl; }; @@ -944,8 +945,10 @@ static inline bool is_ipv6_ext_hdr(struct sk_buff *skb) #define BE_ERROR_EEH 1 #define BE_ERROR_UE BIT(1) #define BE_ERROR_FW BIT(2) -#define BE_ERROR_HW (BE_ERROR_EEH | BE_ERROR_UE) -#define BE_ERROR_ANY (BE_ERROR_EEH | BE_ERROR_UE | BE_ERROR_FW) +#define BE_ERROR_TX BIT(3) +#define BE_ERROR_HW (BE_ERROR_EEH | BE_ERROR_UE | BE_ERROR_TX) +#define BE_ERROR_ANY (BE_ERROR_EEH | BE_ERROR_UE | BE_ERROR_FW | \ + BE_ERROR_TX) #define BE_CLEAR_ALL 0xFF static inline u8 be_check_error(struct be_adapter *adapter, u32 err_type) diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 7d1819c9e8cc..7f7e206f95f8 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -189,6 +189,7 @@ static const struct be_ethtool_stat et_tx_stats[] = { * packet data. This counter is applicable only for Lancer adapters. */ {DRVSTAT_TX_INFO(tx_internal_parity_err)}, + {DRVSTAT_TX_INFO(tx_sge_err)}, {DRVSTAT_TX_INFO(tx_bytes)}, {DRVSTAT_TX_INFO(tx_pkts)}, {DRVSTAT_TX_INFO(tx_vxlan_offload_pkts)}, diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index c967f45705d9..db5f92fb87e0 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h @@ -261,6 +261,7 @@ struct be_eth_hdr_wrb { #define LANCER_TX_COMP_HSW_DROP_MAC_ERR 0x3 #define LANCER_TX_COMP_HSW_DROP_VLAN_ERR 0x5 #define LANCER_TX_COMP_QINQ_ERR 0x7 +#define LANCER_TX_COMP_SGE_ERR 0x9 #define LANCER_TX_COMP_PARITY_ERR 0xb #define LANCER_TX_COMP_DMA_ERR 0xd 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) { |