109e7b002SM Chetan Kumar // SPDX-License-Identifier: GPL-2.0-only
209e7b002SM Chetan Kumar /*
309e7b002SM Chetan Kumar  * Copyright (C) 2020-2021 Intel Corporation.
409e7b002SM Chetan Kumar  */
5*980ec04aSM Chetan Kumar #include <linux/vmalloc.h>
609e7b002SM Chetan Kumar 
709e7b002SM Chetan Kumar #include "iosm_ipc_coredump.h"
809e7b002SM Chetan Kumar 
98bea96efSM Chetan Kumar /**
108bea96efSM Chetan Kumar  * ipc_coredump_collect - To collect coredump
118bea96efSM Chetan Kumar  * @devlink:            Pointer to devlink instance.
128bea96efSM Chetan Kumar  * @data:               Pointer to snapshot
138bea96efSM Chetan Kumar  * @entry:              ID of requested snapshot
148bea96efSM Chetan Kumar  * @region_size:        Region size
158bea96efSM Chetan Kumar  *
168bea96efSM Chetan Kumar  * Returns: 0 on success, error on failure
178bea96efSM Chetan Kumar  */
ipc_coredump_collect(struct iosm_devlink * devlink,u8 ** data,int entry,u32 region_size)1809e7b002SM Chetan Kumar int ipc_coredump_collect(struct iosm_devlink *devlink, u8 **data, int entry,
1909e7b002SM Chetan Kumar 			 u32 region_size)
2009e7b002SM Chetan Kumar {
2109e7b002SM Chetan Kumar 	int ret, bytes_to_read, bytes_read = 0, i = 0;
2209e7b002SM Chetan Kumar 	s32 remaining;
2309e7b002SM Chetan Kumar 	u8 *data_ptr;
2409e7b002SM Chetan Kumar 
2509e7b002SM Chetan Kumar 	data_ptr = vmalloc(region_size);
2609e7b002SM Chetan Kumar 	if (!data_ptr)
2709e7b002SM Chetan Kumar 		return -ENOMEM;
2809e7b002SM Chetan Kumar 
2909e7b002SM Chetan Kumar 	remaining = devlink->cd_file_info[entry].actual_size;
3009e7b002SM Chetan Kumar 	ret = ipc_devlink_send_cmd(devlink, rpsi_cmd_coredump_get, entry);
3109e7b002SM Chetan Kumar 	if (ret) {
3209e7b002SM Chetan Kumar 		dev_err(devlink->dev, "Send coredump_get cmd failed");
3309e7b002SM Chetan Kumar 		goto get_cd_fail;
3409e7b002SM Chetan Kumar 	}
3509e7b002SM Chetan Kumar 	while (remaining > 0) {
3609e7b002SM Chetan Kumar 		bytes_to_read = min(remaining, MAX_DATA_SIZE);
3709e7b002SM Chetan Kumar 		bytes_read = 0;
3809e7b002SM Chetan Kumar 		ret = ipc_imem_sys_devlink_read(devlink, data_ptr + i,
3909e7b002SM Chetan Kumar 						bytes_to_read, &bytes_read);
4009e7b002SM Chetan Kumar 		if (ret) {
4109e7b002SM Chetan Kumar 			dev_err(devlink->dev, "CD data read failed");
4209e7b002SM Chetan Kumar 			goto get_cd_fail;
4309e7b002SM Chetan Kumar 		}
4409e7b002SM Chetan Kumar 		remaining -= bytes_read;
4509e7b002SM Chetan Kumar 		i += bytes_read;
4609e7b002SM Chetan Kumar 	}
4709e7b002SM Chetan Kumar 
4809e7b002SM Chetan Kumar 	*data = data_ptr;
4909e7b002SM Chetan Kumar 
508bea96efSM Chetan Kumar 	return 0;
518bea96efSM Chetan Kumar 
5209e7b002SM Chetan Kumar get_cd_fail:
5309e7b002SM Chetan Kumar 	vfree(data_ptr);
5409e7b002SM Chetan Kumar 	return ret;
5509e7b002SM Chetan Kumar }
5609e7b002SM Chetan Kumar 
578bea96efSM Chetan Kumar /**
588bea96efSM Chetan Kumar  * ipc_coredump_get_list - Get coredump list from modem
598bea96efSM Chetan Kumar  * @devlink:         Pointer to devlink instance.
608bea96efSM Chetan Kumar  * @cmd:             RPSI command to be sent
618bea96efSM Chetan Kumar  *
628bea96efSM Chetan Kumar  * Returns: 0 on success, error on failure
638bea96efSM Chetan Kumar  */
ipc_coredump_get_list(struct iosm_devlink * devlink,u16 cmd)6409e7b002SM Chetan Kumar int ipc_coredump_get_list(struct iosm_devlink *devlink, u16 cmd)
6509e7b002SM Chetan Kumar {
6609e7b002SM Chetan Kumar 	u32 byte_read, num_entries, file_size;
6709e7b002SM Chetan Kumar 	struct iosm_cd_table *cd_table;
6809e7b002SM Chetan Kumar 	u8 size[MAX_SIZE_LEN], i;
6909e7b002SM Chetan Kumar 	char *filename;
708bea96efSM Chetan Kumar 	int ret;
7109e7b002SM Chetan Kumar 
7209e7b002SM Chetan Kumar 	cd_table = kzalloc(MAX_CD_LIST_SIZE, GFP_KERNEL);
7309e7b002SM Chetan Kumar 	if (!cd_table) {
7409e7b002SM Chetan Kumar 		ret = -ENOMEM;
7509e7b002SM Chetan Kumar 		goto  cd_init_fail;
7609e7b002SM Chetan Kumar 	}
7709e7b002SM Chetan Kumar 
7809e7b002SM Chetan Kumar 	ret = ipc_devlink_send_cmd(devlink, cmd, MAX_CD_LIST_SIZE);
7909e7b002SM Chetan Kumar 	if (ret) {
8009e7b002SM Chetan Kumar 		dev_err(devlink->dev, "rpsi_cmd_coredump_start failed");
8109e7b002SM Chetan Kumar 		goto cd_init_fail;
8209e7b002SM Chetan Kumar 	}
8309e7b002SM Chetan Kumar 
8409e7b002SM Chetan Kumar 	ret = ipc_imem_sys_devlink_read(devlink, (u8 *)cd_table,
8509e7b002SM Chetan Kumar 					MAX_CD_LIST_SIZE, &byte_read);
8609e7b002SM Chetan Kumar 	if (ret) {
8709e7b002SM Chetan Kumar 		dev_err(devlink->dev, "Coredump data is invalid");
8809e7b002SM Chetan Kumar 		goto cd_init_fail;
8909e7b002SM Chetan Kumar 	}
9009e7b002SM Chetan Kumar 
9109e7b002SM Chetan Kumar 	if (byte_read != MAX_CD_LIST_SIZE)
9209e7b002SM Chetan Kumar 		goto cd_init_fail;
9309e7b002SM Chetan Kumar 
9409e7b002SM Chetan Kumar 	if (cmd == rpsi_cmd_coredump_start) {
9509e7b002SM Chetan Kumar 		num_entries = le32_to_cpu(cd_table->list.num_entries);
9609e7b002SM Chetan Kumar 		if (num_entries == 0 || num_entries > IOSM_NOF_CD_REGION) {
9709e7b002SM Chetan Kumar 			ret = -EINVAL;
9809e7b002SM Chetan Kumar 			goto cd_init_fail;
9909e7b002SM Chetan Kumar 		}
10009e7b002SM Chetan Kumar 
10109e7b002SM Chetan Kumar 		for (i = 0; i < num_entries; i++) {
10209e7b002SM Chetan Kumar 			file_size = le32_to_cpu(cd_table->list.entry[i].size);
10309e7b002SM Chetan Kumar 			filename = cd_table->list.entry[i].filename;
10409e7b002SM Chetan Kumar 
10509e7b002SM Chetan Kumar 			if (file_size > devlink->cd_file_info[i].default_size) {
10609e7b002SM Chetan Kumar 				ret = -EINVAL;
10709e7b002SM Chetan Kumar 				goto cd_init_fail;
10809e7b002SM Chetan Kumar 			}
10909e7b002SM Chetan Kumar 
11009e7b002SM Chetan Kumar 			devlink->cd_file_info[i].actual_size = file_size;
11109e7b002SM Chetan Kumar 			dev_dbg(devlink->dev, "file: %s actual size %d",
11209e7b002SM Chetan Kumar 				filename, file_size);
11309e7b002SM Chetan Kumar 			devlink_flash_update_status_notify(devlink->devlink_ctx,
11409e7b002SM Chetan Kumar 							   filename,
11509e7b002SM Chetan Kumar 							   "FILENAME", 0, 0);
11609e7b002SM Chetan Kumar 			snprintf(size, sizeof(size), "%d", file_size);
11709e7b002SM Chetan Kumar 			devlink_flash_update_status_notify(devlink->devlink_ctx,
11809e7b002SM Chetan Kumar 							   size, "FILE SIZE",
11909e7b002SM Chetan Kumar 							   0, 0);
12009e7b002SM Chetan Kumar 		}
12109e7b002SM Chetan Kumar 	}
12209e7b002SM Chetan Kumar 
12309e7b002SM Chetan Kumar cd_init_fail:
12409e7b002SM Chetan Kumar 	kfree(cd_table);
12509e7b002SM Chetan Kumar 	return ret;
12609e7b002SM Chetan Kumar }
127