14dcd183fSM Chetan Kumar // SPDX-License-Identifier: GPL-2.0-only 24dcd183fSM Chetan Kumar /* 34dcd183fSM Chetan Kumar * Copyright (C) 2020-2021 Intel Corporation. 44dcd183fSM Chetan Kumar */ 5980ec04aSM Chetan Kumar #include <linux/vmalloc.h> 64dcd183fSM Chetan Kumar 74dcd183fSM Chetan Kumar #include "iosm_ipc_chnl_cfg.h" 84dcd183fSM Chetan Kumar #include "iosm_ipc_coredump.h" 94dcd183fSM Chetan Kumar #include "iosm_ipc_devlink.h" 104dcd183fSM Chetan Kumar #include "iosm_ipc_flash.h" 114dcd183fSM Chetan Kumar 124dcd183fSM Chetan Kumar /* Coredump list */ 134dcd183fSM Chetan Kumar static struct iosm_coredump_file_info list[IOSM_NOF_CD_REGION] = { 144dcd183fSM Chetan Kumar {"report.json", REPORT_JSON_SIZE,}, 154dcd183fSM Chetan Kumar {"coredump.fcd", COREDUMP_FCD_SIZE,}, 164dcd183fSM Chetan Kumar {"cdd.log", CDD_LOG_SIZE,}, 174dcd183fSM Chetan Kumar {"eeprom.bin", EEPROM_BIN_SIZE,}, 184dcd183fSM Chetan Kumar {"bootcore_trace.bin", BOOTCORE_TRC_BIN_SIZE,}, 194dcd183fSM Chetan Kumar {"bootcore_prev_trace.bin", BOOTCORE_PREV_TRC_BIN_SIZE,}, 204dcd183fSM Chetan Kumar }; 214dcd183fSM Chetan Kumar 224dcd183fSM Chetan Kumar /* Get the param values for the specific param ID's */ 234dcd183fSM Chetan Kumar static int ipc_devlink_get_param(struct devlink *dl, u32 id, 244dcd183fSM Chetan Kumar struct devlink_param_gset_ctx *ctx) 254dcd183fSM Chetan Kumar { 264dcd183fSM Chetan Kumar struct iosm_devlink *ipc_devlink = devlink_priv(dl); 274dcd183fSM Chetan Kumar 28b8aa1654SM Chetan Kumar if (id == IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH) 294dcd183fSM Chetan Kumar ctx->val.vu8 = ipc_devlink->param.erase_full_flash; 304dcd183fSM Chetan Kumar 31b8aa1654SM Chetan Kumar return 0; 324dcd183fSM Chetan Kumar } 334dcd183fSM Chetan Kumar 344dcd183fSM Chetan Kumar /* Set the param values for the specific param ID's */ 354dcd183fSM Chetan Kumar static int ipc_devlink_set_param(struct devlink *dl, u32 id, 365625ca56SMateusz Polchlopek struct devlink_param_gset_ctx *ctx, 375625ca56SMateusz Polchlopek struct netlink_ext_ack *extack) 384dcd183fSM Chetan Kumar { 394dcd183fSM Chetan Kumar struct iosm_devlink *ipc_devlink = devlink_priv(dl); 404dcd183fSM Chetan Kumar 41b8aa1654SM Chetan Kumar if (id == IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH) 424dcd183fSM Chetan Kumar ipc_devlink->param.erase_full_flash = ctx->val.vu8; 434dcd183fSM Chetan Kumar 44b8aa1654SM Chetan Kumar return 0; 454dcd183fSM Chetan Kumar } 464dcd183fSM Chetan Kumar 474dcd183fSM Chetan Kumar /* Devlink param structure array */ 484dcd183fSM Chetan Kumar static const struct devlink_param iosm_devlink_params[] = { 494dcd183fSM Chetan Kumar DEVLINK_PARAM_DRIVER(IOSM_DEVLINK_PARAM_ID_ERASE_FULL_FLASH, 504dcd183fSM Chetan Kumar "erase_full_flash", DEVLINK_PARAM_TYPE_BOOL, 514dcd183fSM Chetan Kumar BIT(DEVLINK_PARAM_CMODE_RUNTIME), 524dcd183fSM Chetan Kumar ipc_devlink_get_param, ipc_devlink_set_param, 534dcd183fSM Chetan Kumar NULL), 544dcd183fSM Chetan Kumar }; 554dcd183fSM Chetan Kumar 564dcd183fSM Chetan Kumar /* Get devlink flash component type */ 574dcd183fSM Chetan Kumar static enum iosm_flash_comp_type 584dcd183fSM Chetan Kumar ipc_devlink_get_flash_comp_type(const char comp_str[], u32 len) 594dcd183fSM Chetan Kumar { 604dcd183fSM Chetan Kumar enum iosm_flash_comp_type fls_type; 614dcd183fSM Chetan Kumar 624dcd183fSM Chetan Kumar if (!strncmp("PSI", comp_str, len)) 634dcd183fSM Chetan Kumar fls_type = FLASH_COMP_TYPE_PSI; 644dcd183fSM Chetan Kumar else if (!strncmp("EBL", comp_str, len)) 654dcd183fSM Chetan Kumar fls_type = FLASH_COMP_TYPE_EBL; 664dcd183fSM Chetan Kumar else if (!strncmp("FLS", comp_str, len)) 674dcd183fSM Chetan Kumar fls_type = FLASH_COMP_TYPE_FLS; 684dcd183fSM Chetan Kumar else 694dcd183fSM Chetan Kumar fls_type = FLASH_COMP_TYPE_INVAL; 704dcd183fSM Chetan Kumar 714dcd183fSM Chetan Kumar return fls_type; 724dcd183fSM Chetan Kumar } 734dcd183fSM Chetan Kumar 744dcd183fSM Chetan Kumar /* Function triggered on devlink flash command 754dcd183fSM Chetan Kumar * Flash update function which calls multiple functions based on 764dcd183fSM Chetan Kumar * component type specified in the flash command 774dcd183fSM Chetan Kumar */ 784dcd183fSM Chetan Kumar static int ipc_devlink_flash_update(struct devlink *devlink, 794dcd183fSM Chetan Kumar struct devlink_flash_update_params *params, 804dcd183fSM Chetan Kumar struct netlink_ext_ack *extack) 814dcd183fSM Chetan Kumar { 824dcd183fSM Chetan Kumar struct iosm_devlink *ipc_devlink = devlink_priv(devlink); 834dcd183fSM Chetan Kumar enum iosm_flash_comp_type fls_type; 84b8aa1654SM Chetan Kumar struct iosm_devlink_image *header; 858bea96efSM Chetan Kumar int rc = -EINVAL; 864dcd183fSM Chetan Kumar u8 *mdm_rsp; 874dcd183fSM Chetan Kumar 88b8aa1654SM Chetan Kumar header = (struct iosm_devlink_image *)params->fw->data; 89b8aa1654SM Chetan Kumar 90b8aa1654SM Chetan Kumar if (!header || params->fw->size <= IOSM_DEVLINK_HDR_SIZE || 91b8aa1654SM Chetan Kumar (memcmp(header->magic_header, IOSM_DEVLINK_MAGIC_HEADER, 92b8aa1654SM Chetan Kumar IOSM_DEVLINK_MAGIC_HEADER_LEN) != 0)) 938bea96efSM Chetan Kumar return -EINVAL; 944dcd183fSM Chetan Kumar 954dcd183fSM Chetan Kumar mdm_rsp = kzalloc(IOSM_EBL_DW_PACK_SIZE, GFP_KERNEL); 964dcd183fSM Chetan Kumar if (!mdm_rsp) 974dcd183fSM Chetan Kumar return -ENOMEM; 984dcd183fSM Chetan Kumar 99b8aa1654SM Chetan Kumar fls_type = ipc_devlink_get_flash_comp_type(header->image_type, 100b8aa1654SM Chetan Kumar IOSM_DEVLINK_MAX_IMG_LEN); 1014dcd183fSM Chetan Kumar 1024dcd183fSM Chetan Kumar switch (fls_type) { 1034dcd183fSM Chetan Kumar case FLASH_COMP_TYPE_PSI: 1044dcd183fSM Chetan Kumar rc = ipc_flash_boot_psi(ipc_devlink, params->fw); 1054dcd183fSM Chetan Kumar break; 1064dcd183fSM Chetan Kumar case FLASH_COMP_TYPE_EBL: 1074dcd183fSM Chetan Kumar rc = ipc_flash_boot_ebl(ipc_devlink, params->fw); 1088bea96efSM Chetan Kumar if (rc) 1098bea96efSM Chetan Kumar break; 1108bea96efSM Chetan Kumar rc = ipc_flash_boot_set_capabilities(ipc_devlink, mdm_rsp); 1118bea96efSM Chetan Kumar if (rc) 1128bea96efSM Chetan Kumar break; 1134dcd183fSM Chetan Kumar rc = ipc_flash_read_swid(ipc_devlink, mdm_rsp); 1144dcd183fSM Chetan Kumar break; 1154dcd183fSM Chetan Kumar case FLASH_COMP_TYPE_FLS: 1164dcd183fSM Chetan Kumar rc = ipc_flash_send_fls(ipc_devlink, params->fw, mdm_rsp); 1174dcd183fSM Chetan Kumar break; 1184dcd183fSM Chetan Kumar default: 1194dcd183fSM Chetan Kumar devlink_flash_update_status_notify(devlink, "Invalid component", 120b8aa1654SM Chetan Kumar NULL, 0, 0); 1214dcd183fSM Chetan Kumar break; 1224dcd183fSM Chetan Kumar } 1234dcd183fSM Chetan Kumar 1244dcd183fSM Chetan Kumar if (!rc) 1254dcd183fSM Chetan Kumar devlink_flash_update_status_notify(devlink, "Flashing success", 126b8aa1654SM Chetan Kumar header->image_type, 0, 0); 1274dcd183fSM Chetan Kumar else 1284dcd183fSM Chetan Kumar devlink_flash_update_status_notify(devlink, "Flashing failed", 129b8aa1654SM Chetan Kumar header->image_type, 0, 0); 1304dcd183fSM Chetan Kumar 1314dcd183fSM Chetan Kumar kfree(mdm_rsp); 1324dcd183fSM Chetan Kumar return rc; 1334dcd183fSM Chetan Kumar } 1344dcd183fSM Chetan Kumar 1354dcd183fSM Chetan Kumar /* Call back function for devlink ops */ 1364dcd183fSM Chetan Kumar static const struct devlink_ops devlink_flash_ops = { 1374dcd183fSM Chetan Kumar .flash_update = ipc_devlink_flash_update, 1384dcd183fSM Chetan Kumar }; 1394dcd183fSM Chetan Kumar 1408bea96efSM Chetan Kumar /** 1418bea96efSM Chetan Kumar * ipc_devlink_send_cmd - Send command to Modem 1428bea96efSM Chetan Kumar * @ipc_devlink: Pointer to struct iosm_devlink 1438bea96efSM Chetan Kumar * @cmd: Command to be sent to modem 1448bea96efSM Chetan Kumar * @entry: Command entry number 1458bea96efSM Chetan Kumar * 1468bea96efSM Chetan Kumar * Returns: 0 on success and failure value on error 1478bea96efSM Chetan Kumar */ 1484dcd183fSM Chetan Kumar int ipc_devlink_send_cmd(struct iosm_devlink *ipc_devlink, u16 cmd, u32 entry) 1494dcd183fSM Chetan Kumar { 1504dcd183fSM Chetan Kumar struct iosm_rpsi_cmd rpsi_cmd; 1514dcd183fSM Chetan Kumar 1524dcd183fSM Chetan Kumar rpsi_cmd.param.dword = cpu_to_le32(entry); 1534dcd183fSM Chetan Kumar rpsi_cmd.cmd = cpu_to_le16(cmd); 1544dcd183fSM Chetan Kumar rpsi_cmd.crc = rpsi_cmd.param.word[0] ^ rpsi_cmd.param.word[1] ^ 1554dcd183fSM Chetan Kumar rpsi_cmd.cmd; 1564dcd183fSM Chetan Kumar 1574dcd183fSM Chetan Kumar return ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&rpsi_cmd, 1584dcd183fSM Chetan Kumar sizeof(rpsi_cmd)); 1594dcd183fSM Chetan Kumar } 1604dcd183fSM Chetan Kumar 1618bea96efSM Chetan Kumar /* Function to create snapshot */ 1624dcd183fSM Chetan Kumar static int ipc_devlink_coredump_snapshot(struct devlink *dl, 1634dcd183fSM Chetan Kumar const struct devlink_region_ops *ops, 1644dcd183fSM Chetan Kumar struct netlink_ext_ack *extack, 1654dcd183fSM Chetan Kumar u8 **data) 1664dcd183fSM Chetan Kumar { 1674dcd183fSM Chetan Kumar struct iosm_devlink *ipc_devlink = devlink_priv(dl); 1684dcd183fSM Chetan Kumar struct iosm_coredump_file_info *cd_list = ops->priv; 1694dcd183fSM Chetan Kumar u32 region_size; 1704dcd183fSM Chetan Kumar int rc; 1714dcd183fSM Chetan Kumar 1724dcd183fSM Chetan Kumar dev_dbg(ipc_devlink->dev, "Region:%s, ID:%d", ops->name, 1734dcd183fSM Chetan Kumar cd_list->entry); 1744dcd183fSM Chetan Kumar region_size = cd_list->default_size; 1754dcd183fSM Chetan Kumar rc = ipc_coredump_collect(ipc_devlink, data, cd_list->entry, 1764dcd183fSM Chetan Kumar region_size); 1774dcd183fSM Chetan Kumar if (rc) { 1784dcd183fSM Chetan Kumar dev_err(ipc_devlink->dev, "Fail to create snapshot,err %d", rc); 1794dcd183fSM Chetan Kumar goto coredump_collect_err; 1804dcd183fSM Chetan Kumar } 1814dcd183fSM Chetan Kumar 1824dcd183fSM Chetan Kumar /* Send coredump end cmd indicating end of coredump collection */ 1834dcd183fSM Chetan Kumar if (cd_list->entry == (IOSM_NOF_CD_REGION - 1)) 1844dcd183fSM Chetan Kumar ipc_coredump_get_list(ipc_devlink, rpsi_cmd_coredump_end); 1854dcd183fSM Chetan Kumar 1868bea96efSM Chetan Kumar return 0; 1878bea96efSM Chetan Kumar 1884dcd183fSM Chetan Kumar coredump_collect_err: 1894dcd183fSM Chetan Kumar ipc_coredump_get_list(ipc_devlink, rpsi_cmd_coredump_end); 1904dcd183fSM Chetan Kumar return rc; 1914dcd183fSM Chetan Kumar } 1924dcd183fSM Chetan Kumar 1934dcd183fSM Chetan Kumar /* To create regions for coredump files */ 1944dcd183fSM Chetan Kumar static int ipc_devlink_create_region(struct iosm_devlink *devlink) 1954dcd183fSM Chetan Kumar { 1964dcd183fSM Chetan Kumar struct devlink_region_ops *mdm_coredump; 1974dcd183fSM Chetan Kumar int rc = 0; 1984dcd183fSM Chetan Kumar int i; 1994dcd183fSM Chetan Kumar 2004dcd183fSM Chetan Kumar mdm_coredump = devlink->iosm_devlink_mdm_coredump; 2014dcd183fSM Chetan Kumar for (i = 0; i < IOSM_NOF_CD_REGION; i++) { 2024dcd183fSM Chetan Kumar mdm_coredump[i].name = list[i].filename; 2034dcd183fSM Chetan Kumar mdm_coredump[i].snapshot = ipc_devlink_coredump_snapshot; 2044dcd183fSM Chetan Kumar mdm_coredump[i].destructor = vfree; 2054dcd183fSM Chetan Kumar devlink->cd_regions[i] = 2064dcd183fSM Chetan Kumar devlink_region_create(devlink->devlink_ctx, 2074dcd183fSM Chetan Kumar &mdm_coredump[i], MAX_SNAPSHOTS, 2084dcd183fSM Chetan Kumar list[i].default_size); 2094dcd183fSM Chetan Kumar 2104dcd183fSM Chetan Kumar if (IS_ERR(devlink->cd_regions[i])) { 2114dcd183fSM Chetan Kumar rc = PTR_ERR(devlink->cd_regions[i]); 2124dcd183fSM Chetan Kumar dev_err(devlink->dev, "Devlink region fail,err %d", rc); 2134dcd183fSM Chetan Kumar /* Delete previously created regions */ 214*b0c9a264SAleksandr Mishin for (i--; i >= 0; i--) 2154dcd183fSM Chetan Kumar devlink_region_destroy(devlink->cd_regions[i]); 2164dcd183fSM Chetan Kumar goto region_create_fail; 2174dcd183fSM Chetan Kumar } 2184dcd183fSM Chetan Kumar list[i].entry = i; 2194dcd183fSM Chetan Kumar mdm_coredump[i].priv = list + i; 2204dcd183fSM Chetan Kumar } 2214dcd183fSM Chetan Kumar region_create_fail: 2224dcd183fSM Chetan Kumar return rc; 2234dcd183fSM Chetan Kumar } 2244dcd183fSM Chetan Kumar 2254dcd183fSM Chetan Kumar /* To Destroy devlink regions */ 2264dcd183fSM Chetan Kumar static void ipc_devlink_destroy_region(struct iosm_devlink *ipc_devlink) 2274dcd183fSM Chetan Kumar { 2284dcd183fSM Chetan Kumar u8 i; 2294dcd183fSM Chetan Kumar 2304dcd183fSM Chetan Kumar for (i = 0; i < IOSM_NOF_CD_REGION; i++) 2314dcd183fSM Chetan Kumar devlink_region_destroy(ipc_devlink->cd_regions[i]); 2324dcd183fSM Chetan Kumar } 2334dcd183fSM Chetan Kumar 2348bea96efSM Chetan Kumar /** 2358bea96efSM Chetan Kumar * ipc_devlink_init - Initialize/register devlink to IOSM driver 2368bea96efSM Chetan Kumar * @ipc_imem: Pointer to struct iosm_imem 2378bea96efSM Chetan Kumar * 2388bea96efSM Chetan Kumar * Returns: Pointer to iosm_devlink on success and NULL on failure 2398bea96efSM Chetan Kumar */ 2404dcd183fSM Chetan Kumar struct iosm_devlink *ipc_devlink_init(struct iosm_imem *ipc_imem) 2414dcd183fSM Chetan Kumar { 2424dcd183fSM Chetan Kumar struct ipc_chnl_cfg chnl_cfg_flash = { 0 }; 2434dcd183fSM Chetan Kumar struct iosm_devlink *ipc_devlink; 2444dcd183fSM Chetan Kumar struct devlink *devlink_ctx; 2454dcd183fSM Chetan Kumar int rc; 2464dcd183fSM Chetan Kumar 2474dcd183fSM Chetan Kumar devlink_ctx = devlink_alloc(&devlink_flash_ops, 2484dcd183fSM Chetan Kumar sizeof(struct iosm_devlink), 2494dcd183fSM Chetan Kumar ipc_imem->dev); 2504dcd183fSM Chetan Kumar if (!devlink_ctx) { 2514dcd183fSM Chetan Kumar dev_err(ipc_imem->dev, "devlink_alloc failed"); 2524dcd183fSM Chetan Kumar goto devlink_alloc_fail; 2534dcd183fSM Chetan Kumar } 2544dcd183fSM Chetan Kumar 2554dcd183fSM Chetan Kumar ipc_devlink = devlink_priv(devlink_ctx); 2564dcd183fSM Chetan Kumar ipc_devlink->devlink_ctx = devlink_ctx; 2574dcd183fSM Chetan Kumar ipc_devlink->pcie = ipc_imem->pcie; 2584dcd183fSM Chetan Kumar ipc_devlink->dev = ipc_imem->dev; 2594dcd183fSM Chetan Kumar 2604dcd183fSM Chetan Kumar rc = devlink_params_register(devlink_ctx, iosm_devlink_params, 2614dcd183fSM Chetan Kumar ARRAY_SIZE(iosm_devlink_params)); 2624dcd183fSM Chetan Kumar if (rc) { 2634dcd183fSM Chetan Kumar dev_err(ipc_devlink->dev, 2644dcd183fSM Chetan Kumar "devlink_params_register failed. rc %d", rc); 2654dcd183fSM Chetan Kumar goto param_reg_fail; 2664dcd183fSM Chetan Kumar } 2674dcd183fSM Chetan Kumar 2684dcd183fSM Chetan Kumar ipc_devlink->cd_file_info = list; 2694dcd183fSM Chetan Kumar 2704dcd183fSM Chetan Kumar rc = ipc_devlink_create_region(ipc_devlink); 2714dcd183fSM Chetan Kumar if (rc) { 2724dcd183fSM Chetan Kumar dev_err(ipc_devlink->dev, "Devlink Region create failed, rc %d", 2734dcd183fSM Chetan Kumar rc); 2744dcd183fSM Chetan Kumar goto region_create_fail; 2754dcd183fSM Chetan Kumar } 2764dcd183fSM Chetan Kumar 2774dcd183fSM Chetan Kumar if (ipc_chnl_cfg_get(&chnl_cfg_flash, IPC_MEM_CTRL_CHL_ID_7) < 0) 2784dcd183fSM Chetan Kumar goto chnl_get_fail; 2794dcd183fSM Chetan Kumar 2804dcd183fSM Chetan Kumar ipc_imem_channel_init(ipc_imem, IPC_CTYPE_CTRL, 2814dcd183fSM Chetan Kumar chnl_cfg_flash, IRQ_MOD_OFF); 2824dcd183fSM Chetan Kumar 2834dcd183fSM Chetan Kumar init_completion(&ipc_devlink->devlink_sio.read_sem); 2844dcd183fSM Chetan Kumar skb_queue_head_init(&ipc_devlink->devlink_sio.rx_list); 2854dcd183fSM Chetan Kumar 286504627eeSLeon Romanovsky devlink_register(devlink_ctx); 2874dcd183fSM Chetan Kumar dev_dbg(ipc_devlink->dev, "iosm devlink register success"); 2884dcd183fSM Chetan Kumar 2894dcd183fSM Chetan Kumar return ipc_devlink; 2904dcd183fSM Chetan Kumar 2914dcd183fSM Chetan Kumar chnl_get_fail: 2924dcd183fSM Chetan Kumar ipc_devlink_destroy_region(ipc_devlink); 2934dcd183fSM Chetan Kumar region_create_fail: 2944dcd183fSM Chetan Kumar devlink_params_unregister(devlink_ctx, iosm_devlink_params, 2954dcd183fSM Chetan Kumar ARRAY_SIZE(iosm_devlink_params)); 2964dcd183fSM Chetan Kumar param_reg_fail: 2974dcd183fSM Chetan Kumar devlink_free(devlink_ctx); 2984dcd183fSM Chetan Kumar devlink_alloc_fail: 2994dcd183fSM Chetan Kumar return NULL; 3004dcd183fSM Chetan Kumar } 3014dcd183fSM Chetan Kumar 3028bea96efSM Chetan Kumar /** 3038bea96efSM Chetan Kumar * ipc_devlink_deinit - To unintialize the devlink from IOSM driver. 3048bea96efSM Chetan Kumar * @ipc_devlink: Devlink instance 3058bea96efSM Chetan Kumar */ 3064dcd183fSM Chetan Kumar void ipc_devlink_deinit(struct iosm_devlink *ipc_devlink) 3074dcd183fSM Chetan Kumar { 3084dcd183fSM Chetan Kumar struct devlink *devlink_ctx = ipc_devlink->devlink_ctx; 3094dcd183fSM Chetan Kumar 310504627eeSLeon Romanovsky devlink_unregister(devlink_ctx); 3114dcd183fSM Chetan Kumar ipc_devlink_destroy_region(ipc_devlink); 3124dcd183fSM Chetan Kumar devlink_params_unregister(devlink_ctx, iosm_devlink_params, 3134dcd183fSM Chetan Kumar ARRAY_SIZE(iosm_devlink_params)); 3144dcd183fSM Chetan Kumar if (ipc_devlink->devlink_sio.devlink_read_pend) { 3154dcd183fSM Chetan Kumar complete(&ipc_devlink->devlink_sio.read_sem); 3164dcd183fSM Chetan Kumar complete(&ipc_devlink->devlink_sio.channel->ul_sem); 3174dcd183fSM Chetan Kumar } 3184dcd183fSM Chetan Kumar if (!ipc_devlink->devlink_sio.devlink_read_pend) 3194dcd183fSM Chetan Kumar skb_queue_purge(&ipc_devlink->devlink_sio.rx_list); 3204dcd183fSM Chetan Kumar 3214dcd183fSM Chetan Kumar ipc_imem_sys_devlink_close(ipc_devlink); 3224dcd183fSM Chetan Kumar devlink_free(devlink_ctx); 3234dcd183fSM Chetan Kumar } 324