| From e7a1a60f7338b929e244ff5242fd868dee3f321a Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sun, 18 Jul 2021 15:36:31 -0400 |
| Subject: bnxt_en: Check abort error state in bnxt_half_open_nic() |
| |
| From: Somnath Kotur <somnath.kotur@broadcom.com> |
| |
| [ Upstream commit 11a39259ff79b74bc99f8b7c44075a2d6d5e7ab1 ] |
| |
| bnxt_half_open_nic() is called during during ethtool self test and is |
| protected by rtnl_lock. Firmware reset can be happening at the same |
| time. Only critical portions of the entire firmware reset sequence |
| are protected by the rtnl_lock. It is possible that bnxt_half_open_nic() |
| can be called when the firmware reset sequence is aborting. In that |
| case, bnxt_half_open_nic() needs to check if the ABORT_ERR flag is set |
| and abort if it is. The ethtool self test will fail but the NIC will be |
| brought to a consistent IF_DOWN state. |
| |
| Without this patch, if bnxt_half_open_nic() were to continue in this |
| error state, it may crash like this: |
| |
| bnxt_en 0000:82:00.1 enp130s0f1np1: FW reset in progress during close, FW reset will be aborted |
| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 |
| ... |
| Process ethtool (pid: 333327, stack limit = 0x0000000046476577) |
| Call trace: |
| bnxt_alloc_mem+0x444/0xef0 [bnxt_en] |
| bnxt_half_open_nic+0x24/0xb8 [bnxt_en] |
| bnxt_self_test+0x2dc/0x390 [bnxt_en] |
| ethtool_self_test+0xe0/0x1f8 |
| dev_ethtool+0x1744/0x22d0 |
| dev_ioctl+0x190/0x3e0 |
| sock_ioctl+0x238/0x480 |
| do_vfs_ioctl+0xc4/0x758 |
| ksys_ioctl+0x84/0xb8 |
| __arm64_sys_ioctl+0x28/0x38 |
| el0_svc_handler+0xb0/0x180 |
| el0_svc+0x8/0xc |
| |
| Fixes: a1301f08c5ac ("bnxt_en: Check abort error state in bnxt_open_nic().") |
| Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com> |
| Signed-off-by: Michael Chan <michael.chan@broadcom.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 ++++++ |
| 1 file changed, 6 insertions(+) |
| |
| diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c |
| index be36dee65f90..3c3aa9467310 100644 |
| --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c |
| +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c |
| @@ -10104,6 +10104,12 @@ int bnxt_half_open_nic(struct bnxt *bp) |
| { |
| int rc = 0; |
| |
| + if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state)) { |
| + netdev_err(bp->dev, "A previous firmware reset has not completed, aborting half open\n"); |
| + rc = -ENODEV; |
| + goto half_open_err; |
| + } |
| + |
| rc = bnxt_alloc_mem(bp, false); |
| if (rc) { |
| netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc); |
| -- |
| 2.30.2 |
| |