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