Skip to content

Commit

Permalink
net: wwan: iosm: firmware flashing and coredump collection
Browse files Browse the repository at this point in the history
This patch brings-in support for M.2 7560 Device firmware flashing &
coredump collection using devlink.
- Driver Registers with Devlink framework.
- Register devlink params callback for configuring device params
  required in flashing or coredump flow.
- Implements devlink ops flash_update callback that programs modem
  firmware.
- Creates region & snapshot required for device coredump log collection.

On early detection of device in boot rom stage. Driver registers with
Devlink framework and establish transport channel for PSI (Primary Signed
Image) injection. Once PSI is injected to device, the device execution
stage details are read to determine whether device is in flash or
exception mode. The collected information is reported to devlink user
space application & based on this informationi, application proceeds with
either modem firmware flashing or coredump collection.

Signed-off-by: M Chetan Kumar <m.chetan.kumar@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
M Chetan Kumar authored and David S. Miller committed Sep 13, 2021
1 parent 08c53ae commit 13bb842
Show file tree
Hide file tree
Showing 14 changed files with 2,055 additions and 31 deletions.
1 change: 1 addition & 0 deletions drivers/net/wwan/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ 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.

Expand Down
5 changes: 4 additions & 1 deletion drivers/net/wwan/iosm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ iosm-y = \
iosm_ipc_protocol.o \
iosm_ipc_protocol_ops.o \
iosm_ipc_mux.o \
iosm_ipc_mux_codec.o
iosm_ipc_mux_codec.o \
iosm_ipc_devlink.o \
iosm_ipc_flash.o \
iosm_ipc_coredump.o

obj-$(CONFIG_IOSM) := iosm.o
6 changes: 5 additions & 1 deletion drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "iosm_ipc_chnl_cfg.h"

/* Max. sizes of a downlink buffers */
#define IPC_MEM_MAX_DL_FLASH_BUF_SIZE (16 * 1024)
#define IPC_MEM_MAX_DL_FLASH_BUF_SIZE (64 * 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)
Expand Down Expand Up @@ -60,6 +60,10 @@ 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)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ 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,
};

/**
Expand Down
110 changes: 110 additions & 0 deletions drivers/net/wwan/iosm/iosm_ipc_coredump.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// 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;
}
75 changes: 75 additions & 0 deletions drivers/net/wwan/iosm/iosm_ipc_coredump.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* 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_ */
Loading

0 comments on commit 13bb842

Please sign in to comment.