From patchwork Tue Sep 8 22:48:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shannon Nelson X-Patchwork-Id: 1360224 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=pensando.io Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=pensando.io header.i=@pensando.io header.a=rsa-sha256 header.s=google header.b=IoLu8nqV; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BmL0j63xQz9sT6 for ; Wed, 9 Sep 2020 08:48:37 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729305AbgIHWsb (ORCPT ); Tue, 8 Sep 2020 18:48:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34270 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727882AbgIHWsW (ORCPT ); Tue, 8 Sep 2020 18:48:22 -0400 Received: from mail-pg1-x544.google.com (mail-pg1-x544.google.com [IPv6:2607:f8b0:4864:20::544]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC0A6C061755 for ; Tue, 8 Sep 2020 15:48:21 -0700 (PDT) Received: by mail-pg1-x544.google.com with SMTP id 7so576309pgm.11 for ; Tue, 08 Sep 2020 15:48:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pensando.io; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=k9AC4enbGJ3b0sC2EZqKVeI5FTGnaMi6W6rz9Eujrvs=; b=IoLu8nqVdnqLx2sgQ6XJviLMbC0TFwWDgqKBtTDhdiHjDML28x8HbbDDLg4Bp1jjPo wzQJcTFpEBB/0pSbLoiPnEn8X9RtadCfXRcrY2g+WvqxfdBDPBqUwy6DzKSRZ1/vQnEO kIvbhrGZArVnbnnbTAZhVCt9uqVsva7/jgtXEITpL7OzvlJtFclCRI4IbcTBOGDzCZob NGyHl5lKMIOYFbZxlIFojcCPAjwqnlQakR+YOm7Pg3g3UomyrnrS5ASRcueMcgOYs0T2 sveHLQ/Nm9S+Izwxco5m8g5OZAWTcCsz6KCbOXTzKsQ89PaoNy0zGRtfQyqbk2tccbHs 8aaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=k9AC4enbGJ3b0sC2EZqKVeI5FTGnaMi6W6rz9Eujrvs=; b=na/G1mMR+MliOW8IB9EleuxlAyiRbdqXpAKScPtCEm9N/agjN9J9jV38LwOHdWuRtj cUHDZCCkaiLfL8Une6eF7paFeklgnnrzOhPDPQBU/kfSY9jbxspABfOQRFw+XMx9zmsm r5PR5wtuC+/LT6G6fqKIMdbg3W8fj/joBhLKVZrdhN6EYTx412bmj065cePfG+WaBhi7 G1zs5K0gXBxXG3qkgX5bNc3RwWDX3Kfp4rYbw0vtV+sOZiONLTRuHIbDRwLXELj6NHPc z9ca3n8dfXGq8jXS8g0/q6aKUxKm5UwV7ofMxOSoVo9x1ftCNuR5QkALvCfwbmBGf9dX oNuA== X-Gm-Message-State: AOAM531F6PMqkN/oNh+77Dtb/V6pRC2siV5CSaEF7gZgUSbgYh3lKsJ/ qr9PXZ2Zm0uIKxIoQgcN+Kth/X19Xi+4Gw== X-Google-Smtp-Source: ABdhPJzczGRX8OZFvOZ381MsamA/KGPwwEp+lKF1hFYM4DN6vrrWdiSPgE4TgIX8+l63FJ+sIyHt4g== X-Received: by 2002:a65:5bcf:: with SMTP id o15mr738071pgr.126.1599605300963; Tue, 08 Sep 2020 15:48:20 -0700 (PDT) Received: from driver-dev1.pensando.io ([12.226.153.42]) by smtp.gmail.com with ESMTPSA id v6sm435515pfi.38.2020.09.08.15.48.19 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 08 Sep 2020 15:48:20 -0700 (PDT) From: Shannon Nelson To: netdev@vger.kernel.org, davem@davemloft.net Cc: Shannon Nelson Subject: [PATCH v3 net-next 1/2] ionic: update the fw update api Date: Tue, 8 Sep 2020 15:48:11 -0700 Message-Id: <20200908224812.63434-2-snelson@pensando.io> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200908224812.63434-1-snelson@pensando.io> References: <20200908224812.63434-1-snelson@pensando.io> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add the rest of the firmware api bits needed to support the driver running a firmware update. Signed-off-by: Shannon Nelson --- .../net/ethernet/pensando/ionic/ionic_if.h | 33 ++++++++++++++----- .../net/ethernet/pensando/ionic/ionic_main.c | 4 +++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_if.h b/drivers/net/ethernet/pensando/ionic/ionic_if.h index acc94b244cf3..5bb56a27a50d 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_if.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_if.h @@ -63,8 +63,10 @@ enum ionic_cmd_opcode { IONIC_CMD_QOS_RESET = 245, /* Firmware commands */ - IONIC_CMD_FW_DOWNLOAD = 254, - IONIC_CMD_FW_CONTROL = 255, + IONIC_CMD_FW_DOWNLOAD = 252, + IONIC_CMD_FW_CONTROL = 253, + IONIC_CMD_FW_DOWNLOAD_V1 = 254, + IONIC_CMD_FW_CONTROL_V1 = 255, }; /** @@ -2069,14 +2071,23 @@ typedef struct ionic_admin_comp ionic_fw_download_comp; /** * enum ionic_fw_control_oper - FW control operations - * @IONIC_FW_RESET: Reset firmware - * @IONIC_FW_INSTALL: Install firmware - * @IONIC_FW_ACTIVATE: Activate firmware + * @IONIC_FW_RESET: Reset firmware + * @IONIC_FW_INSTALL: Install firmware + * @IONIC_FW_ACTIVATE: Activate firmware + * @IONIC_FW_INSTALL_ASYNC: Install firmware asynchronously + * @IONIC_FW_INSTALL_STATUS: Firmware installation status + * @IONIC_FW_ACTIVATE_ASYNC: Activate firmware asynchronously + * @IONIC_FW_ACTIVATE_STATUS: Firmware activate status */ enum ionic_fw_control_oper { - IONIC_FW_RESET = 0, - IONIC_FW_INSTALL = 1, - IONIC_FW_ACTIVATE = 2, + IONIC_FW_RESET = 0, + IONIC_FW_INSTALL = 1, + IONIC_FW_ACTIVATE = 2, + IONIC_FW_INSTALL_ASYNC = 3, + IONIC_FW_INSTALL_STATUS = 4, + IONIC_FW_ACTIVATE_ASYNC = 5, + IONIC_FW_ACTIVATE_STATUS = 6, + IONIC_FW_UPDATE_CLEANUP = 7, }; /** @@ -2689,6 +2700,9 @@ union ionic_dev_cmd { struct ionic_q_identify_cmd q_identify; struct ionic_q_init_cmd q_init; struct ionic_q_control_cmd q_control; + + struct ionic_fw_download_cmd fw_download; + struct ionic_fw_control_cmd fw_control; }; union ionic_dev_cmd_comp { @@ -2722,6 +2736,9 @@ union ionic_dev_cmd_comp { struct ionic_q_identify_comp q_identify; struct ionic_q_init_comp q_init; + + ionic_fw_download_comp fw_download; + struct ionic_fw_control_comp fw_control; }; /** diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c index 2b72a51be1d0..f1fd9a98ae4a 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c @@ -170,6 +170,10 @@ static const char *ionic_opcode_to_str(enum ionic_cmd_opcode opcode) return "IONIC_CMD_FW_DOWNLOAD"; case IONIC_CMD_FW_CONTROL: return "IONIC_CMD_FW_CONTROL"; + case IONIC_CMD_FW_DOWNLOAD_V1: + return "IONIC_CMD_FW_DOWNLOAD_V1"; + case IONIC_CMD_FW_CONTROL_V1: + return "IONIC_CMD_FW_CONTROL_V1"; case IONIC_CMD_VF_GETATTR: return "IONIC_CMD_VF_GETATTR"; case IONIC_CMD_VF_SETATTR: From patchwork Tue Sep 8 22:48:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shannon Nelson X-Patchwork-Id: 1360223 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=pensando.io Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=pensando.io header.i=@pensando.io header.a=rsa-sha256 header.s=google header.b=osJnU6ji; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BmL0j1xJTz9sSJ for ; Wed, 9 Sep 2020 08:48:37 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730064AbgIHWsg (ORCPT ); Tue, 8 Sep 2020 18:48:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726694AbgIHWsY (ORCPT ); Tue, 8 Sep 2020 18:48:24 -0400 Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4703BC061573 for ; Tue, 8 Sep 2020 15:48:23 -0700 (PDT) Received: by mail-pg1-x541.google.com with SMTP id 67so571929pgd.12 for ; Tue, 08 Sep 2020 15:48:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pensando.io; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WpK8MHQXp2E5KnljcHJej1vo7BxW5s9/A4q1UAoNN/g=; b=osJnU6jigMSy09JMAV36GoOnxJGMoVjt+2Zbgr1jr+FeEq7rON4OXG5OTuWC0CSAi0 TboqMRrGqMkxks+l6ZaYwMJvaWqX8cxtSYGf5LmsG2lug+uPpletylrid3TCrjs39ql6 gPzhb4IaZ9Nt2mQpDkLDjudeKlOGjm62iSd6fDc/62w1SYlr4sTD0bgX+Tyb8YBfwh1D vawqN4jDCxGltg3U3AnVH0fy18Krc9CFTZnoQEFDmIHhPVtZwitwfJQTyxIRdALw2nkB oypbQm1SeO5m+qbgyLOswZUoIv9LIcEQnmsx9pQG+LPbkl9wBWT02nXnt4V0RTpFOXeW oXuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=WpK8MHQXp2E5KnljcHJej1vo7BxW5s9/A4q1UAoNN/g=; b=beXig56asm4krUUybbqw+kgE8xVDbUD2aR8Dp4WTkHUYY97Al91/C9auosRTGBHn5H yxK8jnC3qM0cttSkygoWkjGBPxPcSE/OcqHldzCiKuSdRrtXrxDn3wkp67LXgrLtXWML xGjr0sDYXIKCd6YJeIUxERFjcfswKLN3A1SLW5bTzpIgFEmND4Mapa6ozcAuSCSMsoJ3 ih4hfDg6281CVS8voC6Ofue+FfYh9K9LTEKMm0AgFECd2Qkj0UewDw/uyNbxJtEA9D0n EgKuT31ZJiPSSAAUoYM3nglOMdeIjKRg/HeZKJR8LouKq25XnczdXw0fj/63yDnKCvOA ylFA== X-Gm-Message-State: AOAM532o037wSZhyfhUpxYgzCf3+32iLXY//bCrK60fvpwXdk3x0ppUz ZVeRMdOwk7R6ccmO5UQhNaZq/KNLOO5x0Q== X-Google-Smtp-Source: ABdhPJwo4XgnjYlN3ajqyDeLzS5oITXPcrE3DeX7w46WEzdgNlP+AoJHNfrjhuPAV85EYrEthvcZaw== X-Received: by 2002:a63:2fc7:: with SMTP id v190mr723991pgv.250.1599605302290; Tue, 08 Sep 2020 15:48:22 -0700 (PDT) Received: from driver-dev1.pensando.io ([12.226.153.42]) by smtp.gmail.com with ESMTPSA id v6sm435515pfi.38.2020.09.08.15.48.21 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 08 Sep 2020 15:48:21 -0700 (PDT) From: Shannon Nelson To: netdev@vger.kernel.org, davem@davemloft.net Cc: Shannon Nelson Subject: [PATCH v3 net-next 2/2] ionic: add devlink firmware update Date: Tue, 8 Sep 2020 15:48:12 -0700 Message-Id: <20200908224812.63434-3-snelson@pensando.io> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200908224812.63434-1-snelson@pensando.io> References: <20200908224812.63434-1-snelson@pensando.io> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add support for firmware update through the devlink interface. This update copies the firmware object into the device, asks the current firmware to install it, then asks the firmware to select the new firmware for the next boot-up. The install and select steps are launched as asynchronous requests, which are then followed up with status request commands. These status request commands will be answered with an EAGAIN return value and will try again until the request has completed or reached the timeout specified. Signed-off-by: Shannon Nelson --- drivers/net/ethernet/pensando/ionic/Makefile | 2 +- .../ethernet/pensando/ionic/ionic_devlink.c | 14 ++ .../ethernet/pensando/ionic/ionic_devlink.h | 3 + .../net/ethernet/pensando/ionic/ionic_fw.c | 209 ++++++++++++++++++ .../net/ethernet/pensando/ionic/ionic_main.c | 23 +- 5 files changed, 242 insertions(+), 9 deletions(-) create mode 100644 drivers/net/ethernet/pensando/ionic/ionic_fw.c diff --git a/drivers/net/ethernet/pensando/ionic/Makefile b/drivers/net/ethernet/pensando/ionic/Makefile index 29f304d75261..8d3c2d3cb10d 100644 --- a/drivers/net/ethernet/pensando/ionic/Makefile +++ b/drivers/net/ethernet/pensando/ionic/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_IONIC) := ionic.o ionic-y := ionic_main.o ionic_bus_pci.o ionic_devlink.o ionic_dev.o \ ionic_debugfs.o ionic_lif.o ionic_rx_filter.o ionic_ethtool.o \ - ionic_txrx.o ionic_stats.o + ionic_txrx.o ionic_stats.o ionic_fw.o diff --git a/drivers/net/ethernet/pensando/ionic/ionic_devlink.c b/drivers/net/ethernet/pensando/ionic/ionic_devlink.c index 8d9fb2e19cca..5348f05ebc32 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_devlink.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_devlink.c @@ -9,6 +9,19 @@ #include "ionic_lif.h" #include "ionic_devlink.h" +static int ionic_dl_flash_update(struct devlink *dl, + const char *fwname, + const char *component, + struct netlink_ext_ack *extack) +{ + struct ionic *ionic = devlink_priv(dl); + + if (component) + return -EOPNOTSUPP; + + return ionic_firmware_update(ionic->lif, fwname, extack); +} + static int ionic_dl_info_get(struct devlink *dl, struct devlink_info_req *req, struct netlink_ext_ack *extack) { @@ -48,6 +61,7 @@ static int ionic_dl_info_get(struct devlink *dl, struct devlink_info_req *req, static const struct devlink_ops ionic_dl_ops = { .info_get = ionic_dl_info_get, + .flash_update = ionic_dl_flash_update, }; struct ionic *ionic_devlink_alloc(struct device *dev) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_devlink.h b/drivers/net/ethernet/pensando/ionic/ionic_devlink.h index 0690172fc57a..5c01a9e306d8 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_devlink.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_devlink.h @@ -6,6 +6,9 @@ #include +int ionic_firmware_update(struct ionic_lif *lif, const char *fw_name, + struct netlink_ext_ack *extack); + struct ionic *ionic_devlink_alloc(struct device *dev); void ionic_devlink_free(struct ionic *ionic); int ionic_devlink_register(struct ionic *ionic); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_fw.c b/drivers/net/ethernet/pensando/ionic/ionic_fw.c new file mode 100644 index 000000000000..c8d699e219d4 --- /dev/null +++ b/drivers/net/ethernet/pensando/ionic/ionic_fw.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2020 Pensando Systems, Inc */ + +#include +#include +#include +#include + +#include "ionic.h" +#include "ionic_dev.h" +#include "ionic_lif.h" +#include "ionic_devlink.h" + +/* The worst case wait for the install activity is about 25 minutes when + * installing a new CPLD, which is very seldom. Normal is about 30-35 + * seconds. Since the driver can't tell if a CPLD update will happen we + * set the timeout for the ugly case. + */ +#define IONIC_FW_INSTALL_TIMEOUT (25 * 60) +#define IONIC_FW_SELECT_TIMEOUT 30 + +/* Number of periodic log updates during fw file download */ +#define IONIC_FW_INTERVAL_FRACTION 32 + +static void ionic_dev_cmd_firmware_download(struct ionic_dev *idev, u64 addr, + u32 offset, u32 length) +{ + union ionic_dev_cmd cmd = { + .fw_download.opcode = IONIC_CMD_FW_DOWNLOAD, + .fw_download.offset = offset, + .fw_download.addr = addr, + .fw_download.length = length + }; + + ionic_dev_cmd_go(idev, &cmd); +} + +static void ionic_dev_cmd_firmware_install(struct ionic_dev *idev) +{ + union ionic_dev_cmd cmd = { + .fw_control.opcode = IONIC_CMD_FW_CONTROL, + .fw_control.oper = IONIC_FW_INSTALL_ASYNC + }; + + ionic_dev_cmd_go(idev, &cmd); +} + +static void ionic_dev_cmd_firmware_activate(struct ionic_dev *idev, u8 slot) +{ + union ionic_dev_cmd cmd = { + .fw_control.opcode = IONIC_CMD_FW_CONTROL, + .fw_control.oper = IONIC_FW_ACTIVATE_ASYNC, + .fw_control.slot = slot + }; + + ionic_dev_cmd_go(idev, &cmd); +} + +static int ionic_fw_status_long_wait(struct ionic *ionic, + const char *label, + unsigned long timeout, + u8 fw_cmd, + struct netlink_ext_ack *extack) +{ + union ionic_dev_cmd cmd = { + .fw_control.opcode = IONIC_CMD_FW_CONTROL, + .fw_control.oper = fw_cmd, + }; + unsigned long start_time; + unsigned long end_time; + struct devlink *dl; + int err; + + dl = priv_to_devlink(ionic); + devlink_flash_update_status_notify(dl, label, NULL, 1, timeout); + start_time = jiffies; + end_time = start_time + (timeout * HZ); + do { + mutex_lock(&ionic->dev_cmd_lock); + ionic_dev_cmd_go(&ionic->idev, &cmd); + err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT); + mutex_unlock(&ionic->dev_cmd_lock); + + devlink_flash_update_status_notify(dl, label, NULL, + (jiffies - start_time) / HZ, + timeout); + } while (time_before(jiffies, end_time) && (err == -EAGAIN || err == -ETIMEDOUT)); + + if (err == -EAGAIN || err == -ETIMEDOUT) { + NL_SET_ERR_MSG_MOD(extack, "Firmware wait timed out"); + dev_err(ionic->dev, "DEV_CMD firmware wait %s timed out\n", label); + } else if (err) { + NL_SET_ERR_MSG_MOD(extack, "Firmware wait failed"); + } else { + devlink_flash_update_status_notify(dl, label, NULL, timeout, timeout); + } + + return err; +} + +int ionic_firmware_update(struct ionic_lif *lif, const char *fw_name, + struct netlink_ext_ack *extack) +{ + struct ionic_dev *idev = &lif->ionic->idev; + struct net_device *netdev = lif->netdev; + struct ionic *ionic = lif->ionic; + union ionic_dev_cmd_comp comp; + u32 buf_sz, copy_sz, offset; + const struct firmware *fw; + struct devlink *dl; + int next_interval; + int err = 0; + u8 fw_slot; + + netdev_info(netdev, "Installing firmware %s\n", fw_name); + + dl = priv_to_devlink(ionic); + devlink_flash_update_begin_notify(dl); + devlink_flash_update_status_notify(dl, "Preparing to flash", NULL, 0, 0); + + err = request_firmware(&fw, fw_name, ionic->dev); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to find firmware file"); + goto err_out; + } + + buf_sz = sizeof(idev->dev_cmd_regs->data); + + netdev_dbg(netdev, + "downloading firmware - size %d part_sz %d nparts %lu\n", + (int)fw->size, buf_sz, DIV_ROUND_UP(fw->size, buf_sz)); + + devlink_flash_update_status_notify(dl, "Downloading", NULL, 0, fw->size); + offset = 0; + next_interval = fw->size / IONIC_FW_INTERVAL_FRACTION; + while (offset < fw->size) { + copy_sz = min_t(unsigned int, buf_sz, fw->size - offset); + mutex_lock(&ionic->dev_cmd_lock); + memcpy_toio(&idev->dev_cmd_regs->data, fw->data + offset, copy_sz); + ionic_dev_cmd_firmware_download(idev, + offsetof(union ionic_dev_cmd_regs, data), + offset, copy_sz); + err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT); + mutex_unlock(&ionic->dev_cmd_lock); + if (err) { + netdev_err(netdev, + "download failed offset 0x%x addr 0x%lx len 0x%x\n", + offset, offsetof(union ionic_dev_cmd_regs, data), + copy_sz); + NL_SET_ERR_MSG_MOD(extack, "Segment download failed"); + goto err_out; + } + offset += copy_sz; + + if (offset > next_interval) { + devlink_flash_update_status_notify(dl, "Downloading", + NULL, offset, fw->size); + next_interval = offset + (fw->size / IONIC_FW_INTERVAL_FRACTION); + } + } + devlink_flash_update_status_notify(dl, "Downloading", NULL, 1, 1); + + devlink_flash_update_status_notify(dl, "Installing", NULL, 0, 2); + + mutex_lock(&ionic->dev_cmd_lock); + ionic_dev_cmd_firmware_install(idev); + err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT); + ionic_dev_cmd_comp(idev, (union ionic_dev_cmd_comp *)&comp); + fw_slot = comp.fw_control.slot; + mutex_unlock(&ionic->dev_cmd_lock); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to start firmware install"); + goto err_out; + } + + err = ionic_fw_status_long_wait(ionic, "Installing", + IONIC_FW_INSTALL_TIMEOUT, + IONIC_FW_INSTALL_STATUS, + extack); + if (err) + goto err_out; + + devlink_flash_update_status_notify(dl, "Selecting", NULL, 0, 2); + + mutex_lock(&ionic->dev_cmd_lock); + ionic_dev_cmd_firmware_activate(idev, fw_slot); + err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT); + mutex_unlock(&ionic->dev_cmd_lock); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to start firmware select"); + goto err_out; + } + + err = ionic_fw_status_long_wait(ionic, "Selecting", + IONIC_FW_SELECT_TIMEOUT, + IONIC_FW_ACTIVATE_STATUS, + extack); + if (err) + goto err_out; + + netdev_info(netdev, "Firmware update completed\n"); + +err_out: + if (err) + devlink_flash_update_status_notify(dl, "Flash failed", NULL, 0, 0); + release_firmware(fw); + devlink_flash_update_end_notify(dl); + return err; +} diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c index f1fd9a98ae4a..c0979b9e38fc 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c @@ -361,17 +361,22 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds) */ max_wait = jiffies + (max_seconds * HZ); try_again: + opcode = idev->dev_cmd_regs->cmd.cmd.opcode; start_time = jiffies; do { done = ionic_dev_cmd_done(idev); if (done) break; - msleep(5); - hb = ionic_heartbeat_check(ionic); + usleep_range(100, 200); + + /* Don't check the heartbeat on FW_CONTROL commands as they are + * notorious for interrupting the firmware's heartbeat update. + */ + if (opcode != IONIC_CMD_FW_CONTROL) + hb = ionic_heartbeat_check(ionic); } while (!done && !hb && time_before(jiffies, max_wait)); duration = jiffies - start_time; - opcode = idev->dev_cmd_regs->cmd.cmd.opcode; dev_dbg(ionic->dev, "DEVCMD %s (%d) done=%d took %ld secs (%ld jiffies)\n", ionic_opcode_to_str(opcode), opcode, done, duration / HZ, duration); @@ -395,8 +400,9 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds) err = ionic_dev_cmd_status(&ionic->idev); if (err) { - if (err == IONIC_RC_EAGAIN && !time_after(jiffies, max_wait)) { - dev_err(ionic->dev, "DEV_CMD %s (%d) error, %s (%d) retrying...\n", + if (err == IONIC_RC_EAGAIN && + time_before(jiffies, (max_wait - HZ))) { + dev_dbg(ionic->dev, "DEV_CMD %s (%d), %s (%d) retrying...\n", ionic_opcode_to_str(opcode), opcode, ionic_error_to_str(err), err); @@ -406,9 +412,10 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds) goto try_again; } - dev_err(ionic->dev, "DEV_CMD %s (%d) error, %s (%d) failed\n", - ionic_opcode_to_str(opcode), opcode, - ionic_error_to_str(err), err); + if (!(opcode == IONIC_CMD_FW_CONTROL && err == IONIC_RC_EAGAIN)) + dev_err(ionic->dev, "DEV_CMD %s (%d) error, %s (%d) failed\n", + ionic_opcode_to_str(opcode), opcode, + ionic_error_to_str(err), err); return ionic_error_to_errno(err); }