From patchwork Wed Sep 15 21:58:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 512772 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ABEBEC433EF for ; Wed, 15 Sep 2021 21:58:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7A55E61130 for ; Wed, 15 Sep 2021 21:58:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232582AbhIOV7s (ORCPT ); Wed, 15 Sep 2021 17:59:48 -0400 Received: from mail.kernel.org ([198.145.29.99]:52110 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232196AbhIOV7r (ORCPT ); Wed, 15 Sep 2021 17:59:47 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 6EACA61130; Wed, 15 Sep 2021 21:58:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1631743107; bh=7TYSoNB/0NDkVm9XCSi0J0PM13RUad/hrGwtVbhBo44=; h=From:To:Cc:Subject:Date:From; b=onyJRW3tAqbOiS8g4MMisuc0ZWBWi6ROQRqlZ5j6p5g/rcuVMWw8m1HBrtd0KCVN/ si/bp1keSKcPdJYtCRrj+JsMbfXSgZd4vmIb9sce9+dZc+1xeTqJEgWqpucB3c68sn gbEFjsmRU6z1Lf+bsP15WrLtr7zkO4ks1p8BFMZrnnhOVB5rrPrRpdfopgCSQWY07m oYLdF5VFsLoTQ0LkrNmKLgm9+Cw7T1QvLlQ+5GWJ56id4sgmeKitT3CNCXD+VM2Tam EV6tC17df3h417OiIWly1f9C648HVuA4fagwAn33Zo8CGYjOF3GMUqRJob1U2ogGIE qKdk2BBLbn/Fw== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, loic.poulain@linaro.org, ryazanov.s.a@gmail.com, m.chetan.kumar@intel.com, Jakub Kicinski Subject: [PATCH net-next] Revert "net: wwan: iosm: firmware flashing and coredump collection" Date: Wed, 15 Sep 2021 14:58:23 -0700 Message-Id: <20210915215823.11584-1-kuba@kernel.org> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The devlink parameters are not the right mechanism to pass extra parameters to device flashing. The params added are also undocumented. This reverts commit 13bb8429ca98 ("net: wwan: iosm: firmware flashing and coredump collection"). Signed-off-by: Jakub Kicinski --- drivers/net/wwan/Kconfig | 1 - drivers/net/wwan/iosm/Makefile | 5 +- drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c | 6 +- drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h | 1 - drivers/net/wwan/iosm/iosm_ipc_coredump.c | 110 ----- drivers/net/wwan/iosm/iosm_ipc_coredump.h | 75 --- drivers/net/wwan/iosm/iosm_ipc_devlink.c | 360 -------------- drivers/net/wwan/iosm/iosm_ipc_devlink.h | 207 -------- drivers/net/wwan/iosm/iosm_ipc_flash.c | 562 ---------------------- drivers/net/wwan/iosm/iosm_ipc_flash.h | 271 ----------- drivers/net/wwan/iosm/iosm_ipc_imem.c | 103 +--- drivers/net/wwan/iosm/iosm_ipc_imem.h | 18 +- drivers/net/wwan/iosm/iosm_ipc_imem_ops.c | 317 ------------ drivers/net/wwan/iosm/iosm_ipc_imem_ops.h | 49 +- 14 files changed, 31 insertions(+), 2054 deletions(-) delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_coredump.c delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_coredump.h delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_devlink.c delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_devlink.h delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_flash.c delete mode 100644 drivers/net/wwan/iosm/iosm_ipc_flash.h diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig index 17543be14665..77dbfc418bce 100644 --- a/drivers/net/wwan/Kconfig +++ b/drivers/net/wwan/Kconfig @@ -71,7 +71,6 @@ config RPMSG_WWAN_CTRL config IOSM tristate "IOSM Driver for Intel M.2 WWAN Device" depends on INTEL_IOMMU - select NET_DEVLINK help This driver enables Intel M.2 WWAN Device communication. diff --git a/drivers/net/wwan/iosm/Makefile b/drivers/net/wwan/iosm/Makefile index b838034bb120..4f9f0ae398e1 100644 --- a/drivers/net/wwan/iosm/Makefile +++ b/drivers/net/wwan/iosm/Makefile @@ -18,9 +18,6 @@ iosm-y = \ iosm_ipc_protocol.o \ iosm_ipc_protocol_ops.o \ iosm_ipc_mux.o \ - iosm_ipc_mux_codec.o \ - iosm_ipc_devlink.o \ - iosm_ipc_flash.o \ - iosm_ipc_coredump.o + iosm_ipc_mux_codec.o obj-$(CONFIG_IOSM) := iosm.o diff --git a/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c b/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c index 128c999e08bb..519361ec40df 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c +++ b/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c @@ -8,7 +8,7 @@ #include "iosm_ipc_chnl_cfg.h" /* Max. sizes of a downlink buffers */ -#define IPC_MEM_MAX_DL_FLASH_BUF_SIZE (64 * 1024) +#define IPC_MEM_MAX_DL_FLASH_BUF_SIZE (16 * 1024) #define IPC_MEM_MAX_DL_LOOPBACK_SIZE (1 * 1024 * 1024) #define IPC_MEM_MAX_DL_AT_BUF_SIZE 2048 #define IPC_MEM_MAX_DL_RPC_BUF_SIZE (32 * 1024) @@ -60,10 +60,6 @@ static struct ipc_chnl_cfg modem_cfg[] = { { IPC_MEM_CTRL_CHL_ID_6, IPC_MEM_PIPE_12, IPC_MEM_PIPE_13, IPC_MEM_MAX_TDS_MBIM, IPC_MEM_MAX_TDS_MBIM, IPC_MEM_MAX_DL_MBIM_BUF_SIZE, WWAN_PORT_MBIM }, - /* Flash Channel/Coredump Channel */ - { IPC_MEM_CTRL_CHL_ID_7, IPC_MEM_PIPE_0, IPC_MEM_PIPE_1, - IPC_MEM_MAX_TDS_FLASH_UL, IPC_MEM_MAX_TDS_FLASH_DL, - IPC_MEM_MAX_DL_FLASH_BUF_SIZE, WWAN_PORT_UNKNOWN }, }; int ipc_chnl_cfg_get(struct ipc_chnl_cfg *chnl_cfg, int index) diff --git a/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h b/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h index e77084e76718..422471367f78 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h +++ b/drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h @@ -23,7 +23,6 @@ enum ipc_channel_id { IPC_MEM_CTRL_CHL_ID_4, IPC_MEM_CTRL_CHL_ID_5, IPC_MEM_CTRL_CHL_ID_6, - IPC_MEM_CTRL_CHL_ID_7, }; /** diff --git a/drivers/net/wwan/iosm/iosm_ipc_coredump.c b/drivers/net/wwan/iosm/iosm_ipc_coredump.c deleted file mode 100644 index fba3c3454e80..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_coredump.c +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#include "iosm_ipc_coredump.h" - -/* Collect coredump data from modem */ -int ipc_coredump_collect(struct iosm_devlink *devlink, u8 **data, int entry, - u32 region_size) -{ - int ret, bytes_to_read, bytes_read = 0, i = 0; - s32 remaining; - u8 *data_ptr; - - data_ptr = vmalloc(region_size); - if (!data_ptr) - return -ENOMEM; - - remaining = devlink->cd_file_info[entry].actual_size; - ret = ipc_devlink_send_cmd(devlink, rpsi_cmd_coredump_get, entry); - if (ret) { - dev_err(devlink->dev, "Send coredump_get cmd failed"); - goto get_cd_fail; - } - while (remaining > 0) { - bytes_to_read = min(remaining, MAX_DATA_SIZE); - bytes_read = 0; - ret = ipc_imem_sys_devlink_read(devlink, data_ptr + i, - bytes_to_read, &bytes_read); - if (ret) { - dev_err(devlink->dev, "CD data read failed"); - goto get_cd_fail; - } - remaining -= bytes_read; - i += bytes_read; - } - - *data = data_ptr; - - return ret; -get_cd_fail: - vfree(data_ptr); - return ret; -} - -/* Get coredump list to be collected from modem */ -int ipc_coredump_get_list(struct iosm_devlink *devlink, u16 cmd) -{ - u32 byte_read, num_entries, file_size; - struct iosm_cd_table *cd_table; - u8 size[MAX_SIZE_LEN], i; - char *filename; - int ret = 0; - - cd_table = kzalloc(MAX_CD_LIST_SIZE, GFP_KERNEL); - if (!cd_table) { - ret = -ENOMEM; - goto cd_init_fail; - } - - ret = ipc_devlink_send_cmd(devlink, cmd, MAX_CD_LIST_SIZE); - if (ret) { - dev_err(devlink->dev, "rpsi_cmd_coredump_start failed"); - goto cd_init_fail; - } - - ret = ipc_imem_sys_devlink_read(devlink, (u8 *)cd_table, - MAX_CD_LIST_SIZE, &byte_read); - if (ret) { - dev_err(devlink->dev, "Coredump data is invalid"); - goto cd_init_fail; - } - - if (byte_read != MAX_CD_LIST_SIZE) - goto cd_init_fail; - - if (cmd == rpsi_cmd_coredump_start) { - num_entries = le32_to_cpu(cd_table->list.num_entries); - if (num_entries == 0 || num_entries > IOSM_NOF_CD_REGION) { - ret = -EINVAL; - goto cd_init_fail; - } - - for (i = 0; i < num_entries; i++) { - file_size = le32_to_cpu(cd_table->list.entry[i].size); - filename = cd_table->list.entry[i].filename; - - if (file_size > devlink->cd_file_info[i].default_size) { - ret = -EINVAL; - goto cd_init_fail; - } - - devlink->cd_file_info[i].actual_size = file_size; - dev_dbg(devlink->dev, "file: %s actual size %d", - filename, file_size); - devlink_flash_update_status_notify(devlink->devlink_ctx, - filename, - "FILENAME", 0, 0); - snprintf(size, sizeof(size), "%d", file_size); - devlink_flash_update_status_notify(devlink->devlink_ctx, - size, "FILE SIZE", - 0, 0); - } - } - -cd_init_fail: - kfree(cd_table); - return ret; -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_coredump.h b/drivers/net/wwan/iosm/iosm_ipc_coredump.h deleted file mode 100644 index d5028153c8d1..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_coredump.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only - * - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#ifndef _IOSM_IPC_COREDUMP_H_ -#define _IOSM_IPC_COREDUMP_H_ - -#include "iosm_ipc_devlink.h" - -/* Max number of bytes to receive for Coredump list structure */ -#define MAX_CD_LIST_SIZE 0x1000 - -/* Max buffer allocated to receive coredump data */ -#define MAX_DATA_SIZE 0x00010000 - -/* Max number of file entries */ -#define MAX_NOF_ENTRY 256 - -/* Max length */ -#define MAX_SIZE_LEN 32 - -/** - * struct iosm_cd_list_entry - Structure to hold coredump file info. - * @size: Number of bytes for the entry - * @filename: Coredump filename to be generated on host - */ -struct iosm_cd_list_entry { - __le32 size; - char filename[IOSM_MAX_FILENAME_LEN]; -} __packed; - -/** - * struct iosm_cd_list - Structure to hold list of coredump files - * to be collected. - * @num_entries: Number of entries to be received - * @entry: Contains File info - */ -struct iosm_cd_list { - __le32 num_entries; - struct iosm_cd_list_entry entry[MAX_NOF_ENTRY]; -} __packed; - -/** - * struct iosm_cd_table - Common Coredump table - * @version: Version of coredump structure - * @list: Coredump list structure - */ -struct iosm_cd_table { - __le32 version; - struct iosm_cd_list list; -} __packed; - -/** - * ipc_coredump_collect - To collect coredump - * @devlink: Pointer to devlink instance. - * @data: Pointer to snapshot - * @entry: ID of requested snapshot - * @region_size: Region size - * - * Returns: 0 on success, error on failure - */ -int ipc_coredump_collect(struct iosm_devlink *devlink, u8 **data, int entry, - u32 region_size); - -/** - * ipc_coredump_get_list - Get coredump list - * @devlink: Pointer to devlink instance. - * @cmd: RPSI command to be sent - * - * Returns: 0 on success, error on failure - */ -int ipc_coredump_get_list(struct iosm_devlink *devlink, u16 cmd); - -#endif /* _IOSM_IPC_COREDUMP_H_ */ diff --git a/drivers/net/wwan/iosm/iosm_ipc_devlink.c b/drivers/net/wwan/iosm/iosm_ipc_devlink.c deleted file mode 100644 index 592792c277fe..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_devlink.c +++ /dev/null @@ -1,360 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#include "iosm_ipc_chnl_cfg.h" -#include "iosm_ipc_coredump.h" -#include "iosm_ipc_devlink.h" -#include "iosm_ipc_flash.h" - -/* Coredump list */ -static struct iosm_coredump_file_info list[IOSM_NOF_CD_REGION] = { - {"report.json", REPORT_JSON_SIZE,}, - {"coredump.fcd", COREDUMP_FCD_SIZE,}, - {"cdd.log", CDD_LOG_SIZE,}, - {"eeprom.bin", EEPROM_BIN_SIZE,}, - {"bootcore_trace.bin", BOOTCORE_TRC_BIN_SIZE,}, - {"bootcore_prev_trace.bin", BOOTCORE_PREV_TRC_BIN_SIZE,}, -}; - -/* Get the param values for the specific param ID's */ -static int ipc_devlink_get_param(struct devlink *dl, u32 id, - struct devlink_param_gset_ctx *ctx) -{ - struct iosm_devlink *ipc_devlink = devlink_priv(dl); - int rc = 0; - - switch (id) { - case IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH: - ctx->val.vu8 = ipc_devlink->param.erase_full_flash; - break; - - case IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION: - ctx->val.vu8 = ipc_devlink->param.download_region; - break; - - case IOSM_DEVLINK_PARAM_ID_ADDRESS: - ctx->val.vu32 = ipc_devlink->param.address; - break; - - case IOSM_DEVLINK_PARAM_ID_REGION_COUNT: - ctx->val.vu8 = ipc_devlink->param.region_count; - break; - - default: - rc = -EOPNOTSUPP; - break; - } - - return rc; -} - -/* Set the param values for the specific param ID's */ -static int ipc_devlink_set_param(struct devlink *dl, u32 id, - struct devlink_param_gset_ctx *ctx) -{ - struct iosm_devlink *ipc_devlink = devlink_priv(dl); - int rc = 0; - - switch (id) { - case IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH: - ipc_devlink->param.erase_full_flash = ctx->val.vu8; - break; - - case IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION: - ipc_devlink->param.download_region = ctx->val.vu8; - break; - - case IOSM_DEVLINK_PARAM_ID_ADDRESS: - ipc_devlink->param.address = ctx->val.vu32; - break; - - case IOSM_DEVLINK_PARAM_ID_REGION_COUNT: - ipc_devlink->param.region_count = ctx->val.vu8; - break; - - default: - rc = -EOPNOTSUPP; - break; - } - - return rc; -} - -/* Devlink param structure array */ -static const struct devlink_param iosm_devlink_params[] = { - DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH, - "erase_full_flash", DEVLINK_PARAM_TYPE_BOOL, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - ipc_devlink_get_param, ipc_devlink_set_param, - NULL), - DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION, - "download_region", DEVLINK_PARAM_TYPE_BOOL, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - ipc_devlink_get_param, ipc_devlink_set_param, - NULL), - DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_ADDRESS, - "address", DEVLINK_PARAM_TYPE_U32, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - ipc_devlink_get_param, ipc_devlink_set_param, - NULL), - DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_REGION_COUNT, - "region_count", DEVLINK_PARAM_TYPE_U8, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - ipc_devlink_get_param, ipc_devlink_set_param, - NULL), -}; - -/* Get devlink flash component type */ -static enum iosm_flash_comp_type -ipc_devlink_get_flash_comp_type(const char comp_str[], u32 len) -{ - enum iosm_flash_comp_type fls_type; - - if (!strncmp("PSI", comp_str, len)) - fls_type = FLASH_COMP_TYPE_PSI; - else if (!strncmp("EBL", comp_str, len)) - fls_type = FLASH_COMP_TYPE_EBL; - else if (!strncmp("FLS", comp_str, len)) - fls_type = FLASH_COMP_TYPE_FLS; - else - fls_type = FLASH_COMP_TYPE_INVAL; - - return fls_type; -} - -/* Function triggered on devlink flash command - * Flash update function which calls multiple functions based on - * component type specified in the flash command - */ -static int ipc_devlink_flash_update(struct devlink *devlink, - struct devlink_flash_update_params *params, - struct netlink_ext_ack *extack) -{ - struct iosm_devlink *ipc_devlink = devlink_priv(devlink); - enum iosm_flash_comp_type fls_type; - u32 rc = -EINVAL; - u8 *mdm_rsp; - - mdm_rsp = kzalloc(IOSM_EBL_DW_PACK_SIZE, GFP_KERNEL); - if (!mdm_rsp) - return -ENOMEM; - - fls_type = ipc_devlink_get_flash_comp_type(params->component, - strlen(params->component)); - - switch (fls_type) { - case FLASH_COMP_TYPE_PSI: - rc = ipc_flash_boot_psi(ipc_devlink, params->fw); - break; - case FLASH_COMP_TYPE_EBL: - rc = ipc_flash_boot_ebl(ipc_devlink, params->fw); - if (!rc) - rc = ipc_flash_boot_set_capabilities(ipc_devlink, - mdm_rsp); - if (!rc) - rc = ipc_flash_read_swid(ipc_devlink, mdm_rsp); - break; - case FLASH_COMP_TYPE_FLS: - rc = ipc_flash_send_fls(ipc_devlink, params->fw, mdm_rsp); - break; - default: - devlink_flash_update_status_notify(devlink, "Invalid component", - params->component, 0, 0); - break; - } - - if (!rc) - devlink_flash_update_status_notify(devlink, "Flashing success", - params->component, 0, 0); - else - devlink_flash_update_status_notify(devlink, "Flashing failed", - params->component, 0, 0); - - kfree(mdm_rsp); - return rc; -} - -/* Call back function for devlink ops */ -static const struct devlink_ops devlink_flash_ops = { - .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT, - .flash_update = ipc_devlink_flash_update, -}; - -/* Send command to modem to collect data */ -int ipc_devlink_send_cmd(struct iosm_devlink *ipc_devlink, u16 cmd, u32 entry) -{ - struct iosm_rpsi_cmd rpsi_cmd; - - rpsi_cmd.param.dword = cpu_to_le32(entry); - rpsi_cmd.cmd = cpu_to_le16(cmd); - rpsi_cmd.crc = rpsi_cmd.param.word[0] ^ rpsi_cmd.param.word[1] ^ - rpsi_cmd.cmd; - - return ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&rpsi_cmd, - sizeof(rpsi_cmd)); -} - -static int ipc_devlink_coredump_snapshot(struct devlink *dl, - const struct devlink_region_ops *ops, - struct netlink_ext_ack *extack, - u8 **data) -{ - struct iosm_devlink *ipc_devlink = devlink_priv(dl); - struct iosm_coredump_file_info *cd_list = ops->priv; - u32 region_size; - int rc; - - dev_dbg(ipc_devlink->dev, "Region:%s, ID:%d", ops->name, - cd_list->entry); - region_size = cd_list->default_size; - rc = ipc_coredump_collect(ipc_devlink, data, cd_list->entry, - region_size); - if (rc) { - dev_err(ipc_devlink->dev, "Fail to create snapshot,err %d", rc); - goto coredump_collect_err; - } - - /* Send coredump end cmd indicating end of coredump collection */ - if (cd_list->entry == (IOSM_NOF_CD_REGION - 1)) - ipc_coredump_get_list(ipc_devlink, rpsi_cmd_coredump_end); - - return rc; -coredump_collect_err: - ipc_coredump_get_list(ipc_devlink, rpsi_cmd_coredump_end); - return rc; -} - -/* To create regions for coredump files */ -static int ipc_devlink_create_region(struct iosm_devlink *devlink) -{ - struct devlink_region_ops *mdm_coredump; - int rc = 0; - u8 i; - - mdm_coredump = devlink->iosm_devlink_mdm_coredump; - for (i = 0; i < IOSM_NOF_CD_REGION; i++) { - mdm_coredump[i].name = list[i].filename; - mdm_coredump[i].snapshot = ipc_devlink_coredump_snapshot; - mdm_coredump[i].destructor = vfree; - devlink->cd_regions[i] = - devlink_region_create(devlink->devlink_ctx, - &mdm_coredump[i], MAX_SNAPSHOTS, - list[i].default_size); - - if (IS_ERR(devlink->cd_regions[i])) { - rc = PTR_ERR(devlink->cd_regions[i]); - dev_err(devlink->dev, "Devlink region fail,err %d", rc); - /* Delete previously created regions */ - for ( ; i > 0; i--) - devlink_region_destroy(devlink->cd_regions[i]); - goto region_create_fail; - } - list[i].entry = i; - mdm_coredump[i].priv = list + i; - } -region_create_fail: - return rc; -} - -/* To Destroy devlink regions */ -static void ipc_devlink_destroy_region(struct iosm_devlink *ipc_devlink) -{ - u8 i; - - for (i = 0; i < IOSM_NOF_CD_REGION; i++) - devlink_region_destroy(ipc_devlink->cd_regions[i]); -} - -/* Handle registration to devlink framework */ -struct iosm_devlink *ipc_devlink_init(struct iosm_imem *ipc_imem) -{ - struct ipc_chnl_cfg chnl_cfg_flash = { 0 }; - struct iosm_devlink *ipc_devlink; - struct devlink *devlink_ctx; - int rc; - - devlink_ctx = devlink_alloc(&devlink_flash_ops, - sizeof(struct iosm_devlink), - ipc_imem->dev); - if (!devlink_ctx) { - dev_err(ipc_imem->dev, "devlink_alloc failed"); - goto devlink_alloc_fail; - } - - ipc_devlink = devlink_priv(devlink_ctx); - ipc_devlink->devlink_ctx = devlink_ctx; - ipc_devlink->pcie = ipc_imem->pcie; - ipc_devlink->dev = ipc_imem->dev; - rc = devlink_register(devlink_ctx); - if (rc) { - dev_err(ipc_devlink->dev, "devlink_register failed rc %d", rc); - goto free_dl; - } - - rc = devlink_params_register(devlink_ctx, iosm_devlink_params, - ARRAY_SIZE(iosm_devlink_params)); - if (rc) { - dev_err(ipc_devlink->dev, - "devlink_params_register failed. rc %d", rc); - goto param_reg_fail; - } - - devlink_params_publish(devlink_ctx); - ipc_devlink->cd_file_info = list; - - rc = ipc_devlink_create_region(ipc_devlink); - if (rc) { - dev_err(ipc_devlink->dev, "Devlink Region create failed, rc %d", - rc); - goto region_create_fail; - } - - if (ipc_chnl_cfg_get(&chnl_cfg_flash, IPC_MEM_CTRL_CHL_ID_7) < 0) - goto chnl_get_fail; - - ipc_imem_channel_init(ipc_imem, IPC_CTYPE_CTRL, - chnl_cfg_flash, IRQ_MOD_OFF); - - init_completion(&ipc_devlink->devlink_sio.read_sem); - skb_queue_head_init(&ipc_devlink->devlink_sio.rx_list); - - dev_dbg(ipc_devlink->dev, "iosm devlink register success"); - - return ipc_devlink; - -chnl_get_fail: - ipc_devlink_destroy_region(ipc_devlink); -region_create_fail: - devlink_params_unpublish(devlink_ctx); - devlink_params_unregister(devlink_ctx, iosm_devlink_params, - ARRAY_SIZE(iosm_devlink_params)); -param_reg_fail: - devlink_unregister(devlink_ctx); -free_dl: - devlink_free(devlink_ctx); -devlink_alloc_fail: - return NULL; -} - -/* Handle unregistration of devlink */ -void ipc_devlink_deinit(struct iosm_devlink *ipc_devlink) -{ - struct devlink *devlink_ctx = ipc_devlink->devlink_ctx; - - ipc_devlink_destroy_region(ipc_devlink); - devlink_params_unpublish(devlink_ctx); - devlink_params_unregister(devlink_ctx, iosm_devlink_params, - ARRAY_SIZE(iosm_devlink_params)); - if (ipc_devlink->devlink_sio.devlink_read_pend) { - complete(&ipc_devlink->devlink_sio.read_sem); - complete(&ipc_devlink->devlink_sio.channel->ul_sem); - } - if (!ipc_devlink->devlink_sio.devlink_read_pend) - skb_queue_purge(&ipc_devlink->devlink_sio.rx_list); - - ipc_imem_sys_devlink_close(ipc_devlink); - devlink_unregister(devlink_ctx); - devlink_free(devlink_ctx); -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_devlink.h b/drivers/net/wwan/iosm/iosm_ipc_devlink.h deleted file mode 100644 index 392735080cb3..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_devlink.h +++ /dev/null @@ -1,207 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only - * - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#ifndef _IOSM_IPC_DEVLINK_H_ -#define _IOSM_IPC_DEVLINK_H_ - -#include - -#include "iosm_ipc_imem.h" -#include "iosm_ipc_imem_ops.h" -#include "iosm_ipc_pcie.h" - -/* MAX file name length */ -#define IOSM_MAX_FILENAME_LEN 32 -/* EBL response size */ -#define IOSM_EBL_RSP_SIZE 76 -/* MAX number of regions supported */ -#define IOSM_NOF_CD_REGION 6 -/* MAX number of SNAPSHOTS supported */ -#define MAX_SNAPSHOTS 1 -/* Default Coredump file size */ -#define REPORT_JSON_SIZE 0x800 -#define COREDUMP_FCD_SIZE 0x10E00000 -#define CDD_LOG_SIZE 0x30000 -#define EEPROM_BIN_SIZE 0x10000 -#define BOOTCORE_TRC_BIN_SIZE 0x8000 -#define BOOTCORE_PREV_TRC_BIN_SIZE 0x20000 - -/** - * enum iosm_devlink_param_id - Enum type to different devlink params - * @IOSM_DEVLINK_PARAM_ID_BASE: Devlink param base ID - * @IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH: Set if full erase required - * @IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION: Set if fls file to be - * flashed is Loadmap/region file - * @IOSM_DEVLINK_PARAM_ID_ADDRESS: Address of the region to be - * flashed - * @IOSM_DEVLINK_PARAM_ID_REGION_COUNT: Max region count - */ - -enum iosm_devlink_param_id { - IOSM_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, - IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH, - IOSM_DEVLINK_PARAM_ID_DOWNLOAD_REGION, - IOSM_DEVLINK_PARAM_ID_ADDRESS, - IOSM_DEVLINK_PARAM_ID_REGION_COUNT, -}; - -/** - * enum iosm_rpsi_cmd_code - Enum type for RPSI command list - * @rpsi_cmd_code_ebl: Command to load ebl - * @rpsi_cmd_coredump_start: Command to get list of files and - * file size info from PSI - * @rpsi_cmd_coredump_get: Command to get the coredump data - * @rpsi_cmd_coredump_end: Command to stop receiving the coredump - */ -enum iosm_rpsi_cmd_code { - rpsi_cmd_code_ebl = 0x02, - rpsi_cmd_coredump_start = 0x10, - rpsi_cmd_coredump_get = 0x11, - rpsi_cmd_coredump_end = 0x12, -}; - -/** - * enum iosm_flash_comp_type - Enum for different flash component types - * @FLASH_COMP_TYPE_PSI: PSI flash comp type - * @FLASH_COMP_TYPE_EBL: EBL flash comp type - * @FLASH_COMP_TYPE_FLS: FLS flash comp type - * @FLASH_COMP_TYPE_INVAL: Invalid flash comp type - */ -enum iosm_flash_comp_type { - FLASH_COMP_TYPE_PSI, - FLASH_COMP_TYPE_EBL, - FLASH_COMP_TYPE_FLS, - FLASH_COMP_TYPE_INVAL, -}; - -/** - * struct iosm_devlink_sio - SIO instance - * @rx_list: Downlink skbuf list received from CP - * @read_sem: Needed for the blocking read or downlink transfer - * @channel_id: Reserved channel id for flashing/CD collection to RAM - * @channel: Channel instance for flashing and coredump - * @devlink_read_pend: Check if read is pending - */ -struct iosm_devlink_sio { - struct sk_buff_head rx_list; - struct completion read_sem; - int channel_id; - struct ipc_mem_channel *channel; - u32 devlink_read_pend; -}; - -/** - * struct iosm_flash_params - List of flash params required for flashing - * @address: Address of the region file to be flashed - * @region_count: Maximum no of regions for each fls file - * @download_region: To be set if region is being flashed - * @erase_full_flash: To set the flashing mode - * erase_full_flash = 1; full erase - * erase_full_flash = 0; no erase - * @erase_full_flash_done: Flag to check if it is a full erase - */ -struct iosm_flash_params { - u32 address; - u8 region_count; - u8 download_region; - u8 erase_full_flash; - u8 erase_full_flash_done; -}; - -/** - * struct iosm_ebl_ctx_data - EBL ctx data used during flashing - * @ebl_sw_info_version: SWID version info obtained from EBL - * @m_ebl_resp: Buffer used to read and write the ebl data - */ -struct iosm_ebl_ctx_data { - u8 ebl_sw_info_version; - u8 m_ebl_resp[IOSM_EBL_RSP_SIZE]; -}; - -/** - * struct iosm_coredump_file_info - Coredump file info - * @filename: Name of coredump file - * @default_size: Default size of coredump file - * @actual_size: Actual size of coredump file - * @entry: Index of the coredump file - */ -struct iosm_coredump_file_info { - char filename[IOSM_MAX_FILENAME_LEN]; - u32 default_size; - u32 actual_size; - u32 entry; -}; - -/** - * struct iosm_devlink - IOSM Devlink structure - * @devlink_sio: SIO instance for read/write functionality - * @pcie: Pointer to PCIe component - * @dev: Pointer to device struct - * @devlink_ctx: Pointer to devlink context - * @param: Params required for flashing - * @ebl_ctx: Data to be read and written to Modem - * @cd_file_info: coredump file info - * @iosm_devlink_mdm_coredump: region ops for coredump collection - * @cd_regions: coredump regions - */ -struct iosm_devlink { - struct iosm_devlink_sio devlink_sio; - struct iosm_pcie *pcie; - struct device *dev; - struct devlink *devlink_ctx; - struct iosm_flash_params param; - struct iosm_ebl_ctx_data ebl_ctx; - struct iosm_coredump_file_info *cd_file_info; - struct devlink_region_ops iosm_devlink_mdm_coredump[IOSM_NOF_CD_REGION]; - struct devlink_region *cd_regions[IOSM_NOF_CD_REGION]; -}; - -/** - * union iosm_rpsi_param_u - RPSI cmd param for CRC calculation - * @word: Words member used in CRC calculation - * @dword: Actual data - */ -union iosm_rpsi_param_u { - __le16 word[2]; - __le32 dword; -}; - -/** - * struct iosm_rpsi_cmd - Structure for RPSI Command - * @param: Used to calculate CRC - * @cmd: Stores the RPSI command - * @crc: Stores the CRC value - */ -struct iosm_rpsi_cmd { - union iosm_rpsi_param_u param; - __le16 cmd; - __le16 crc; -}; - -/** - * ipc_devlink_init - To initialize the devlink to IOSM driver - * @ipc_imem: Pointer to struct iosm_imem - * - * Returns: Pointer to iosm_devlink on success and NULL on failure - */ -struct iosm_devlink *ipc_devlink_init(struct iosm_imem *ipc_imem); - -/** - * ipc_devlink_deinit - To unintialize the devlink from IOSM driver. - * @ipc_devlink: Devlink instance - */ -void ipc_devlink_deinit(struct iosm_devlink *ipc_devlink); - -/** - * ipc_devlink_send_cmd - Send command to Modem - * @ipc_devlink: Pointer to struct iosm_devlink - * @cmd: Command to be sent to modem - * @entry: Command entry number - * - * Returns: 0 on success and failure value on error - */ -int ipc_devlink_send_cmd(struct iosm_devlink *ipc_devlink, u16 cmd, u32 entry); - -#endif /* _IOSM_IPC_DEVLINK_H */ diff --git a/drivers/net/wwan/iosm/iosm_ipc_flash.c b/drivers/net/wwan/iosm/iosm_ipc_flash.c deleted file mode 100644 index a43aafc70168..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_flash.c +++ /dev/null @@ -1,562 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#include "iosm_ipc_coredump.h" -#include "iosm_ipc_devlink.h" -#include "iosm_ipc_flash.h" - -/* This function will pack the data to be sent to the modem using the - * payload, payload length and pack id - */ -static int ipc_flash_proc_format_ebl_pack(struct iosm_flash_data *flash_req, - u32 pack_length, u16 pack_id, - u8 *payload, u32 payload_length) -{ - u16 checksum = pack_id; - u32 i; - - if (payload_length + IOSM_EBL_HEAD_SIZE > pack_length) - return -EINVAL; - - flash_req->pack_id = cpu_to_le16(pack_id); - flash_req->msg_length = cpu_to_le32(payload_length); - checksum += (payload_length >> IOSM_EBL_PAYL_SHIFT) + - (payload_length & IOSM_EBL_CKSM); - - for (i = 0; i < payload_length; i++) - checksum += payload[i]; - - flash_req->checksum = cpu_to_le16(checksum); - - return 0; -} - -/* validate the response received from modem and - * check the type of errors received - */ -static int ipc_flash_proc_check_ebl_rsp(void *hdr_rsp, void *payload_rsp) -{ - struct iosm_ebl_error *err_info = payload_rsp; - u16 *rsp_code = hdr_rsp; - int res = 0; - u32 i; - - if (*rsp_code == IOSM_EBL_RSP_BUFF) { - for (i = 0; i < IOSM_MAX_ERRORS; i++) { - if (!err_info->error[i].error_code) { - pr_err("EBL: error_class = %d, error_code = %d", - err_info->error[i].error_class, - err_info->error[i].error_code); - } - } - res = -EINVAL; - } - - return res; -} - -/* Send data to the modem */ -static int ipc_flash_send_data(struct iosm_devlink *ipc_devlink, u32 size, - u16 pack_id, u8 *payload, u32 payload_length) -{ - struct iosm_flash_data flash_req; - int ret; - - ret = ipc_flash_proc_format_ebl_pack(&flash_req, size, - pack_id, payload, payload_length); - if (ret) { - dev_err(ipc_devlink->dev, "EBL2 pack failed for pack_id:%d", - pack_id); - goto ipc_free_payload; - } - - ret = ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&flash_req, - IOSM_EBL_HEAD_SIZE); - if (ret) { - dev_err(ipc_devlink->dev, "EBL Header write failed for Id:%x", - pack_id); - goto ipc_free_payload; - } - - ret = ipc_imem_sys_devlink_write(ipc_devlink, payload, payload_length); - if (ret) { - dev_err(ipc_devlink->dev, "EBL Payload write failed for Id:%x", - pack_id); - } - -ipc_free_payload: - return ret; -} - -/* Allocate flash channel and read LER data from modem */ -int ipc_flash_link_establish(struct iosm_imem *ipc_imem) -{ - u8 ler_data[IOSM_LER_RSP_SIZE]; - u32 bytes_read; - - /* Allocate channel for flashing/cd collection */ - ipc_imem->ipc_devlink->devlink_sio.channel = - ipc_imem_sys_devlink_open(ipc_imem); - - if (!ipc_imem->ipc_devlink->devlink_sio.channel) - goto chl_open_fail; - - if (ipc_imem_sys_devlink_read(ipc_imem->ipc_devlink, ler_data, - IOSM_LER_RSP_SIZE, &bytes_read)) - goto devlink_read_fail; - - if (bytes_read != IOSM_LER_RSP_SIZE) - goto devlink_read_fail; - return 0; - -devlink_read_fail: - ipc_imem_sys_devlink_close(ipc_imem->ipc_devlink); -chl_open_fail: - return -EIO; -} - -/* Receive data from the modem */ -static int ipc_flash_receive_data(struct iosm_devlink *ipc_devlink, u32 size, - u8 *mdm_rsp) -{ - u8 mdm_rsp_hdr[IOSM_EBL_HEAD_SIZE]; - u32 bytes_read; - int ret; - - ret = ipc_imem_sys_devlink_read(ipc_devlink, mdm_rsp_hdr, - IOSM_EBL_HEAD_SIZE, &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL rsp to read %d bytes failed", - IOSM_EBL_HEAD_SIZE); - goto ipc_flash_recv_err; - } - - if (bytes_read != IOSM_EBL_HEAD_SIZE) { - ret = -EINVAL; - goto ipc_flash_recv_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, mdm_rsp, size, - &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL rsp to read %d bytes failed", - size); - goto ipc_flash_recv_err; - } - - if (bytes_read != size) { - ret = -EINVAL; - goto ipc_flash_recv_err; - } - - ret = ipc_flash_proc_check_ebl_rsp(mdm_rsp_hdr + 2, mdm_rsp); - -ipc_flash_recv_err: - return ret; -} - -/* Function to send command to modem and receive response */ -static int ipc_flash_send_receive(struct iosm_devlink *ipc_devlink, u16 pack_id, - u8 *payload, u32 payload_length, u8 *mdm_rsp) -{ - size_t frame_len = IOSM_EBL_DW_PACK_SIZE; - int ret; - - if (pack_id == FLASH_SET_PROT_CONF) - frame_len = IOSM_EBL_W_PACK_SIZE; - - ret = ipc_flash_send_data(ipc_devlink, frame_len, pack_id, payload, - payload_length); - if (ret) - goto ipc_flash_send_rcv; - - ret = ipc_flash_receive_data(ipc_devlink, - frame_len - IOSM_EBL_HEAD_SIZE, mdm_rsp); - -ipc_flash_send_rcv: - return ret; -} - -/* Set the capabilities for the EBL */ -int ipc_flash_boot_set_capabilities(struct iosm_devlink *ipc_devlink, - u8 *mdm_rsp) -{ - int ret; - - ipc_devlink->ebl_ctx.ebl_sw_info_version = - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_RSP_SW_INFO_VER]; - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_SKIP_ERASE] = IOSM_CAP_NOT_ENHANCED; - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_SKIP_CRC] = IOSM_CAP_NOT_ENHANCED; - - if (ipc_devlink->ebl_ctx.m_ebl_resp[EBL_CAPS_FLAG] & - IOSM_CAP_USE_EXT_CAP) { - if (ipc_devlink->param.erase_full_flash) - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_OOS_CONFIG] &= - ~((u8)IOSM_EXT_CAP_ERASE_ALL); - else - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_OOS_CONFIG] &= - ~((u8)IOSM_EXT_CAP_COMMIT_ALL); - ipc_devlink->ebl_ctx.m_ebl_resp[EBL_EXT_CAPS_HANDLED] = - IOSM_CAP_USE_EXT_CAP; - } - - /* Write back the EBL capability to modem - * Request Set Protcnf command - */ - ret = ipc_flash_send_receive(ipc_devlink, FLASH_SET_PROT_CONF, - ipc_devlink->ebl_ctx.m_ebl_resp, - IOSM_EBL_RSP_SIZE, mdm_rsp); - return ret; -} - -/* Read the SWID type and SWID value from the EBL */ -int ipc_flash_read_swid(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp) -{ - struct iosm_flash_msg_control cmd_msg; - struct iosm_swid_table *swid; - char ebl_swid[IOSM_SWID_STR]; - int ret; - - if (ipc_devlink->ebl_ctx.ebl_sw_info_version != - IOSM_EXT_CAP_SWID_OOS_PACK) - return -EINVAL; - - cmd_msg.action = cpu_to_le32(FLASH_OOSC_ACTION_READ); - cmd_msg.type = cpu_to_le32(FLASH_OOSC_TYPE_SWID_TABLE); - cmd_msg.length = cpu_to_le32(IOSM_MSG_LEN_ARG); - cmd_msg.arguments = cpu_to_le32(IOSM_MSG_LEN_ARG); - - ret = ipc_flash_send_receive(ipc_devlink, FLASH_OOS_CONTROL, - (u8 *)&cmd_msg, IOSM_MDM_SEND_16, mdm_rsp); - if (ret) - goto ipc_swid_err; - - cmd_msg.action = cpu_to_le32(*((u32 *)mdm_rsp)); - - ret = ipc_flash_send_receive(ipc_devlink, FLASH_OOS_DATA_READ, - (u8 *)&cmd_msg, IOSM_MDM_SEND_4, mdm_rsp); - if (ret) - goto ipc_swid_err; - - swid = (struct iosm_swid_table *)mdm_rsp; - dev_dbg(ipc_devlink->dev, "SWID %x RF_ENGINE_ID %x", swid->sw_id_val, - swid->rf_engine_id_val); - - snprintf(ebl_swid, sizeof(ebl_swid), "SWID: %x, RF_ENGINE_ID: %x", - swid->sw_id_val, swid->rf_engine_id_val); - - devlink_flash_update_status_notify(ipc_devlink->devlink_ctx, ebl_swid, - NULL, 0, 0); -ipc_swid_err: - return ret; -} - -/* Function to check if full erase or conditional erase was successful */ -static int ipc_flash_erase_check(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp) -{ - int ret, count = 0; - u16 mdm_rsp_data; - - /* Request Flash Erase Check */ - do { - mdm_rsp_data = IOSM_MDM_SEND_DATA; - ret = ipc_flash_send_receive(ipc_devlink, FLASH_ERASE_CHECK, - (u8 *)&mdm_rsp_data, - IOSM_MDM_SEND_2, mdm_rsp); - if (ret) - goto ipc_erase_chk_err; - - mdm_rsp_data = *((u16 *)mdm_rsp); - if (mdm_rsp_data > IOSM_MDM_ERASE_RSP) { - dev_err(ipc_devlink->dev, - "Flash Erase Check resp wrong 0x%04X", - mdm_rsp_data); - ret = -EINVAL; - goto ipc_erase_chk_err; - } - count++; - msleep(IOSM_FLASH_ERASE_CHECK_INTERVAL); - } while ((mdm_rsp_data != IOSM_MDM_ERASE_RSP) && - (count < (IOSM_FLASH_ERASE_CHECK_TIMEOUT / - IOSM_FLASH_ERASE_CHECK_INTERVAL))); - - if (mdm_rsp_data != IOSM_MDM_ERASE_RSP) { - dev_err(ipc_devlink->dev, "Modem erase check timeout failure!"); - ret = -ETIMEDOUT; - } - -ipc_erase_chk_err: - return ret; -} - -/* Full erase function which will erase the nand flash through EBL command */ -static int ipc_flash_full_erase(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp) -{ - u32 erase_address = IOSM_ERASE_START_ADDR; - struct iosm_flash_msg_control cmd_msg; - u32 erase_length = IOSM_ERASE_LEN; - int ret; - - dev_dbg(ipc_devlink->dev, "Erase full nand flash"); - cmd_msg.action = cpu_to_le32(FLASH_OOSC_ACTION_ERASE); - cmd_msg.type = cpu_to_le32(FLASH_OOSC_TYPE_ALL_FLASH); - cmd_msg.length = cpu_to_le32(erase_length); - cmd_msg.arguments = cpu_to_le32(erase_address); - - ret = ipc_flash_send_receive(ipc_devlink, FLASH_OOS_CONTROL, - (unsigned char *)&cmd_msg, - IOSM_MDM_SEND_16, mdm_rsp); - if (ret) - goto ipc_flash_erase_err; - - ipc_devlink->param.erase_full_flash_done = IOSM_SET_FLAG; - ret = ipc_flash_erase_check(ipc_devlink, mdm_rsp); - -ipc_flash_erase_err: - return ret; -} - -/* Logic for flashing all the Loadmaps available for individual fls file */ -static int ipc_flash_download_region(struct iosm_devlink *ipc_devlink, - const struct firmware *fw, u8 *mdm_rsp) -{ - __le32 reg_info[2]; /* 0th position region address, 1st position size */ - char *file_ptr; - u32 rest_len; - u32 raw_len; - int ret; - - file_ptr = (char *)fw->data; - reg_info[0] = cpu_to_le32(ipc_devlink->param.address); - - if (!ipc_devlink->param.erase_full_flash_done) { - reg_info[1] = cpu_to_le32(ipc_devlink->param.address + - fw->size - 2); - ret = ipc_flash_send_receive(ipc_devlink, FLASH_ERASE_START, - (u8 *)reg_info, IOSM_MDM_SEND_8, - mdm_rsp); - if (ret) - goto dl_region_fail; - - ret = ipc_flash_erase_check(ipc_devlink, mdm_rsp); - if (ret) - goto dl_region_fail; - } - - /* Request Flash Set Address */ - ret = ipc_flash_send_receive(ipc_devlink, FLASH_SET_ADDRESS, - (u8 *)reg_info, IOSM_MDM_SEND_4, mdm_rsp); - if (ret) - goto dl_region_fail; - - rest_len = fw->size; - - /* Request Flash Write Raw Image */ - ret = ipc_flash_send_data(ipc_devlink, IOSM_EBL_DW_PACK_SIZE, - FLASH_WRITE_IMAGE_RAW, (u8 *)&rest_len, - IOSM_MDM_SEND_4); - if (ret) - goto dl_region_fail; - - do { - raw_len = (rest_len > IOSM_FLS_BUF_SIZE) ? IOSM_FLS_BUF_SIZE : - rest_len; - ret = ipc_imem_sys_devlink_write(ipc_devlink, file_ptr, - raw_len); - if (ret) { - dev_err(ipc_devlink->dev, "Image write failed"); - goto dl_region_fail; - } - file_ptr += raw_len; - rest_len -= raw_len; - } while (rest_len); - - ret = ipc_flash_receive_data(ipc_devlink, IOSM_EBL_DW_PAYL_SIZE, - mdm_rsp); - -dl_region_fail: - return ret; -} - -/* Flash the individual fls files */ -int ipc_flash_send_fls(struct iosm_devlink *ipc_devlink, - const struct firmware *fw, u8 *mdm_rsp) -{ - u16 flash_cmd; - int ret; - - if (ipc_devlink->param.erase_full_flash) { - ipc_devlink->param.erase_full_flash = false; - ret = ipc_flash_full_erase(ipc_devlink, mdm_rsp); - if (ret) - goto ipc_flash_err; - } - - /* Request Sec Start */ - if (!ipc_devlink->param.download_region) { - ret = ipc_flash_send_receive(ipc_devlink, FLASH_SEC_START, - (u8 *)fw->data, fw->size, mdm_rsp); - if (ret) - goto ipc_flash_err; - } else { - /* Download regions */ - ipc_devlink->param.region_count -= IOSM_SET_FLAG; - ret = ipc_flash_download_region(ipc_devlink, fw, mdm_rsp); - if (ret) - goto ipc_flash_err; - - if (!ipc_devlink->param.region_count) { - /* Request Sec End */ - flash_cmd = IOSM_MDM_SEND_DATA; - ret = ipc_flash_send_receive(ipc_devlink, FLASH_SEC_END, - (u8 *)&flash_cmd, - IOSM_MDM_SEND_2, mdm_rsp); - } - } - -ipc_flash_err: - return ret; -} - -/* Inject RPSI */ -int ipc_flash_boot_psi(struct iosm_devlink *ipc_devlink, - const struct firmware *fw) -{ - u8 psi_ack_byte[IOSM_PSI_ACK], read_data[2]; - u32 bytes_read; - u8 *psi_code; - int ret; - - dev_dbg(ipc_devlink->dev, "Boot transfer PSI"); - psi_code = kzalloc(fw->size, GFP_KERNEL); - if (!psi_code) - return -ENOMEM; - - memcpy(psi_code, fw->data, fw->size); - ret = ipc_imem_sys_devlink_write(ipc_devlink, psi_code, fw->size); - if (ret) { - dev_err(ipc_devlink->dev, "RPSI Image write failed"); - goto ipc_flash_psi_free; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, - IOSM_LER_ACK_SIZE, &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "ipc_devlink_sio_read ACK failed"); - goto ipc_flash_psi_free; - } - - if (bytes_read != IOSM_LER_ACK_SIZE) { - ret = -EINVAL; - goto ipc_flash_psi_free; - } - - snprintf(psi_ack_byte, sizeof(psi_ack_byte), "%x%x", read_data[0], - read_data[1]); - devlink_flash_update_status_notify(ipc_devlink->devlink_ctx, - psi_ack_byte, "PSI ACK", 0, 0); - - if (read_data[0] == 0x00 && read_data[1] == 0xCD) { - dev_dbg(ipc_devlink->dev, "Coredump detected"); - ret = ipc_coredump_get_list(ipc_devlink, - rpsi_cmd_coredump_start); - if (ret) - dev_err(ipc_devlink->dev, "Failed to get cd list"); - } - -ipc_flash_psi_free: - kfree(psi_code); - return ret; -} - -/* Inject EBL */ -int ipc_flash_boot_ebl(struct iosm_devlink *ipc_devlink, - const struct firmware *fw) -{ - u32 ebl_size = fw->size; - u8 read_data[2]; - u32 bytes_read; - int ret; - - if (ipc_mmio_get_exec_stage(ipc_devlink->pcie->imem->mmio) != - IPC_MEM_EXEC_STAGE_PSI) { - devlink_flash_update_status_notify(ipc_devlink->devlink_ctx, - "Invalid execution stage", - NULL, 0, 0); - return -EINVAL; - } - - dev_dbg(ipc_devlink->dev, "Boot transfer EBL"); - ret = ipc_devlink_send_cmd(ipc_devlink, rpsi_cmd_code_ebl, - IOSM_RPSI_LOAD_SIZE); - if (ret) { - dev_err(ipc_devlink->dev, "Sending rpsi_cmd_code_ebl failed"); - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE, - &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "rpsi_cmd_code_ebl read failed"); - goto ipc_flash_ebl_err; - } - - if (bytes_read != IOSM_READ_SIZE) { - ret = -EINVAL; - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&ebl_size, - sizeof(ebl_size)); - if (ret) { - dev_err(ipc_devlink->dev, "EBL length write failed"); - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE, - &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL read failed"); - goto ipc_flash_ebl_err; - } - - if (bytes_read != IOSM_READ_SIZE) { - ret = -EINVAL; - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_write(ipc_devlink, (unsigned char *)fw->data, - fw->size); - if (ret) { - dev_err(ipc_devlink->dev, "EBL data transfer failed"); - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE, - &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL read failed"); - goto ipc_flash_ebl_err; - } - - if (bytes_read != IOSM_READ_SIZE) { - ret = -EINVAL; - goto ipc_flash_ebl_err; - } - - ret = ipc_imem_sys_devlink_read(ipc_devlink, - ipc_devlink->ebl_ctx.m_ebl_resp, - IOSM_EBL_RSP_SIZE, &bytes_read); - if (ret) { - dev_err(ipc_devlink->dev, "EBL response read failed"); - goto ipc_flash_ebl_err; - } - - if (bytes_read != IOSM_EBL_RSP_SIZE) - ret = -EINVAL; - -ipc_flash_ebl_err: - return ret; -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_flash.h b/drivers/net/wwan/iosm/iosm_ipc_flash.h deleted file mode 100644 index aee848927228..000000000000 --- a/drivers/net/wwan/iosm/iosm_ipc_flash.h +++ /dev/null @@ -1,271 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only - * - * Copyright (C) 2020-2021 Intel Corporation. - */ - -#ifndef _IOSM_IPC_FLASH_H -#define _IOSM_IPC_FLASH_H - -/* Buffer size used to read the fls image */ -#define IOSM_FLS_BUF_SIZE 0x00100000 -/* Full erase start address */ -#define IOSM_ERASE_START_ADDR 0x00000000 -/* Erase length for NAND flash */ -#define IOSM_ERASE_LEN 0xFFFFFFFF -/* EBL response Header size */ -#define IOSM_EBL_HEAD_SIZE 8 -/* EBL payload size */ -#define IOSM_EBL_W_PAYL_SIZE 2048 -/* Total EBL pack size */ -#define IOSM_EBL_W_PACK_SIZE (IOSM_EBL_HEAD_SIZE + IOSM_EBL_W_PAYL_SIZE) -/* EBL payload size */ -#define IOSM_EBL_DW_PAYL_SIZE 16384 -/* Total EBL pack size */ -#define IOSM_EBL_DW_PACK_SIZE (IOSM_EBL_HEAD_SIZE + IOSM_EBL_DW_PAYL_SIZE) -/* EBL name size */ -#define IOSM_EBL_NAME 32 -/* Maximum supported error types */ -#define IOSM_MAX_ERRORS 8 -/* Read size for RPSI/EBL response */ -#define IOSM_READ_SIZE 2 -/* Link establishment response ack size */ -#define IOSM_LER_ACK_SIZE 2 -/* PSI ACK len */ -#define IOSM_PSI_ACK 8 -/* SWID capability for packed swid type */ -#define IOSM_EXT_CAP_SWID_OOS_PACK 0x02 -/* EBL error response buffer */ -#define IOSM_EBL_RSP_BUFF 0x0041 -/* SWID string length */ -#define IOSM_SWID_STR 64 -/* Load EBL command size */ -#define IOSM_RPSI_LOAD_SIZE 0 -/* EBL payload checksum */ -#define IOSM_EBL_CKSM 0x0000FFFF -/* SWID msg len and argument */ -#define IOSM_MSG_LEN_ARG 0 -/* Data to be sent to modem */ -#define IOSM_MDM_SEND_DATA 0x0000 -/* Data received from modem as part of erase check */ -#define IOSM_MDM_ERASE_RSP 0x0001 -/* Bit shift to calculate Checksum */ -#define IOSM_EBL_PAYL_SHIFT 16 -/* Flag To be set */ -#define IOSM_SET_FLAG 1 -/* Set flash erase check timeout to 100 msec */ -#define IOSM_FLASH_ERASE_CHECK_TIMEOUT 100 -/* Set flash erase check interval to 20 msec */ -#define IOSM_FLASH_ERASE_CHECK_INTERVAL 20 -/* Link establishment response ack size */ -#define IOSM_LER_RSP_SIZE 60 - -/** - * enum iosm_flash_package_type - Enum for the flashing operations - * @FLASH_SET_PROT_CONF: Write EBL capabilities - * @FLASH_SEC_START: Start writing the secpack - * @FLASH_SEC_END: Validate secpack end - * @FLASH_SET_ADDRESS: Set the address for flashing - * @FLASH_ERASE_START: Start erase before flashing - * @FLASH_ERASE_CHECK: Validate the erase functionality - * @FLASH_OOS_CONTROL: Retrieve data based on oos actions - * @FLASH_OOS_DATA_READ: Read data from EBL - * @FLASH_WRITE_IMAGE_RAW: Write the raw image to flash - */ -enum iosm_flash_package_type { - FLASH_SET_PROT_CONF = 0x0086, - FLASH_SEC_START = 0x0204, - FLASH_SEC_END, - FLASH_SET_ADDRESS = 0x0802, - FLASH_ERASE_START = 0x0805, - FLASH_ERASE_CHECK, - FLASH_OOS_CONTROL = 0x080C, - FLASH_OOS_DATA_READ = 0x080E, - FLASH_WRITE_IMAGE_RAW, -}; - -/** - * enum iosm_out_of_session_action - Actions possible over the - * OutOfSession command interface - * @FLASH_OOSC_ACTION_READ: Read data according to its type - * @FLASH_OOSC_ACTION_ERASE: Erase data according to its type - */ -enum iosm_out_of_session_action { - FLASH_OOSC_ACTION_READ = 2, - FLASH_OOSC_ACTION_ERASE = 3, -}; - -/** - * enum iosm_out_of_session_type - Data types that can be handled over the - * Out Of Session command Interface - * @FLASH_OOSC_TYPE_ALL_FLASH: The whole flash area - * @FLASH_OOSC_TYPE_SWID_TABLE: Read the swid table from the target - */ -enum iosm_out_of_session_type { - FLASH_OOSC_TYPE_ALL_FLASH = 8, - FLASH_OOSC_TYPE_SWID_TABLE = 16, -}; - -/** - * enum iosm_ebl_caps - EBL capability settings - * @IOSM_CAP_NOT_ENHANCED: If capability not supported - * @IOSM_CAP_USE_EXT_CAP: To be set if extended capability is set - * @IOSM_EXT_CAP_ERASE_ALL: Set Erase all capability - * @IOSM_EXT_CAP_COMMIT_ALL: Set the commit all capability - */ -enum iosm_ebl_caps { - IOSM_CAP_NOT_ENHANCED = 0x00, - IOSM_CAP_USE_EXT_CAP = 0x01, - IOSM_EXT_CAP_ERASE_ALL = 0x08, - IOSM_EXT_CAP_COMMIT_ALL = 0x20, -}; - -/** - * enum iosm_ebl_rsp - EBL response field - * @EBL_CAPS_FLAG: EBL capability flag - * @EBL_SKIP_ERASE: EBL skip erase flag - * @EBL_SKIP_CRC: EBL skip wr_pack crc - * @EBL_EXT_CAPS_HANDLED: EBL extended capability handled flag - * @EBL_OOS_CONFIG: EBL oos configuration - * @EBL_RSP_SW_INFO_VER: EBL SW info version - */ -enum iosm_ebl_rsp { - EBL_CAPS_FLAG = 50, - EBL_SKIP_ERASE = 54, - EBL_SKIP_CRC = 55, - EBL_EXT_CAPS_HANDLED = 57, - EBL_OOS_CONFIG = 64, - EBL_RSP_SW_INFO_VER = 70, -}; - -/** - * enum iosm_mdm_send_recv_data - Data to send to modem - * @IOSM_MDM_SEND_2: Send 2 bytes of payload - * @IOSM_MDM_SEND_4: Send 4 bytes of payload - * @IOSM_MDM_SEND_8: Send 8 bytes of payload - * @IOSM_MDM_SEND_16: Send 16 bytes of payload - */ -enum iosm_mdm_send_recv_data { - IOSM_MDM_SEND_2 = 2, - IOSM_MDM_SEND_4 = 4, - IOSM_MDM_SEND_8 = 8, - IOSM_MDM_SEND_16 = 16, -}; - -/** - * struct iosm_ebl_one_error - Structure containing error details - * @error_class: Error type- standard, security and text error - * @error_code: Specific error from error type - */ -struct iosm_ebl_one_error { - u16 error_class; - u16 error_code; -}; - -/** - * struct iosm_ebl_error- Structure with max error type supported - * @error: Array of one_error structure with max errors - */ -struct iosm_ebl_error { - struct iosm_ebl_one_error error[IOSM_MAX_ERRORS]; -}; - -/** - * struct iosm_swid_table - SWID table data for modem - * @number_of_data_sets: Number of swid types - * @sw_id_type: SWID type - SWID - * @sw_id_val: SWID value - * @rf_engine_id_type: RF engine ID type - RF_ENGINE_ID - * @rf_engine_id_val: RF engine ID value - */ -struct iosm_swid_table { - u32 number_of_data_sets; - char sw_id_type[IOSM_EBL_NAME]; - u32 sw_id_val; - char rf_engine_id_type[IOSM_EBL_NAME]; - u32 rf_engine_id_val; -}; - -/** - * struct iosm_flash_msg_control - Data sent to modem - * @action: Action to be performed - * @type: Type of action - * @length: Length of the action - * @arguments: Argument value sent to modem - */ -struct iosm_flash_msg_control { - __le32 action; - __le32 type; - __le32 length; - __le32 arguments; -}; - -/** - * struct iosm_flash_data - Header Data to be sent to modem - * @checksum: Checksum value calculated for the payload data - * @pack_id: Flash Action type - * @msg_length: Payload length - */ -struct iosm_flash_data { - __le16 checksum; - __le16 pack_id; - __le32 msg_length; -}; - -/** - * ipc_flash_boot_psi - Inject PSI image - * @ipc_devlink: Pointer to devlink structure - * @fw: FW image - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_boot_psi(struct iosm_devlink *ipc_devlink, - const struct firmware *fw); - -/** - * ipc_flash_boot_ebl - Inject EBL image - * @ipc_devlink: Pointer to devlink structure - * @fw: FW image - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_boot_ebl(struct iosm_devlink *ipc_devlink, - const struct firmware *fw); - -/** - * ipc_flash_boot_set_capabilities - Set modem bool capabilities in flash - * @ipc_devlink: Pointer to devlink structure - * @mdm_rsp: Pointer to modem response buffer - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_boot_set_capabilities(struct iosm_devlink *ipc_devlink, - u8 *mdm_rsp); - -/** - * ipc_flash_link_establish - Flash link establishment - * @ipc_imem: Pointer to struct iosm_imem - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_link_establish(struct iosm_imem *ipc_imem); - -/** - * ipc_flash_read_swid - Get swid during flash phase - * @ipc_devlink: Pointer to devlink structure - * @mdm_rsp: Pointer to modem response buffer - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_read_swid(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp); - -/** - * ipc_flash_send_fls - Inject Modem subsystem fls file to device - * @ipc_devlink: Pointer to devlink structure - * @fw: FW image - * @mdm_rsp: Pointer to modem response buffer - * - * Returns: 0 on success and failure value on error - */ -int ipc_flash_send_fls(struct iosm_devlink *ipc_devlink, - const struct firmware *fw, u8 *mdm_rsp); -#endif diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.c b/drivers/net/wwan/iosm/iosm_ipc_imem.c index 1cf49e9959f4..9f00e36b7f79 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c @@ -6,8 +6,6 @@ #include #include "iosm_ipc_chnl_cfg.h" -#include "iosm_ipc_devlink.h" -#include "iosm_ipc_flash.h" #include "iosm_ipc_imem.h" #include "iosm_ipc_port.h" @@ -265,12 +263,9 @@ static void ipc_imem_dl_skb_process(struct iosm_imem *ipc_imem, switch (pipe->channel->ctype) { case IPC_CTYPE_CTRL: port_id = pipe->channel->channel_id; - if (port_id == IPC_MEM_CTRL_CHL_ID_7) - ipc_imem_sys_devlink_notify_rx(ipc_imem->ipc_devlink, - skb); - else - wwan_port_rx(ipc_imem->ipc_port[port_id]->iosm_port, - skb); + + /* Pass the packet to the wwan layer. */ + wwan_port_rx(ipc_imem->ipc_port[port_id]->iosm_port, skb); break; case IPC_CTYPE_WWAN: @@ -404,8 +399,19 @@ static void ipc_imem_rom_irq_exec(struct iosm_imem *ipc_imem) { struct ipc_mem_channel *channel; - channel = ipc_imem->ipc_devlink->devlink_sio.channel; + if (ipc_imem->flash_channel_id < 0) { + ipc_imem->rom_exit_code = IMEM_ROM_EXIT_FAIL; + dev_err(ipc_imem->dev, "Missing flash app:%d", + ipc_imem->flash_channel_id); + return; + } + ipc_imem->rom_exit_code = ipc_mmio_get_rom_exit_code(ipc_imem->mmio); + + /* Wake up the flash app to continue or to terminate depending + * on the CP ROM exit code. + */ + channel = &ipc_imem->channels[ipc_imem->flash_channel_id]; complete(&channel->ul_sem); } @@ -566,7 +572,7 @@ static void ipc_imem_handle_irq(struct iosm_imem *ipc_imem, int irq) enum ipc_phase old_phase, phase; bool retry_allocation = false; bool ul_pending = false; - int i; + int ch_id, i; if (irq != IMEM_IRQ_DONT_CARE) ipc_imem->ev_irq_pending[irq] = false; @@ -690,8 +696,11 @@ static void ipc_imem_handle_irq(struct iosm_imem *ipc_imem, int irq) if ((phase == IPC_P_PSI || phase == IPC_P_EBL) && ipc_imem->ipc_requested_state == IPC_MEM_DEVICE_IPC_RUNNING && ipc_mmio_get_ipc_state(ipc_imem->mmio) == - IPC_MEM_DEVICE_IPC_RUNNING) { - complete(&ipc_imem->ipc_devlink->devlink_sio.channel->ul_sem); + IPC_MEM_DEVICE_IPC_RUNNING && + ipc_imem->flash_channel_id >= 0) { + /* Wake up the flash app to open the pipes. */ + ch_id = ipc_imem->flash_channel_id; + complete(&ipc_imem->channels[ch_id].ul_sem); } /* Reset the expected CP state. */ @@ -1167,9 +1176,6 @@ void ipc_imem_cleanup(struct iosm_imem *ipc_imem) ipc_port_deinit(ipc_imem->ipc_port); } - if (ipc_imem->ipc_devlink) - ipc_devlink_deinit(ipc_imem->ipc_devlink); - ipc_imem_device_ipc_uninit(ipc_imem); ipc_imem_channel_reset(ipc_imem); @@ -1252,7 +1258,6 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, void __iomem *mmio, struct device *dev) { struct iosm_imem *ipc_imem = kzalloc(sizeof(*pcie->imem), GFP_KERNEL); - enum ipc_mem_exec_stage stage; if (!ipc_imem) return NULL; @@ -1267,6 +1272,9 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, ipc_imem->cp_version = 0; ipc_imem->device_sleep = IPC_HOST_SLEEP_ENTER_SLEEP; + /* Reset the flash channel id. */ + ipc_imem->flash_channel_id = -1; + /* Reset the max number of configured channels */ ipc_imem->nr_of_channels = 0; @@ -1320,21 +1328,8 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, goto imem_config_fail; } - stage = ipc_mmio_get_exec_stage(ipc_imem->mmio); - if (stage == IPC_MEM_EXEC_STAGE_BOOT) { - /* Alloc and Register devlink */ - ipc_imem->ipc_devlink = ipc_devlink_init(ipc_imem); - if (!ipc_imem->ipc_devlink) { - dev_err(ipc_imem->dev, "Devlink register failed"); - goto imem_config_fail; - } - - if (ipc_flash_link_establish(ipc_imem)) - goto devlink_channel_fail; - } return ipc_imem; -devlink_channel_fail: - ipc_devlink_deinit(ipc_imem->ipc_devlink); + imem_config_fail: hrtimer_cancel(&ipc_imem->td_alloc_timer); hrtimer_cancel(&ipc_imem->fast_update_timer); @@ -1366,51 +1361,3 @@ void ipc_imem_td_update_timer_suspend(struct iosm_imem *ipc_imem, bool suspend) { ipc_imem->td_update_timer_suspended = suspend; } - -/* Verify the CP execution state, copy the chip info, - * change the execution phase to ROM - */ -static int ipc_imem_devlink_trigger_chip_info_cb(struct iosm_imem *ipc_imem, - int arg, void *msg, - size_t msgsize) -{ - enum ipc_mem_exec_stage stage; - struct sk_buff *skb; - int rc = -EINVAL; - size_t size; - - /* Test the CP execution state. */ - stage = ipc_mmio_get_exec_stage(ipc_imem->mmio); - if (stage != IPC_MEM_EXEC_STAGE_BOOT) { - dev_err(ipc_imem->dev, - "Execution_stage: expected BOOT, received = %X", stage); - goto trigger_chip_info_fail; - } - /* Allocate a new sk buf for the chip info. */ - size = ipc_imem->mmio->chip_info_size; - if (size > IOSM_CHIP_INFO_SIZE_MAX) - goto trigger_chip_info_fail; - - skb = ipc_pcie_alloc_local_skb(ipc_imem->pcie, GFP_ATOMIC, size); - if (!skb) { - dev_err(ipc_imem->dev, "exhausted skbuf kernel DL memory"); - rc = -ENOMEM; - goto trigger_chip_info_fail; - } - /* Copy the chip info characters into the ipc_skb. */ - ipc_mmio_copy_chip_info(ipc_imem->mmio, skb_put(skb, size), size); - /* First change to the ROM boot phase. */ - dev_dbg(ipc_imem->dev, "execution_stage[%X] eq. BOOT", stage); - ipc_imem->phase = ipc_imem_phase_update(ipc_imem); - ipc_imem_sys_devlink_notify_rx(ipc_imem->ipc_devlink, skb); - rc = 0; -trigger_chip_info_fail: - return rc; -} - -int ipc_imem_devlink_trigger_chip_info(struct iosm_imem *ipc_imem) -{ - return ipc_task_queue_send_task(ipc_imem, - ipc_imem_devlink_trigger_chip_info_cb, - 0, NULL, 0, true); -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h index 6be6708b4eec..dc65b0712261 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h @@ -69,7 +69,7 @@ struct ipc_chnl_cfg; #define IMEM_IRQ_DONT_CARE (-1) -#define IPC_MEM_MAX_CHANNELS 8 +#define IPC_MEM_MAX_CHANNELS 7 #define IPC_MEM_MUX_IP_SESSION_ENTRIES 8 @@ -98,7 +98,6 @@ struct ipc_chnl_cfg; #define IPC_MEM_DL_ETH_OFFSET 16 #define IPC_CB(skb) ((struct ipc_skb_cb *)((skb)->cb)) -#define IOSM_CHIP_INFO_SIZE_MAX 100 #define FULLY_FUNCTIONAL 0 @@ -305,9 +304,9 @@ enum ipc_phase { * @ipc_port: IPC PORT data structure pointer * @pcie: IPC PCIe * @dev: Pointer to device structure + * @flash_channel_id: Reserved channel id for flashing to RAM. * @ipc_requested_state: Expected IPC state on CP. * @channels: Channel list with UL/DL pipe pairs. - * @ipc_devlink: IPC Devlink data structure pointer * @ipc_status: local ipc_status * @nr_of_channels: number of configured channels * @startup_timer: startup timer for NAND support. @@ -350,9 +349,9 @@ struct iosm_imem { struct iosm_cdev *ipc_port[IPC_MEM_MAX_CHANNELS]; struct iosm_pcie *pcie; struct device *dev; + int flash_channel_id; enum ipc_mem_device_ipc_state ipc_requested_state; struct ipc_mem_channel channels[IPC_MEM_MAX_CHANNELS]; - struct iosm_devlink *ipc_devlink; u32 ipc_status; u32 nr_of_channels; struct hrtimer startup_timer; @@ -576,15 +575,4 @@ void ipc_imem_ipc_init_check(struct iosm_imem *ipc_imem); */ void ipc_imem_channel_init(struct iosm_imem *ipc_imem, enum ipc_ctype ctype, struct ipc_chnl_cfg chnl_cfg, u32 irq_moderation); - -/** - * ipc_imem_devlink_trigger_chip_info - Inform devlink that the chip - * information are available if the - * flashing to RAM interworking shall be - * executed. - * @ipc_imem: Pointer to imem structure - * - * Returns: 0 on success, -1 on failure - */ -int ipc_imem_devlink_trigger_chip_info(struct iosm_imem *ipc_imem); #endif diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c index b885a6570235..0a472ce77370 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.c @@ -6,7 +6,6 @@ #include #include "iosm_ipc_chnl_cfg.h" -#include "iosm_ipc_devlink.h" #include "iosm_ipc_imem.h" #include "iosm_ipc_imem_ops.h" #include "iosm_ipc_port.h" @@ -332,319 +331,3 @@ int ipc_imem_sys_cdev_write(struct iosm_cdev *ipc_cdev, struct sk_buff *skb) out: return ret; } - -/* Open a SIO link to CP and return the channel instance */ -struct ipc_mem_channel *ipc_imem_sys_devlink_open(struct iosm_imem *ipc_imem) -{ - struct ipc_mem_channel *channel; - enum ipc_phase phase; - int channel_id; - - phase = ipc_imem_phase_update(ipc_imem); - switch (phase) { - case IPC_P_OFF: - case IPC_P_ROM: - /* Get a channel id as flash id and reserve it. */ - channel_id = ipc_imem_channel_alloc(ipc_imem, - IPC_MEM_CTRL_CHL_ID_7, - IPC_CTYPE_CTRL); - - if (channel_id < 0) { - dev_err(ipc_imem->dev, - "reservation of a flash channel id failed"); - goto error; - } - - ipc_imem->ipc_devlink->devlink_sio.channel_id = channel_id; - channel = &ipc_imem->channels[channel_id]; - - /* Enqueue chip info data to be read */ - if (ipc_imem_devlink_trigger_chip_info(ipc_imem)) { - dev_err(ipc_imem->dev, "Enqueue of chip info failed"); - channel->state = IMEM_CHANNEL_FREE; - goto error; - } - - return channel; - - case IPC_P_PSI: - case IPC_P_EBL: - ipc_imem->cp_version = ipc_mmio_get_cp_version(ipc_imem->mmio); - if (ipc_imem->cp_version == -1) { - dev_err(ipc_imem->dev, "invalid CP version"); - goto error; - } - - channel_id = ipc_imem->ipc_devlink->devlink_sio.channel_id; - return ipc_imem_channel_open(ipc_imem, channel_id, - IPC_HP_CDEV_OPEN); - - default: - /* CP is in the wrong state (e.g. CRASH or CD_READY) */ - dev_err(ipc_imem->dev, "SIO open refused, phase %d", phase); - } -error: - return NULL; -} - -/* Release a SIO channel link to CP. */ -void ipc_imem_sys_devlink_close(struct iosm_devlink *ipc_devlink) -{ - struct iosm_imem *ipc_imem = ipc_devlink->pcie->imem; - int boot_check_timeout = BOOT_CHECK_DEFAULT_TIMEOUT; - enum ipc_mem_exec_stage exec_stage; - struct ipc_mem_channel *channel; - enum ipc_phase curr_phase; - int status = 0; - u32 tail = 0; - - channel = ipc_imem->ipc_devlink->devlink_sio.channel; - curr_phase = ipc_imem->phase; - /* Increase the total wait time to boot_check_timeout */ - do { - exec_stage = ipc_mmio_get_exec_stage(ipc_imem->mmio); - if (exec_stage == IPC_MEM_EXEC_STAGE_RUN || - exec_stage == IPC_MEM_EXEC_STAGE_PSI) - break; - msleep(20); - boot_check_timeout -= 20; - } while (boot_check_timeout > 0); - - /* If there are any pending TDs then wait for Timeout/Completion before - * closing pipe. - */ - if (channel->ul_pipe.old_tail != channel->ul_pipe.old_head) { - status = wait_for_completion_interruptible_timeout - (&ipc_imem->ul_pend_sem, - msecs_to_jiffies(IPC_PEND_DATA_TIMEOUT)); - if (status == 0) { - dev_dbg(ipc_imem->dev, - "Data Timeout on UL-Pipe:%d Head:%d Tail:%d", - channel->ul_pipe.pipe_nr, - channel->ul_pipe.old_head, - channel->ul_pipe.old_tail); - } - } - - ipc_protocol_get_head_tail_index(ipc_imem->ipc_protocol, - &channel->dl_pipe, NULL, &tail); - - if (tail != channel->dl_pipe.old_tail) { - status = wait_for_completion_interruptible_timeout - (&ipc_imem->dl_pend_sem, - msecs_to_jiffies(IPC_PEND_DATA_TIMEOUT)); - if (status == 0) { - dev_dbg(ipc_imem->dev, - "Data Timeout on DL-Pipe:%d Head:%d Tail:%d", - channel->dl_pipe.pipe_nr, - channel->dl_pipe.old_head, - channel->dl_pipe.old_tail); - } - } - - /* Due to wait for completion in messages, there is a small window - * between closing the pipe and updating the channel is closed. In this - * small window there could be HP update from Host Driver. Hence update - * the channel state as CLOSING to aviod unnecessary interrupt - * towards CP. - */ - channel->state = IMEM_CHANNEL_CLOSING; - /* Release the pipe resources */ - ipc_imem_pipe_cleanup(ipc_imem, &channel->ul_pipe); - ipc_imem_pipe_cleanup(ipc_imem, &channel->dl_pipe); -} - -void ipc_imem_sys_devlink_notify_rx(struct iosm_devlink *ipc_devlink, - struct sk_buff *skb) -{ - skb_queue_tail(&ipc_devlink->devlink_sio.rx_list, skb); - complete(&ipc_devlink->devlink_sio.read_sem); -} - -/* PSI transfer */ -static int ipc_imem_sys_psi_transfer(struct iosm_imem *ipc_imem, - struct ipc_mem_channel *channel, - unsigned char *buf, int count) -{ - int psi_start_timeout = PSI_START_DEFAULT_TIMEOUT; - enum ipc_mem_exec_stage exec_stage; - - dma_addr_t mapping = 0; - int ret; - - ret = ipc_pcie_addr_map(ipc_imem->pcie, buf, count, &mapping, - DMA_TO_DEVICE); - if (ret) - goto pcie_addr_map_fail; - - /* Save the PSI information for the CP ROM driver on the doorbell - * scratchpad. - */ - ipc_mmio_set_psi_addr_and_size(ipc_imem->mmio, mapping, count); - ipc_doorbell_fire(ipc_imem->pcie, 0, IPC_MEM_EXEC_STAGE_BOOT); - - ret = wait_for_completion_interruptible_timeout - (&channel->ul_sem, - msecs_to_jiffies(IPC_PSI_TRANSFER_TIMEOUT)); - - if (ret <= 0) { - dev_err(ipc_imem->dev, "Failed PSI transfer to CP, Error-%d", - ret); - goto psi_transfer_fail; - } - /* If the PSI download fails, return the CP boot ROM exit code */ - if (ipc_imem->rom_exit_code != IMEM_ROM_EXIT_OPEN_EXT && - ipc_imem->rom_exit_code != IMEM_ROM_EXIT_CERT_EXT) { - ret = (-1) * ((int)ipc_imem->rom_exit_code); - goto psi_transfer_fail; - } - - dev_dbg(ipc_imem->dev, "PSI image successfully downloaded"); - - /* Wait psi_start_timeout milliseconds until the CP PSI image is - * running and updates the execution_stage field with - * IPC_MEM_EXEC_STAGE_PSI. Verify the execution stage. - */ - do { - exec_stage = ipc_mmio_get_exec_stage(ipc_imem->mmio); - - if (exec_stage == IPC_MEM_EXEC_STAGE_PSI) - break; - - msleep(20); - psi_start_timeout -= 20; - } while (psi_start_timeout > 0); - - if (exec_stage != IPC_MEM_EXEC_STAGE_PSI) - goto psi_transfer_fail; /* Unknown status of CP PSI process. */ - - ipc_imem->phase = IPC_P_PSI; - - /* Enter the PSI phase. */ - dev_dbg(ipc_imem->dev, "execution_stage[%X] eq. PSI", exec_stage); - - /* Request the RUNNING state from CP and wait until it was reached - * or timeout. - */ - ipc_imem_ipc_init_check(ipc_imem); - - ret = wait_for_completion_interruptible_timeout - (&channel->ul_sem, msecs_to_jiffies(IPC_PSI_TRANSFER_TIMEOUT)); - if (ret <= 0) { - dev_err(ipc_imem->dev, - "Failed PSI RUNNING state on CP, Error-%d", ret); - goto psi_transfer_fail; - } - - if (ipc_mmio_get_ipc_state(ipc_imem->mmio) != - IPC_MEM_DEVICE_IPC_RUNNING) { - dev_err(ipc_imem->dev, - "ch[%d] %s: unexpected CP IPC state %d, not RUNNING", - channel->channel_id, - ipc_imem_phase_get_string(ipc_imem->phase), - ipc_mmio_get_ipc_state(ipc_imem->mmio)); - - goto psi_transfer_fail; - } - - /* Create the flash channel for the transfer of the images. */ - if (!ipc_imem_sys_devlink_open(ipc_imem)) { - dev_err(ipc_imem->dev, "can't open flash_channel"); - goto psi_transfer_fail; - } - - ret = 0; -psi_transfer_fail: - ipc_pcie_addr_unmap(ipc_imem->pcie, count, mapping, DMA_TO_DEVICE); -pcie_addr_map_fail: - return ret; -} - -int ipc_imem_sys_devlink_write(struct iosm_devlink *ipc_devlink, - unsigned char *buf, int count) -{ - struct iosm_imem *ipc_imem = ipc_devlink->pcie->imem; - struct ipc_mem_channel *channel; - struct sk_buff *skb; - dma_addr_t mapping; - int ret; - - channel = ipc_imem->ipc_devlink->devlink_sio.channel; - - /* In the ROM phase the PSI image is passed to CP about a specific - * shared memory area and doorbell scratchpad directly. - */ - if (ipc_imem->phase == IPC_P_ROM) { - ret = ipc_imem_sys_psi_transfer(ipc_imem, channel, buf, count); - /* If the PSI transfer fails then send crash - * Signature. - */ - if (ret > 0) - ipc_imem_msg_send_feature_set(ipc_imem, - IPC_MEM_INBAND_CRASH_SIG, - false); - goto out; - } - - /* Allocate skb memory for the uplink buffer. */ - skb = ipc_pcie_alloc_skb(ipc_devlink->pcie, count, GFP_KERNEL, &mapping, - DMA_TO_DEVICE, 0); - if (!skb) { - ret = -ENOMEM; - goto out; - } - - memcpy(skb_put(skb, count), buf, count); - - IPC_CB(skb)->op_type = UL_USR_OP_BLOCKED; - - /* Add skb to the uplink skbuf accumulator. */ - skb_queue_tail(&channel->ul_list, skb); - - /* Inform the IPC tasklet to pass uplink IP packets to CP. */ - if (!ipc_imem_call_cdev_write(ipc_imem)) { - ret = wait_for_completion_interruptible(&channel->ul_sem); - - if (ret < 0) { - dev_err(ipc_imem->dev, - "ch[%d] no CP confirmation, status = %d", - channel->channel_id, ret); - ipc_pcie_kfree_skb(ipc_devlink->pcie, skb); - goto out; - } - } - ret = 0; -out: - return ret; -} - -int ipc_imem_sys_devlink_read(struct iosm_devlink *devlink, u8 *data, - u32 bytes_to_read, u32 *bytes_read) -{ - struct sk_buff *skb = NULL; - int rc = 0; - - /* check skb is available in rx_list or wait for skb */ - devlink->devlink_sio.devlink_read_pend = 1; - while (!skb && !(skb = skb_dequeue(&devlink->devlink_sio.rx_list))) { - if (!wait_for_completion_interruptible_timeout - (&devlink->devlink_sio.read_sem, - msecs_to_jiffies(IPC_READ_TIMEOUT))) { - dev_err(devlink->dev, "Read timedout"); - rc = -ETIMEDOUT; - goto devlink_read_fail; - } - } - devlink->devlink_sio.devlink_read_pend = 0; - if (bytes_to_read < skb->len) { - dev_err(devlink->dev, "Invalid size,expected len %d", skb->len); - rc = -EINVAL; - goto devlink_read_fail; - } - *bytes_read = skb->len; - memcpy(data, skb->data, skb->len); - -devlink_read_fail: - ipc_pcie_kfree_skb(devlink->pcie, skb); - return rc; -} diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h index f0c88ac5643c..2007fe23e9a5 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem_ops.h @@ -9,7 +9,7 @@ #include "iosm_ipc_mux_codec.h" /* Maximum wait time for blocking read */ -#define IPC_READ_TIMEOUT 3000 +#define IPC_READ_TIMEOUT 500 /* The delay in ms for defering the unregister */ #define SIO_UNREGISTER_DEFER_DELAY_MS 1 @@ -98,51 +98,4 @@ int ipc_imem_sys_wwan_transmit(struct iosm_imem *ipc_imem, int if_id, */ void ipc_imem_wwan_channel_init(struct iosm_imem *ipc_imem, enum ipc_mux_protocol mux_type); - -/** - * ipc_imem_sys_devlink_open - Open a Flash/CD Channel link to CP - * @ipc_imem: iosm_imem instance - * - * Return: channel instance on success, NULL for failure - */ -struct ipc_mem_channel *ipc_imem_sys_devlink_open(struct iosm_imem *ipc_imem); - -/** - * ipc_imem_sys_devlink_close - Release a Flash/CD channel link to CP - * @ipc_devlink: Pointer to ipc_devlink data-struct - * - */ -void ipc_imem_sys_devlink_close(struct iosm_devlink *ipc_devlink); - -/** - * ipc_imem_sys_devlink_notify_rx - Receive downlink characters from CP, - * the downlink skbuf is added at the end of the - * downlink or rx list - * @ipc_devlink: Pointer to ipc_devlink data-struct - * @skb: Pointer to sk buffer - */ -void ipc_imem_sys_devlink_notify_rx(struct iosm_devlink *ipc_devlink, - struct sk_buff *skb); - -/** - * ipc_imem_sys_devlink_read - Copy the rx data and free the skbuf - * @ipc_devlink: Devlink instance - * @data: Buffer to read the data from modem - * @bytes_to_read: Size of destination buffer - * @bytes_read: Number of bytes read - * - * Return: 0 on success and failure value on error - */ -int ipc_imem_sys_devlink_read(struct iosm_devlink *ipc_devlink, u8 *data, - u32 bytes_to_read, u32 *bytes_read); - -/** - * ipc_imem_sys_devlink_write - Route the uplink buffer to CP - * @ipc_devlink: Devlink_sio instance - * @buf: Pointer to buffer - * @count: Number of data bytes to write - * Return: 0 on success and failure value on error - */ -int ipc_imem_sys_devlink_write(struct iosm_devlink *ipc_devlink, - unsigned char *buf, int count); #endif