Loading drivers/net/wwan/iosm/iosm_ipc_coredump.c 0 → 100644 +110 −0 Original line number Diff line number Diff line // 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; } drivers/net/wwan/iosm/iosm_ipc_coredump.h 0 → 100644 +75 −0 Original line number Diff line number Diff line /* 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
drivers/net/wwan/iosm/iosm_ipc_coredump.c 0 → 100644 +110 −0 Original line number Diff line number Diff line // 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; }
drivers/net/wwan/iosm/iosm_ipc_coredump.h 0 → 100644 +75 −0 Original line number Diff line number Diff line /* 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_ */