linux/drivers/net/wwan/iosm/iosm_ipc_coredump.c
<<
>>
Prefs
   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 */
  17int 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
  51get_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 */
  63int 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
 122cd_init_fail:
 123        kfree(cd_table);
 124        return ret;
 125}
 126