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 */
ipc_coredump_collect(struct iosm_devlink * devlink,u8 ** data,int entry,u32 region_size)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 */
ipc_coredump_get_list(struct iosm_devlink * devlink,u16 cmd)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