1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2020-2021 Intel Corporation. 4 */ 5 #include <linux/vmalloc.h> 6 7 #include "iosm_ipc_coredump.h" 8 9 /** 10 * ipc_coredump_collect - To collect coredump 11 * @devlink: Pointer to devlink instance. 12 * @data: Pointer to snapshot 13 * @entry: ID of requested snapshot 14 * @region_size: Region size 15 * 16 * Returns: 0 on success, error on failure 17 */ 18 int ipc_coredump_collect(struct iosm_devlink *devlink, u8 **data, int entry, 19 u32 region_size) 20 { 21 int ret, bytes_to_read, bytes_read = 0, i = 0; 22 s32 remaining; 23 u8 *data_ptr; 24 25 data_ptr = vmalloc(region_size); 26 if (!data_ptr) 27 return -ENOMEM; 28 29 remaining = devlink->cd_file_info[entry].actual_size; 30 ret = ipc_devlink_send_cmd(devlink, rpsi_cmd_coredump_get, entry); 31 if (ret) { 32 dev_err(devlink->dev, "Send coredump_get cmd failed"); 33 goto get_cd_fail; 34 } 35 while (remaining > 0) { 36 bytes_to_read = min(remaining, MAX_DATA_SIZE); 37 bytes_read = 0; 38 ret = ipc_imem_sys_devlink_read(devlink, data_ptr + i, 39 bytes_to_read, &bytes_read); 40 if (ret) { 41 dev_err(devlink->dev, "CD data read failed"); 42 goto get_cd_fail; 43 } 44 remaining -= bytes_read; 45 i += bytes_read; 46 } 47 48 *data = data_ptr; 49 50 return 0; 51 52 get_cd_fail: 53 vfree(data_ptr); 54 return ret; 55 } 56 57 /** 58 * ipc_coredump_get_list - Get coredump list from modem 59 * @devlink: Pointer to devlink instance. 60 * @cmd: RPSI command to be sent 61 * 62 * Returns: 0 on success, error on failure 63 */ 64 int ipc_coredump_get_list(struct iosm_devlink *devlink, u16 cmd) 65 { 66 u32 byte_read, num_entries, file_size; 67 struct iosm_cd_table *cd_table; 68 u8 size[MAX_SIZE_LEN], i; 69 char *filename; 70 int ret; 71 72 cd_table = kzalloc(MAX_CD_LIST_SIZE, GFP_KERNEL); 73 if (!cd_table) { 74 ret = -ENOMEM; 75 goto cd_init_fail; 76 } 77 78 ret = ipc_devlink_send_cmd(devlink, cmd, MAX_CD_LIST_SIZE); 79 if (ret) { 80 dev_err(devlink->dev, "rpsi_cmd_coredump_start failed"); 81 goto cd_init_fail; 82 } 83 84 ret = ipc_imem_sys_devlink_read(devlink, (u8 *)cd_table, 85 MAX_CD_LIST_SIZE, &byte_read); 86 if (ret) { 87 dev_err(devlink->dev, "Coredump data is invalid"); 88 goto cd_init_fail; 89 } 90 91 if (byte_read != MAX_CD_LIST_SIZE) 92 goto cd_init_fail; 93 94 if (cmd == rpsi_cmd_coredump_start) { 95 num_entries = le32_to_cpu(cd_table->list.num_entries); 96 if (num_entries == 0 || num_entries > IOSM_NOF_CD_REGION) { 97 ret = -EINVAL; 98 goto cd_init_fail; 99 } 100 101 for (i = 0; i < num_entries; i++) { 102 file_size = le32_to_cpu(cd_table->list.entry[i].size); 103 filename = cd_table->list.entry[i].filename; 104 105 if (file_size > devlink->cd_file_info[i].default_size) { 106 ret = -EINVAL; 107 goto cd_init_fail; 108 } 109 110 devlink->cd_file_info[i].actual_size = file_size; 111 dev_dbg(devlink->dev, "file: %s actual size %d", 112 filename, file_size); 113 devlink_flash_update_status_notify(devlink->devlink_ctx, 114 filename, 115 "FILENAME", 0, 0); 116 snprintf(size, sizeof(size), "%d", file_size); 117 devlink_flash_update_status_notify(devlink->devlink_ctx, 118 size, "FILE SIZE", 119 0, 0); 120 } 121 } 122 123 cd_init_fail: 124 kfree(cd_table); 125 return ret; 126 } 127