1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020-2021 Intel Corporation.
6 #include "iosm_ipc_chnl_cfg.h"
7 #include "iosm_ipc_coredump.h"
8 #include "iosm_ipc_devlink.h"
9 #include "iosm_ipc_flash.h"
12 static struct iosm_coredump_file_info list[IOSM_NOF_CD_REGION] = {
13 {"report.json", REPORT_JSON_SIZE,},
14 {"coredump.fcd", COREDUMP_FCD_SIZE,},
15 {"cdd.log", CDD_LOG_SIZE,},
16 {"eeprom.bin", EEPROM_BIN_SIZE,},
17 {"bootcore_trace.bin", BOOTCORE_TRC_BIN_SIZE,},
18 {"bootcore_prev_trace.bin", BOOTCORE_PREV_TRC_BIN_SIZE,},
21 /* Get the param values for the specific param ID's */
22 static int ipc_devlink_get_param(struct devlink *dl, u32 id,
23 struct devlink_param_gset_ctx *ctx)
25 struct iosm_devlink *ipc_devlink = devlink_priv(dl);
27 if (id == IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH)
28 ctx->val.vu8 = ipc_devlink->param.erase_full_flash;
33 /* Set the param values for the specific param ID's */
34 static int ipc_devlink_set_param(struct devlink *dl, u32 id,
35 struct devlink_param_gset_ctx *ctx)
37 struct iosm_devlink *ipc_devlink = devlink_priv(dl);
39 if (id == IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH)
40 ipc_devlink->param.erase_full_flash = ctx->val.vu8;
45 /* Devlink param structure array */
46 static const struct devlink_param iosm_devlink_params[] = {
47 DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH,
48 "erase_full_flash", DEVLINK_PARAM_TYPE_BOOL,
49 BIT(DEVLINK_PARAM_CMODE_RUNTIME),
50 ipc_devlink_get_param, ipc_devlink_set_param,
54 /* Get devlink flash component type */
55 static enum iosm_flash_comp_type
56 ipc_devlink_get_flash_comp_type(const char comp_str[], u32 len)
58 enum iosm_flash_comp_type fls_type;
60 if (!strncmp("PSI", comp_str, len))
61 fls_type = FLASH_COMP_TYPE_PSI;
62 else if (!strncmp("EBL", comp_str, len))
63 fls_type = FLASH_COMP_TYPE_EBL;
64 else if (!strncmp("FLS", comp_str, len))
65 fls_type = FLASH_COMP_TYPE_FLS;
67 fls_type = FLASH_COMP_TYPE_INVAL;
72 /* Function triggered on devlink flash command
73 * Flash update function which calls multiple functions based on
74 * component type specified in the flash command
76 static int ipc_devlink_flash_update(struct devlink *devlink,
77 struct devlink_flash_update_params *params,
78 struct netlink_ext_ack *extack)
80 struct iosm_devlink *ipc_devlink = devlink_priv(devlink);
81 enum iosm_flash_comp_type fls_type;
82 struct iosm_devlink_image *header;
86 header = (struct iosm_devlink_image *)params->fw->data;
88 if (!header || params->fw->size <= IOSM_DEVLINK_HDR_SIZE ||
89 (memcmp(header->magic_header, IOSM_DEVLINK_MAGIC_HEADER,
90 IOSM_DEVLINK_MAGIC_HEADER_LEN) != 0))
93 mdm_rsp = kzalloc(IOSM_EBL_DW_PACK_SIZE, GFP_KERNEL);
97 fls_type = ipc_devlink_get_flash_comp_type(header->image_type,
98 IOSM_DEVLINK_MAX_IMG_LEN);
101 case FLASH_COMP_TYPE_PSI:
102 rc = ipc_flash_boot_psi(ipc_devlink, params->fw);
104 case FLASH_COMP_TYPE_EBL:
105 rc = ipc_flash_boot_ebl(ipc_devlink, params->fw);
108 rc = ipc_flash_boot_set_capabilities(ipc_devlink, mdm_rsp);
111 rc = ipc_flash_read_swid(ipc_devlink, mdm_rsp);
113 case FLASH_COMP_TYPE_FLS:
114 rc = ipc_flash_send_fls(ipc_devlink, params->fw, mdm_rsp);
117 devlink_flash_update_status_notify(devlink, "Invalid component",
123 devlink_flash_update_status_notify(devlink, "Flashing success",
124 header->image_type, 0, 0);
126 devlink_flash_update_status_notify(devlink, "Flashing failed",
127 header->image_type, 0, 0);
133 /* Call back function for devlink ops */
134 static const struct devlink_ops devlink_flash_ops = {
135 .flash_update = ipc_devlink_flash_update,
139 * ipc_devlink_send_cmd - Send command to Modem
140 * @ipc_devlink: Pointer to struct iosm_devlink
141 * @cmd: Command to be sent to modem
142 * @entry: Command entry number
144 * Returns: 0 on success and failure value on error
146 int ipc_devlink_send_cmd(struct iosm_devlink *ipc_devlink, u16 cmd, u32 entry)
148 struct iosm_rpsi_cmd rpsi_cmd;
150 rpsi_cmd.param.dword = cpu_to_le32(entry);
151 rpsi_cmd.cmd = cpu_to_le16(cmd);
152 rpsi_cmd.crc = rpsi_cmd.param.word[0] ^ rpsi_cmd.param.word[1] ^
155 return ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&rpsi_cmd,
159 /* Function to create snapshot */
160 static int ipc_devlink_coredump_snapshot(struct devlink *dl,
161 const struct devlink_region_ops *ops,
162 struct netlink_ext_ack *extack,
165 struct iosm_devlink *ipc_devlink = devlink_priv(dl);
166 struct iosm_coredump_file_info *cd_list = ops->priv;
170 dev_dbg(ipc_devlink->dev, "Region:%s, ID:%d", ops->name,
172 region_size = cd_list->default_size;
173 rc = ipc_coredump_collect(ipc_devlink, data, cd_list->entry,
176 dev_err(ipc_devlink->dev, "Fail to create snapshot,err %d", rc);
177 goto coredump_collect_err;
180 /* Send coredump end cmd indicating end of coredump collection */
181 if (cd_list->entry == (IOSM_NOF_CD_REGION - 1))
182 ipc_coredump_get_list(ipc_devlink, rpsi_cmd_coredump_end);
186 coredump_collect_err:
187 ipc_coredump_get_list(ipc_devlink, rpsi_cmd_coredump_end);
191 /* To create regions for coredump files */
192 static int ipc_devlink_create_region(struct iosm_devlink *devlink)
194 struct devlink_region_ops *mdm_coredump;
198 mdm_coredump = devlink->iosm_devlink_mdm_coredump;
199 for (i = 0; i < IOSM_NOF_CD_REGION; i++) {
200 mdm_coredump[i].name = list[i].filename;
201 mdm_coredump[i].snapshot = ipc_devlink_coredump_snapshot;
202 mdm_coredump[i].destructor = vfree;
203 devlink->cd_regions[i] =
204 devlink_region_create(devlink->devlink_ctx,
205 &mdm_coredump[i], MAX_SNAPSHOTS,
206 list[i].default_size);
208 if (IS_ERR(devlink->cd_regions[i])) {
209 rc = PTR_ERR(devlink->cd_regions[i]);
210 dev_err(devlink->dev, "Devlink region fail,err %d", rc);
211 /* Delete previously created regions */
213 devlink_region_destroy(devlink->cd_regions[i]);
214 goto region_create_fail;
217 mdm_coredump[i].priv = list + i;
223 /* To Destroy devlink regions */
224 static void ipc_devlink_destroy_region(struct iosm_devlink *ipc_devlink)
228 for (i = 0; i < IOSM_NOF_CD_REGION; i++)
229 devlink_region_destroy(ipc_devlink->cd_regions[i]);
233 * ipc_devlink_init - Initialize/register devlink to IOSM driver
234 * @ipc_imem: Pointer to struct iosm_imem
236 * Returns: Pointer to iosm_devlink on success and NULL on failure
238 struct iosm_devlink *ipc_devlink_init(struct iosm_imem *ipc_imem)
240 struct ipc_chnl_cfg chnl_cfg_flash = { 0 };
241 struct iosm_devlink *ipc_devlink;
242 struct devlink *devlink_ctx;
245 devlink_ctx = devlink_alloc(&devlink_flash_ops,
246 sizeof(struct iosm_devlink),
249 dev_err(ipc_imem->dev, "devlink_alloc failed");
250 goto devlink_alloc_fail;
253 ipc_devlink = devlink_priv(devlink_ctx);
254 ipc_devlink->devlink_ctx = devlink_ctx;
255 ipc_devlink->pcie = ipc_imem->pcie;
256 ipc_devlink->dev = ipc_imem->dev;
258 rc = devlink_params_register(devlink_ctx, iosm_devlink_params,
259 ARRAY_SIZE(iosm_devlink_params));
261 dev_err(ipc_devlink->dev,
262 "devlink_params_register failed. rc %d", rc);
266 ipc_devlink->cd_file_info = list;
268 rc = ipc_devlink_create_region(ipc_devlink);
270 dev_err(ipc_devlink->dev, "Devlink Region create failed, rc %d",
272 goto region_create_fail;
275 if (ipc_chnl_cfg_get(&chnl_cfg_flash, IPC_MEM_CTRL_CHL_ID_7) < 0)
278 ipc_imem_channel_init(ipc_imem, IPC_CTYPE_CTRL,
279 chnl_cfg_flash, IRQ_MOD_OFF);
281 init_completion(&ipc_devlink->devlink_sio.read_sem);
282 skb_queue_head_init(&ipc_devlink->devlink_sio.rx_list);
284 devlink_register(devlink_ctx);
285 dev_dbg(ipc_devlink->dev, "iosm devlink register success");
290 ipc_devlink_destroy_region(ipc_devlink);
292 devlink_params_unregister(devlink_ctx, iosm_devlink_params,
293 ARRAY_SIZE(iosm_devlink_params));
295 devlink_free(devlink_ctx);
301 * ipc_devlink_deinit - To unintialize the devlink from IOSM driver.
302 * @ipc_devlink: Devlink instance
304 void ipc_devlink_deinit(struct iosm_devlink *ipc_devlink)
306 struct devlink *devlink_ctx = ipc_devlink->devlink_ctx;
308 devlink_unregister(devlink_ctx);
309 ipc_devlink_destroy_region(ipc_devlink);
310 devlink_params_unregister(devlink_ctx, iosm_devlink_params,
311 ARRAY_SIZE(iosm_devlink_params));
312 if (ipc_devlink->devlink_sio.devlink_read_pend) {
313 complete(&ipc_devlink->devlink_sio.read_sem);
314 complete(&ipc_devlink->devlink_sio.channel->ul_sem);
316 if (!ipc_devlink->devlink_sio.devlink_read_pend)
317 skb_queue_purge(&ipc_devlink->devlink_sio.rx_list);
319 ipc_imem_sys_devlink_close(ipc_devlink);
320 devlink_free(devlink_ctx);