Commit 5a344973 authored by David S. Miller's avatar David S. Miller

Merge branch 'bnxt_en-fixes'

Michael Chan says:

====================
bnxt_en: Bug fixes

This series contains bug fixes for FEC reporting, ethtool self test,
multicast setup, devlink health reporting and live patching, and
a firmware response timeout.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8940e6b6 1278d17a
...@@ -4747,8 +4747,10 @@ static int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, u16 vnic_id) ...@@ -4747,8 +4747,10 @@ static int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, u16 vnic_id)
return rc; return rc;
req->vnic_id = cpu_to_le32(vnic->fw_vnic_id); req->vnic_id = cpu_to_le32(vnic->fw_vnic_id);
req->num_mc_entries = cpu_to_le32(vnic->mc_list_count); if (vnic->rx_mask & CFA_L2_SET_RX_MASK_REQ_MASK_MCAST) {
req->mc_tbl_addr = cpu_to_le64(vnic->mc_list_mapping); req->num_mc_entries = cpu_to_le32(vnic->mc_list_count);
req->mc_tbl_addr = cpu_to_le64(vnic->mc_list_mapping);
}
req->mask = cpu_to_le32(vnic->rx_mask); req->mask = cpu_to_le32(vnic->rx_mask);
return hwrm_req_send_silent(bp, req); return hwrm_req_send_silent(bp, req);
} }
...@@ -7787,6 +7789,19 @@ static int bnxt_map_fw_health_regs(struct bnxt *bp) ...@@ -7787,6 +7789,19 @@ static int bnxt_map_fw_health_regs(struct bnxt *bp)
return 0; return 0;
} }
static void bnxt_remap_fw_health_regs(struct bnxt *bp)
{
if (!bp->fw_health)
return;
if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) {
bp->fw_health->status_reliable = true;
bp->fw_health->resets_reliable = true;
} else {
bnxt_try_map_fw_health_reg(bp);
}
}
static int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp) static int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp)
{ {
struct bnxt_fw_health *fw_health = bp->fw_health; struct bnxt_fw_health *fw_health = bp->fw_health;
...@@ -8639,6 +8654,9 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) ...@@ -8639,6 +8654,9 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
vnic->uc_filter_count = 1; vnic->uc_filter_count = 1;
vnic->rx_mask = 0; vnic->rx_mask = 0;
if (test_bit(BNXT_STATE_HALF_OPEN, &bp->state))
goto skip_rx_mask;
if (bp->dev->flags & IFF_BROADCAST) if (bp->dev->flags & IFF_BROADCAST)
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_BCAST; vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_BCAST;
...@@ -8648,7 +8666,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) ...@@ -8648,7 +8666,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
if (bp->dev->flags & IFF_ALLMULTI) { if (bp->dev->flags & IFF_ALLMULTI) {
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
vnic->mc_list_count = 0; vnic->mc_list_count = 0;
} else { } else if (bp->dev->flags & IFF_MULTICAST) {
u32 mask = 0; u32 mask = 0;
bnxt_mc_list_updated(bp, &mask); bnxt_mc_list_updated(bp, &mask);
...@@ -8659,6 +8677,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) ...@@ -8659,6 +8677,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
if (rc) if (rc)
goto err_out; goto err_out;
skip_rx_mask:
rc = bnxt_hwrm_set_coal(bp); rc = bnxt_hwrm_set_coal(bp);
if (rc) if (rc)
netdev_warn(bp->dev, "HWRM set coalescing failure rc: %x\n", netdev_warn(bp->dev, "HWRM set coalescing failure rc: %x\n",
...@@ -9850,8 +9869,8 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up) ...@@ -9850,8 +9869,8 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
resc_reinit = true; resc_reinit = true;
if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_HOT_FW_RESET_DONE) if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_HOT_FW_RESET_DONE)
fw_reset = true; fw_reset = true;
else if (bp->fw_health && !bp->fw_health->status_reliable) else
bnxt_try_map_fw_health_reg(bp); bnxt_remap_fw_health_regs(bp);
if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) && !fw_reset) { if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) && !fw_reset) {
netdev_err(bp->dev, "RESET_DONE not set during FW reset.\n"); netdev_err(bp->dev, "RESET_DONE not set during FW reset.\n");
...@@ -10330,13 +10349,15 @@ int bnxt_half_open_nic(struct bnxt *bp) ...@@ -10330,13 +10349,15 @@ int bnxt_half_open_nic(struct bnxt *bp)
goto half_open_err; goto half_open_err;
} }
rc = bnxt_alloc_mem(bp, false); rc = bnxt_alloc_mem(bp, true);
if (rc) { if (rc) {
netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc); netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc);
goto half_open_err; goto half_open_err;
} }
rc = bnxt_init_nic(bp, false); set_bit(BNXT_STATE_HALF_OPEN, &bp->state);
rc = bnxt_init_nic(bp, true);
if (rc) { if (rc) {
clear_bit(BNXT_STATE_HALF_OPEN, &bp->state);
netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc); netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc);
goto half_open_err; goto half_open_err;
} }
...@@ -10344,7 +10365,7 @@ int bnxt_half_open_nic(struct bnxt *bp) ...@@ -10344,7 +10365,7 @@ int bnxt_half_open_nic(struct bnxt *bp)
half_open_err: half_open_err:
bnxt_free_skbs(bp); bnxt_free_skbs(bp);
bnxt_free_mem(bp, false); bnxt_free_mem(bp, true);
dev_close(bp->dev); dev_close(bp->dev);
return rc; return rc;
} }
...@@ -10354,9 +10375,10 @@ int bnxt_half_open_nic(struct bnxt *bp) ...@@ -10354,9 +10375,10 @@ int bnxt_half_open_nic(struct bnxt *bp)
*/ */
void bnxt_half_close_nic(struct bnxt *bp) void bnxt_half_close_nic(struct bnxt *bp)
{ {
bnxt_hwrm_resource_free(bp, false, false); bnxt_hwrm_resource_free(bp, false, true);
bnxt_free_skbs(bp); bnxt_free_skbs(bp);
bnxt_free_mem(bp, false); bnxt_free_mem(bp, true);
clear_bit(BNXT_STATE_HALF_OPEN, &bp->state);
} }
void bnxt_reenable_sriov(struct bnxt *bp) void bnxt_reenable_sriov(struct bnxt *bp)
...@@ -10772,7 +10794,7 @@ static void bnxt_set_rx_mode(struct net_device *dev) ...@@ -10772,7 +10794,7 @@ static void bnxt_set_rx_mode(struct net_device *dev)
if (dev->flags & IFF_ALLMULTI) { if (dev->flags & IFF_ALLMULTI) {
mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
vnic->mc_list_count = 0; vnic->mc_list_count = 0;
} else { } else if (dev->flags & IFF_MULTICAST) {
mc_update = bnxt_mc_list_updated(bp, &mask); mc_update = bnxt_mc_list_updated(bp, &mask);
} }
...@@ -10849,9 +10871,10 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp) ...@@ -10849,9 +10871,10 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
!bnxt_promisc_ok(bp)) !bnxt_promisc_ok(bp))
vnic->rx_mask &= ~CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; vnic->rx_mask &= ~CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0); rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0);
if (rc && vnic->mc_list_count) { if (rc && (vnic->rx_mask & CFA_L2_SET_RX_MASK_REQ_MASK_MCAST)) {
netdev_info(bp->dev, "Failed setting MC filters rc: %d, turning on ALL_MCAST mode\n", netdev_info(bp->dev, "Failed setting MC filters rc: %d, turning on ALL_MCAST mode\n",
rc); rc);
vnic->rx_mask &= ~CFA_L2_SET_RX_MASK_REQ_MASK_MCAST;
vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
vnic->mc_list_count = 0; vnic->mc_list_count = 0;
rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0); rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0);
......
...@@ -1921,6 +1921,7 @@ struct bnxt { ...@@ -1921,6 +1921,7 @@ struct bnxt {
#define BNXT_STATE_RECOVER 12 #define BNXT_STATE_RECOVER 12
#define BNXT_STATE_FW_NON_FATAL_COND 13 #define BNXT_STATE_FW_NON_FATAL_COND 13
#define BNXT_STATE_FW_ACTIVATE_RESET 14 #define BNXT_STATE_FW_ACTIVATE_RESET 14
#define BNXT_STATE_HALF_OPEN 15 /* For offline ethtool tests */
#define BNXT_NO_FW_ACCESS(bp) \ #define BNXT_NO_FW_ACCESS(bp) \
(test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) || \ (test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) || \
......
...@@ -367,6 +367,16 @@ bnxt_dl_livepatch_report_err(struct bnxt *bp, struct netlink_ext_ack *extack, ...@@ -367,6 +367,16 @@ bnxt_dl_livepatch_report_err(struct bnxt *bp, struct netlink_ext_ack *extack,
} }
} }
/* Live patch status in NVM */
#define BNXT_LIVEPATCH_NOT_INSTALLED 0
#define BNXT_LIVEPATCH_INSTALLED FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL
#define BNXT_LIVEPATCH_REMOVED FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE
#define BNXT_LIVEPATCH_MASK (FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL | \
FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE)
#define BNXT_LIVEPATCH_ACTIVATED BNXT_LIVEPATCH_MASK
#define BNXT_LIVEPATCH_STATE(flags) ((flags) & BNXT_LIVEPATCH_MASK)
static int static int
bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
{ {
...@@ -374,8 +384,9 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) ...@@ -374,8 +384,9 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
struct hwrm_fw_livepatch_query_input *query_req; struct hwrm_fw_livepatch_query_input *query_req;
struct hwrm_fw_livepatch_output *patch_resp; struct hwrm_fw_livepatch_output *patch_resp;
struct hwrm_fw_livepatch_input *patch_req; struct hwrm_fw_livepatch_input *patch_req;
u16 flags, live_patch_state;
bool activated = false;
u32 installed = 0; u32 installed = 0;
u16 flags;
u8 target; u8 target;
int rc; int rc;
...@@ -394,7 +405,6 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) ...@@ -394,7 +405,6 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
hwrm_req_drop(bp, query_req); hwrm_req_drop(bp, query_req);
return rc; return rc;
} }
patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_ACTIVATE;
patch_req->loadtype = FW_LIVEPATCH_REQ_LOADTYPE_NVM_INSTALL; patch_req->loadtype = FW_LIVEPATCH_REQ_LOADTYPE_NVM_INSTALL;
patch_resp = hwrm_req_hold(bp, patch_req); patch_resp = hwrm_req_hold(bp, patch_req);
...@@ -407,12 +417,20 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) ...@@ -407,12 +417,20 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
} }
flags = le16_to_cpu(query_resp->status_flags); flags = le16_to_cpu(query_resp->status_flags);
if (~flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL) live_patch_state = BNXT_LIVEPATCH_STATE(flags);
if (live_patch_state == BNXT_LIVEPATCH_NOT_INSTALLED)
continue; continue;
if ((flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE) &&
!strncmp(query_resp->active_ver, query_resp->install_ver, if (live_patch_state == BNXT_LIVEPATCH_ACTIVATED) {
sizeof(query_resp->active_ver))) activated = true;
continue; continue;
}
if (live_patch_state == BNXT_LIVEPATCH_INSTALLED)
patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_ACTIVATE;
else if (live_patch_state == BNXT_LIVEPATCH_REMOVED)
patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_DEACTIVATE;
patch_req->fw_target = target; patch_req->fw_target = target;
rc = hwrm_req_send(bp, patch_req); rc = hwrm_req_send(bp, patch_req);
...@@ -424,8 +442,13 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) ...@@ -424,8 +442,13 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
} }
if (!rc && !installed) { if (!rc && !installed) {
NL_SET_ERR_MSG_MOD(extack, "No live patches found"); if (activated) {
rc = -ENOENT; NL_SET_ERR_MSG_MOD(extack, "Live patch already activated");
rc = -EEXIST;
} else {
NL_SET_ERR_MSG_MOD(extack, "No live patches found");
rc = -ENOENT;
}
} }
hwrm_req_drop(bp, query_req); hwrm_req_drop(bp, query_req);
hwrm_req_drop(bp, patch_req); hwrm_req_drop(bp, patch_req);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "bnxt_hsi.h" #include "bnxt_hsi.h"
#include "bnxt.h" #include "bnxt.h"
#include "bnxt_hwrm.h" #include "bnxt_hwrm.h"
#include "bnxt_ulp.h"
#include "bnxt_xdp.h" #include "bnxt_xdp.h"
#include "bnxt_ptp.h" #include "bnxt_ptp.h"
#include "bnxt_ethtool.h" #include "bnxt_ethtool.h"
...@@ -1969,6 +1970,9 @@ static int bnxt_get_fecparam(struct net_device *dev, ...@@ -1969,6 +1970,9 @@ static int bnxt_get_fecparam(struct net_device *dev,
case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS272_IEEE_ACTIVE: case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS272_IEEE_ACTIVE:
fec->active_fec |= ETHTOOL_FEC_LLRS; fec->active_fec |= ETHTOOL_FEC_LLRS;
break; break;
case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_NONE_ACTIVE:
fec->active_fec |= ETHTOOL_FEC_OFF;
break;
} }
return 0; return 0;
} }
...@@ -3454,7 +3458,7 @@ static int bnxt_run_loopback(struct bnxt *bp) ...@@ -3454,7 +3458,7 @@ static int bnxt_run_loopback(struct bnxt *bp)
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
data = skb_put(skb, pkt_size); data = skb_put(skb, pkt_size);
eth_broadcast_addr(data); ether_addr_copy(&data[i], bp->dev->dev_addr);
i += ETH_ALEN; i += ETH_ALEN;
ether_addr_copy(&data[i], bp->dev->dev_addr); ether_addr_copy(&data[i], bp->dev->dev_addr);
i += ETH_ALEN; i += ETH_ALEN;
...@@ -3548,9 +3552,12 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest, ...@@ -3548,9 +3552,12 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
if (!offline) { if (!offline) {
bnxt_run_fw_tests(bp, test_mask, &test_results); bnxt_run_fw_tests(bp, test_mask, &test_results);
} else { } else {
rc = bnxt_close_nic(bp, false, false); bnxt_ulp_stop(bp);
if (rc) rc = bnxt_close_nic(bp, true, false);
if (rc) {
bnxt_ulp_start(bp, rc);
return; return;
}
bnxt_run_fw_tests(bp, test_mask, &test_results); bnxt_run_fw_tests(bp, test_mask, &test_results);
buf[BNXT_MACLPBK_TEST_IDX] = 1; buf[BNXT_MACLPBK_TEST_IDX] = 1;
...@@ -3560,6 +3567,7 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest, ...@@ -3560,6 +3567,7 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
if (rc) { if (rc) {
bnxt_hwrm_mac_loopback(bp, false); bnxt_hwrm_mac_loopback(bp, false);
etest->flags |= ETH_TEST_FL_FAILED; etest->flags |= ETH_TEST_FL_FAILED;
bnxt_ulp_start(bp, rc);
return; return;
} }
if (bnxt_run_loopback(bp)) if (bnxt_run_loopback(bp))
...@@ -3585,7 +3593,8 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest, ...@@ -3585,7 +3593,8 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
} }
bnxt_hwrm_phy_loopback(bp, false, false); bnxt_hwrm_phy_loopback(bp, false, false);
bnxt_half_close_nic(bp); bnxt_half_close_nic(bp);
rc = bnxt_open_nic(bp, false, true); rc = bnxt_open_nic(bp, true, true);
bnxt_ulp_start(bp, rc);
} }
if (rc || bnxt_test_irq(bp)) { if (rc || bnxt_test_irq(bp)) {
buf[BNXT_IRQ_TEST_IDX] = 1; buf[BNXT_IRQ_TEST_IDX] = 1;
......
...@@ -644,17 +644,23 @@ static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx) ...@@ -644,17 +644,23 @@ static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx)
/* Last byte of resp contains valid bit */ /* Last byte of resp contains valid bit */
valid = ((u8 *)ctx->resp) + len - 1; valid = ((u8 *)ctx->resp) + len - 1;
for (j = 0; j < HWRM_VALID_BIT_DELAY_USEC; j++) { for (j = 0; j < HWRM_VALID_BIT_DELAY_USEC; ) {
/* make sure we read from updated DMA memory */ /* make sure we read from updated DMA memory */
dma_rmb(); dma_rmb();
if (*valid) if (*valid)
break; break;
usleep_range(1, 5); if (j < 10) {
udelay(1);
j++;
} else {
usleep_range(20, 30);
j += 20;
}
} }
if (j >= HWRM_VALID_BIT_DELAY_USEC) { if (j >= HWRM_VALID_BIT_DELAY_USEC) {
hwrm_err(bp, ctx, "Error (timeout: %u) msg {0x%x 0x%x} len:%d v:%d\n", hwrm_err(bp, ctx, "Error (timeout: %u) msg {0x%x 0x%x} len:%d v:%d\n",
hwrm_total_timeout(i), req_type, hwrm_total_timeout(i) + j, req_type,
le16_to_cpu(ctx->req->seq_id), len, *valid); le16_to_cpu(ctx->req->seq_id), len, *valid);
goto exit; goto exit;
} }
......
...@@ -90,7 +90,7 @@ static inline unsigned int hwrm_total_timeout(unsigned int n) ...@@ -90,7 +90,7 @@ static inline unsigned int hwrm_total_timeout(unsigned int n)
} }
#define HWRM_VALID_BIT_DELAY_USEC 150 #define HWRM_VALID_BIT_DELAY_USEC 50000
static inline bool bnxt_cfa_hwrm_message(u16 req_type) static inline bool bnxt_cfa_hwrm_message(u16 req_type)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment