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