From 3f675dbe10e6b51433174ce9a6265f4fe4df5b2e Mon Sep 17 00:00:00 2001 From: "Carrie.Cai" Date: Sat, 9 Mar 2024 17:50:26 +0800 Subject: [PATCH 1/2] fix 0day bugs for Mont-TSSE in CI test Montage inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I975BF CVE: NA -------------------------------------------------------- fix the 0day bug report by ci Reported-by: kernel test robot Closes:https://lore.kernel.org/oe-kbuild-all/202402290504.Dzt3mHvf-lkp@intel.com/ Signed-off-by: Carrie.Cai --- drivers/crypto/montage/tsse/tsse_dev.h | 1 - drivers/crypto/montage/tsse/tsse_dev_mgr.c | 26 +------------------ drivers/crypto/montage/tsse/tsse_fw_service.c | 4 +-- drivers/crypto/montage/tsse/tsse_ipc.c | 22 ++++------------ drivers/crypto/montage/tsse/tsse_service.c | 8 +++--- 5 files changed, 11 insertions(+), 50 deletions(-) diff --git a/drivers/crypto/montage/tsse/tsse_dev.h b/drivers/crypto/montage/tsse/tsse_dev.h index d1dafee61300..13570ae8d52a 100644 --- a/drivers/crypto/montage/tsse/tsse_dev.h +++ b/drivers/crypto/montage/tsse/tsse_dev.h @@ -72,7 +72,6 @@ int tsse_devmgr_add_dev(struct tsse_dev *tsse_dev); void tsse_devmgr_rm_dev(struct tsse_dev *tdev); int tsse_prepare_restart_dev(struct tsse_dev *tdev); int tsse_start_dev(struct tsse_dev *tdev); -struct tsse_dev *get_tssedev(int id); static inline struct tsse_dev *pci_to_tsse_dev(struct pci_dev *pci_dev) { diff --git a/drivers/crypto/montage/tsse/tsse_dev_mgr.c b/drivers/crypto/montage/tsse/tsse_dev_mgr.c index 159f75c8f46f..0b9f9c1c40eb 100644 --- a/drivers/crypto/montage/tsse/tsse_dev_mgr.c +++ b/drivers/crypto/montage/tsse/tsse_dev_mgr.c @@ -34,12 +34,6 @@ static inline void tsse_list_add(struct list_head *new, struct list_head *prev, WRITE_ONCE(prev->next, new); } -static inline void tsse_list_add_tail(struct list_head *new, - struct list_head *head) -{ - tsse_list_add(new, head->prev, head); -} - static int tsse_dev_pf_get(struct tsse_dev *vf_tsse_dev) { int ret = 0; @@ -104,7 +98,7 @@ void tsse_dev_put(struct tsse_dev *tdev) } } -int tsse_stop_dev(struct tsse_dev *tdev, bool busy_exit) +static int tsse_stop_dev(struct tsse_dev *tdev, bool busy_exit) { int times, max_retry = 150; @@ -209,21 +203,3 @@ struct list_head *tsse_devmgr_get_head(void) { return &tsse_dev_table; } - -struct tsse_dev *get_tssedev(int id) -{ - struct list_head *itr; - struct tsse_dev *ptr; - - mutex_lock(&tsse_dev_table_lock); - - list_for_each(itr, &tsse_dev_table) { - ptr = list_entry(itr, struct tsse_dev, list); - break; - } - - mutex_unlock(&tsse_dev_table_lock); - - return ptr; -} -EXPORT_SYMBOL_GPL(get_tssedev); diff --git a/drivers/crypto/montage/tsse/tsse_fw_service.c b/drivers/crypto/montage/tsse/tsse_fw_service.c index fc3907a7c503..c191a339dd13 100644 --- a/drivers/crypto/montage/tsse/tsse_fw_service.c +++ b/drivers/crypto/montage/tsse/tsse_fw_service.c @@ -23,7 +23,7 @@ #define SEARCH_PATTERN "MT_CFG_BUILD_VERSION_DETAIL" #define SEARCH_PATTERN_LEN 28 -int fw_send_msg(struct tsse_ipc *tsseipc, struct ipc_msg *msg) +static int fw_send_msg(struct tsse_ipc *tsseipc, struct ipc_msg *msg) { u8 *h2d; u32 int_reg; @@ -48,7 +48,7 @@ int fw_send_msg(struct tsse_ipc *tsseipc, struct ipc_msg *msg) return 0; } -void fw_free(void *msg_t) +static void fw_free(void *msg_t) { struct tsse_msg *tssemsg; struct ipc_msg *payload; diff --git a/drivers/crypto/montage/tsse/tsse_ipc.c b/drivers/crypto/montage/tsse/tsse_ipc.c index 0f92c096f211..4cac3f61d8df 100644 --- a/drivers/crypto/montage/tsse/tsse_ipc.c +++ b/drivers/crypto/montage/tsse/tsse_ipc.c @@ -14,7 +14,7 @@ #include "tsse_dev.h" #include "tsse_service.h" -struct tsse_msg *get_msginf(void __iomem *d2h) +static struct tsse_msg *get_msginf(void __iomem *d2h) { uint32_t u_len; struct tsse_msg *tssemsg; @@ -38,7 +38,7 @@ struct tsse_msg *get_msginf(void __iomem *d2h) return tssemsg; } -void ipc_recieve_msg(struct tsse_ipc *tsseipc, struct ipc_msg *msg) +static void ipc_recieve_msg(struct tsse_ipc *tsseipc, struct ipc_msg *msg) { uint32_t u_len = msg->header.i_len - sizeof(struct ipc_header); uint32_t *msg_data = NULL; @@ -50,7 +50,7 @@ void ipc_recieve_msg(struct tsse_ipc *tsseipc, struct ipc_msg *msg) } -int msg_rout(struct tsse_ipc *tsseipc, struct tsse_msg *tssemsg) +static int msg_rout(struct tsse_ipc *tsseipc, struct tsse_msg *tssemsg) { int ret = 0; struct ipc_msg *msg; @@ -100,26 +100,14 @@ void notify_device(struct tsse_ipc *tsseipc) } EXPORT_SYMBOL(notify_device); -void ipc_send_msg(struct tsse_ipc *tsseipc, struct ipc_data *msg) -{ - u8 *h2d = NULL; - - h2d = (u8 *)(tsseipc->virt_addr + HOST2MAIN_IPC_OFFSET); - memcpy_toio(h2d, msg, sizeof(struct ipc_header)); - memcpy_toio(h2d + sizeof(struct ipc_header), (u32 *)msg->i_ptr, - msg->header.i_len - sizeof(struct ipc_header)); - return; - -} - -void ipc_hw_init(struct tsse_ipc *hw_ipc) +static void ipc_hw_init(struct tsse_ipc *hw_ipc) { writel(0x1, hw_ipc->virt_addr + MAIN2HOST_INTR_ENABLE_OFFSET); writel(0x0, hw_ipc->virt_addr + HOST2MAIN_INTR_SET_OFFSET); writel(0x0, hw_ipc->virt_addr + MAIN2HOST_INTR_SET_OFFSET); } -int ipc_init_msg(struct tsse_ipc *tsseipc) +static int ipc_init_msg(struct tsse_ipc *tsseipc) { u8 *h2d; u32 int_reg; diff --git a/drivers/crypto/montage/tsse/tsse_service.c b/drivers/crypto/montage/tsse/tsse_service.c index 64121a655803..e4be85535b77 100644 --- a/drivers/crypto/montage/tsse/tsse_service.c +++ b/drivers/crypto/montage/tsse/tsse_service.c @@ -5,14 +5,13 @@ * Copyright © 2023 Montage Technology. All rights reserved. */ #include -#include "tsse_ipc.h" -#include "tsse_fw_service.h" +#include "tsse_service.h" int service_rout(struct tsse_ipc *tsseipc, struct ipc_msg *msg) { struct msg_info *info; uint32_t msg_class; - int ret; + int ret = 0; info = (struct msg_info *)msg->i_data; msg_class = info->msg_class; @@ -25,6 +24,5 @@ int service_rout(struct tsse_ipc *tsseipc, struct ipc_msg *msg) ret = -EINVAL; break; } - return 0; - + return ret; } -- Gitee From 7795623241fe9eb57352a09b27d06b5d4ff07071 Mon Sep 17 00:00:00 2001 From: "Carrie.Cai" Date: Sat, 9 Mar 2024 18:02:18 +0800 Subject: [PATCH 2/2] add firmware update function for Mont-TSSE Montage inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I96W72 CVE: NA -------------------------------------------------------- add support for Mont-TSSE firmware update by sysfs. Signed-off-by: Carrie.Cai --- drivers/crypto/montage/tsse/tsse_dev.h | 2 + drivers/crypto/montage/tsse/tsse_dev_drv.c | 64 ++++++++- drivers/crypto/montage/tsse/tsse_dev_mgr.c | 4 - drivers/crypto/montage/tsse/tsse_fw_service.c | 100 +++++++------ drivers/crypto/montage/tsse/tsse_fw_service.h | 6 +- drivers/crypto/montage/tsse/tsse_ipc.c | 134 +++++++++--------- drivers/crypto/montage/tsse/tsse_ipc.h | 15 +- 7 files changed, 190 insertions(+), 135 deletions(-) diff --git a/drivers/crypto/montage/tsse/tsse_dev.h b/drivers/crypto/montage/tsse/tsse_dev.h index 13570ae8d52a..c16d2ae7c414 100644 --- a/drivers/crypto/montage/tsse/tsse_dev.h +++ b/drivers/crypto/montage/tsse/tsse_dev.h @@ -18,6 +18,7 @@ #define TSSE_PCI_MAX_BARS 4 #define TSSE_FW_VERSION_LEN 32 + struct tsse_bar { void __iomem *virt_addr; resource_size_t addr; @@ -58,6 +59,7 @@ struct tsse_dev { void *mbx_hw; const struct firmware *fw; char fw_version[TSSE_FW_VERSION_LEN]; + bool fw_version_exist; }; #define TSSEDEV_TO_DEV(tssedev) (&((tssedev)->tsse_pci_dev.pci_dev->dev)) #define TSSE_DEV_BARS(tssedev) ((tssedev)->tsse_pci_dev.bars) diff --git a/drivers/crypto/montage/tsse/tsse_dev_drv.c b/drivers/crypto/montage/tsse/tsse_dev_drv.c index 9e914576a129..0bdf4ba0d717 100644 --- a/drivers/crypto/montage/tsse/tsse_dev_drv.c +++ b/drivers/crypto/montage/tsse/tsse_dev_drv.c @@ -11,18 +11,25 @@ #include #include #include +#include #include "tsse_dev_drv.h" #include "tsse_vuart.h" #include "tsse_ipc.h" #include "tsse_fw_service.h" +#define CLUSTER_SLOT_CONFIG_OFFSET 0x5780000 +#define QPAIR_SETTING_OFFSET 0x50000 +#define BAR_START 2 +#define BAR_END 4 + static DEFINE_IDA(tsse_ida); static inline void tsse_qpair_enable_pf(struct tsse_dev *tdev, bool enable) { writel(enable ? 1 : 0, - TSSE_DEV_BARS(tdev)[2].virt_addr + 0x5780000 + 0x50000); + TSSE_DEV_BARS(tdev)[2].virt_addr + + CLUSTER_SLOT_CONFIG_OFFSET + QPAIR_SETTING_OFFSET); } static int tsse_sriov_disable(struct tsse_dev *tdev) { @@ -107,6 +114,39 @@ static int tsse_sriov_configure(struct pci_dev *pdev, int num_vfs_param) return num_vfs_param; } +/** + * This function will be called when user writes string to /sys/bus/pci/devices/.../tsse_image_load. + * Driver will always loads /lib/firmware/tsse_firmware.bin. + * @dev: device + * @attr: device attribute + * @buf: string that user writes + * @count: string length that user writes + * Return: the number of bytes used from the buffer, here it is just the count argument. +*/ +static ssize_t tsse_image_load_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = NULL; + struct tsse_dev *tdev = NULL; + + pdev = container_of(dev, struct pci_dev, dev); + if (pdev) + tdev = pci_to_tsse_dev(pdev); + if (buf && count && tdev) { + tsse_dev_info(tdev, "receive command to load firmware %s\n", TSSE_FIRMWARE); + if (!tsse_fw_load(pdev, TSSE_FIRMWARE, &tdev->fw)) { + if (!get_firmware_version(tdev->fw, tdev->fw_version)) + tdev->fw_version_exist = true; + if (tsse_fw_manual_load_ipc(pdev)) + dev_err(&pdev->dev, "%s %d: firmware update failed\n", + __func__, __LINE__); + } + } + return count; +} + +DEVICE_ATTR_WO(tsse_image_load); + static int device_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int status = 0; @@ -163,7 +203,7 @@ static int device_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_err; } - for (bar = 2; bar < 4;) { + for (bar = BAR_START; bar < BAR_END;) { TSSE_DEV_BARS(tdev)[bar].addr = pci_resource_start(pdev, bar); TSSE_DEV_BARS(tdev)[bar].size = pci_resource_len(pdev, bar); TSSE_DEV_BARS(tdev) @@ -219,9 +259,13 @@ static int device_probe(struct pci_dev *pdev, const struct pci_device_id *id) status = -EFAULT; goto out_err_port_init; } + + tdev->fw_version_exist = false; /* Its result not break driver init process */ - if (!tsse_fw_load(pdev)) - get_firmware_version((char *)tdev->fw->data, tdev->fw->size, tdev->fw_version); + if (!tsse_fw_load(pdev, TSSE_FIRMWARE, &tdev->fw)) { + if (!get_firmware_version(tdev->fw, tdev->fw_version)) + tdev->fw_version_exist = true; + } if (tsse_ipc_init(pdev)) { dev_err(&pdev->dev, @@ -231,13 +275,22 @@ static int device_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_err_ipc; } + if (sysfs_create_file(&pdev->dev.kobj, &dev_attr_tsse_image_load.attr)) { + dev_err(&pdev->dev, + "%s %d: sysfs_create_file failed for tsse image load.\n", + __func__, __LINE__); + status = -EFAULT; + goto out_err_image_load; + } + tsse_dev_info(tdev, "successful\n"); pci_read_config_dword(pdev, 0x720, &tmp_val); tsse_dev_dbg(tdev, "the value of FILTER_MASK_2_REG is 0x%x\n", tmp_val); return 0; - +out_err_image_load: + tsse_ipc_deinit(tdev); out_err_ipc: vuart_uninit_port(pdev); out_err_port_init: @@ -261,6 +314,7 @@ static void device_remove(struct pci_dev *pdev) release_firmware(tdev->fw); tdev->fw = NULL; } + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_tsse_image_load.attr); tsse_ipc_deinit(tdev); vuart_uninit_port(pdev); tsse_devmgr_rm_dev(tdev); diff --git a/drivers/crypto/montage/tsse/tsse_dev_mgr.c b/drivers/crypto/montage/tsse/tsse_dev_mgr.c index 0b9f9c1c40eb..39553eb96832 100644 --- a/drivers/crypto/montage/tsse/tsse_dev_mgr.c +++ b/drivers/crypto/montage/tsse/tsse_dev_mgr.c @@ -166,13 +166,11 @@ int tsse_start_dev(struct tsse_dev *tdev) clear_bit(TSSE_DEV_STATUS_STARTED, &tdev->status); return ret; } -EXPORT_SYMBOL_GPL(tsse_start_dev); int tsse_prepare_restart_dev(struct tsse_dev *tdev) { return tsse_stop_dev(tdev, false); } -EXPORT_SYMBOL_GPL(tsse_prepare_restart_dev); void tsse_devmgr_rm_dev(struct tsse_dev *tdev) { @@ -180,7 +178,6 @@ void tsse_devmgr_rm_dev(struct tsse_dev *tdev) tsse_dev_free_irq_vectors(tdev); msleep(300); } -EXPORT_SYMBOL_GPL(tsse_devmgr_rm_dev); int tsse_devmgr_add_dev(struct tsse_dev *tdev) { @@ -197,7 +194,6 @@ int tsse_devmgr_add_dev(struct tsse_dev *tdev) } return ret; } -EXPORT_SYMBOL_GPL(tsse_devmgr_add_dev); struct list_head *tsse_devmgr_get_head(void) { diff --git a/drivers/crypto/montage/tsse/tsse_fw_service.c b/drivers/crypto/montage/tsse/tsse_fw_service.c index c191a339dd13..ed47d38ef1ad 100644 --- a/drivers/crypto/montage/tsse/tsse_fw_service.c +++ b/drivers/crypto/montage/tsse/tsse_fw_service.c @@ -21,25 +21,28 @@ #include "tsse_service.h" #define SEARCH_PATTERN "MT_CFG_BUILD_VERSION_DETAIL" -#define SEARCH_PATTERN_LEN 28 +#define SPACE_CH ' ' static int fw_send_msg(struct tsse_ipc *tsseipc, struct ipc_msg *msg) { u8 *h2d; u32 int_reg; - u32 rc; mutex_lock(&tsseipc->list_lock); int_reg = readl(tsseipc->virt_addr + HOST2MAIN_INTR_SET_OFFSET); if ((int_reg & IPC_REGISTER_INT_SET) != 0) { - rc = -1; mutex_unlock(&tsseipc->list_lock); - return rc; + return -EFAULT; + } + if (msg->header.i_len < sizeof(struct ipc_header) + + sizeof(struct msg_info) + sizeof(struct fw_load)) { + dev_err(tsseipc->dev, "msg format error\n"); + return -EFAULT; } h2d = (u8 *)(tsseipc->virt_addr + HOST2MAIN_IPC_OFFSET); memcpy_toio(h2d, msg, sizeof(struct ipc_header)); - memcpy_toio(h2d + sizeof(struct ipc_header), (u32 *)msg->i_data, + memcpy_toio(h2d + sizeof(struct ipc_header), (u8 *)msg->i_data, msg->header.i_len - sizeof(struct ipc_header)); writel(0x1, tsseipc->virt_addr + HOST2MAIN_INTR_SET_OFFSET); @@ -48,41 +51,30 @@ static int fw_send_msg(struct tsse_ipc *tsseipc, struct ipc_msg *msg) return 0; } -static void fw_free(void *msg_t) -{ - struct tsse_msg *tssemsg; - struct ipc_msg *payload; - - payload = (struct ipc_msg *)msg_t; - tssemsg = container_of(payload, struct tsse_msg, ipc_payload); - - kvfree(tssemsg); -} - -int get_firmware_version(char *fw_buffer, uint32_t buffer_len, char *fw_version) +/** + * Get version information from firmware + * @fw: firmware pointer + * @fw_version_out: firmware version string output + * Return: 0 on success, error code otherwise +*/ +int get_firmware_version(const struct firmware *fw, char *fw_version_out) { - char *pattern; - char *space_ch = " "; + const char *pattern = SEARCH_PATTERN; + const uint8_t *fw_buffer = fw->data; uint32_t pattern_i = 0, buffer_i = 0; - uint32_t pattern_len = SEARCH_PATTERN_LEN - 1; // Not include "\0" + uint32_t pattern_len = strlen(pattern); // Not include "\0" uint32_t version_start = 0; uint32_t version_len = 0; - pattern = kzalloc(SEARCH_PATTERN_LEN, GFP_KERNEL); - if (!pattern) - return -1; - - snprintf(pattern, SEARCH_PATTERN_LEN, SEARCH_PATTERN); - - while (buffer_i < buffer_len) { - if (pattern[pattern_i] == fw_buffer[buffer_i]) { + while (buffer_i < fw->size) { + if (pattern[pattern_i] == (char) fw_buffer[buffer_i]) { buffer_i++; pattern_i++; } if (pattern_i == pattern_len) { break; // pattern found - } else if ((buffer_i < buffer_len) && - (pattern[pattern_i] != fw_buffer[buffer_i])) { + } else if ((buffer_i < fw->size) && + (pattern[pattern_i] != (char) fw_buffer[buffer_i])) { // mismatch after pattern_i matches if (pattern_i != 0) { // since the pattern has no common prefix, when mismatch, @@ -93,22 +85,28 @@ int get_firmware_version(char *fw_buffer, uint32_t buffer_len, char *fw_version) } } } - kfree(pattern); if (pattern_i == pattern_len) { buffer_i++; version_start = buffer_i; - while (buffer_i < buffer_len) { - if (fw_buffer[buffer_i] == space_ch[0]) { + while (buffer_i < fw->size) { + if (fw_buffer[buffer_i] == SPACE_CH) { version_len = buffer_i - version_start; - strscpy(fw_version, fw_buffer + version_start, version_len + 1); + if (version_len >= TSSE_FW_VERSION_LEN - 1) + version_len = TSSE_FW_VERSION_LEN - 2; + strscpy(fw_version_out, fw_buffer + version_start, version_len + 1); return 0; } buffer_i++; } } - return -1; + return -EINVAL; } +/** + * Firmware service to handle IPC message from mainCPU. + * It will write init or manual load firmware to PCIe BAR and send message back. + * No return value. +*/ void fw_service(void *tsseipc_t, void *msg_t) { void __iomem *fw; @@ -120,16 +118,15 @@ void fw_service(void *tsseipc_t, void *msg_t) struct ipc_msg *msg = (struct ipc_msg *)msg_t; task_offset = sizeof(struct msg_info); - fw_task = (struct fw_load *)(msg->i_data + - task_offset / sizeof(uint32_t)); - + fw_task = (struct fw_load *)((uint8_t *)msg->i_data + task_offset); tdev = pci_to_tsse_dev(tsseipc->pdev); + if (!tdev || !tdev->fw) { fw_task->result = 1; fw_task->size = 0; dev_info(tsseipc->dev, "firmware loading failed\n"); - fw_send_msg(tsseipc, msg); - fw_free(msg); + if (fw_send_msg(tsseipc, msg)) + dev_err(tsseipc->dev, "notify device failed\n"); return; } @@ -140,24 +137,33 @@ void fw_service(void *tsseipc_t, void *msg_t) memcpy_toio((u8 *)fw, tdev->fw->data, size); dev_info(tsseipc->dev, "firmware loading done\n"); - fw_send_msg(tsseipc, msg); - fw_free(msg); + if (fw_send_msg(tsseipc, msg)) + dev_err(tsseipc->dev, "notify device failed\n"); - dev_info(tsseipc->dev, "firmware version: %s\n", tdev->fw_version); + if (tdev->fw_version_exist) + dev_info(tsseipc->dev, "firmware version: %s\n", tdev->fw_version); if (tdev->fw) { release_firmware(tdev->fw); tdev->fw = NULL; + memset(tdev->fw_version, 0, TSSE_FW_VERSION_LEN); + tdev->fw_version_exist = false; } } -int tsse_fw_load(struct pci_dev *pdev) +/** + * Load firmware from /lib/firmware + * @pdev: pci device + * @name: firmware file name + * @fw: pointer to firmware pointer + * Return: 0 on success, error code otherwise +*/ +int tsse_fw_load(struct pci_dev *pdev, const char *name, const struct firmware **fw) { int result; - struct tsse_dev *tdev = pci_to_tsse_dev(pdev); - result = request_firmware(&tdev->fw, TSSE_FIRMWARE, &pdev->dev); + result = request_firmware(fw, name, &pdev->dev); if (result) - dev_err(&pdev->dev, "%s failed\n", __func__); + dev_err(&pdev->dev, "%s failed for %s\n", __func__, name); return result; } diff --git a/drivers/crypto/montage/tsse/tsse_fw_service.h b/drivers/crypto/montage/tsse/tsse_fw_service.h index 973ca6a0bce9..706ea6d29769 100644 --- a/drivers/crypto/montage/tsse/tsse_fw_service.h +++ b/drivers/crypto/montage/tsse/tsse_fw_service.h @@ -8,10 +8,12 @@ #ifndef __TSSE_FW_SERVICE_H__ #define __TSSE_FW_SERVICE_H__ +#include + #define FW_BASE 0x7000000 #define TSSE_FIRMWARE "tsse_firmware.bin" void fw_service(void *tsseipc_t, void *msg_t); -int tsse_fw_load(struct pci_dev *pdev); -int get_firmware_version(char *fw_buffer, uint32_t buffer_len, char *fw_version); +int tsse_fw_load(struct pci_dev *pdev, const char *name, const struct firmware **fw); +int get_firmware_version(const struct firmware *fw, char *fw_version_out); #endif diff --git a/drivers/crypto/montage/tsse/tsse_ipc.c b/drivers/crypto/montage/tsse/tsse_ipc.c index 4cac3f61d8df..3e7f29052854 100644 --- a/drivers/crypto/montage/tsse/tsse_ipc.c +++ b/drivers/crypto/montage/tsse/tsse_ipc.c @@ -14,60 +14,41 @@ #include "tsse_dev.h" #include "tsse_service.h" -static struct tsse_msg *get_msginf(void __iomem *d2h) +/** + * Create ipc_msg and read message from BAR. + * Return the pointer to ipc_msg, the caller is responsible for free it. +*/ +static struct ipc_msg *get_msginf(void __iomem *d2h) { - uint32_t u_len; - struct tsse_msg *tssemsg; + uint32_t u_len = 0; + struct ipc_msg *msg = NULL; + uint8_t *device_msg_data = NULL; struct ipc_header *ipc_info = (struct ipc_header *)d2h; + // The memory layout in d2h should at least contains: + // ipc_header, msg_info and fw_load (message body) + if (ipc_info->i_len < sizeof(struct ipc_header) + + sizeof(struct msg_info) + sizeof(struct fw_load)) { + pr_info("%s(): msg format error\n", __func__); + return NULL; + } u_len = ipc_info->i_len - sizeof(struct ipc_header); - - tssemsg = (struct tsse_msg *)(kzalloc(sizeof(struct tsse_msg) + u_len, + msg = (struct ipc_msg *)(kzalloc(sizeof(struct ipc_msg) + u_len, GFP_ATOMIC)); - - if (!tssemsg) { - pr_info("%s(): tssemsg kzalloc failed\n", __func__); + if (!msg) { + pr_info("%s(): ipc_msg kzalloc failed\n", __func__); return NULL; } - tssemsg->ipc_payload.header.inst_id = ipc_info->inst_id; - tssemsg->ipc_payload.header.tgid = ipc_info->tgid; - tssemsg->ipc_payload.header.i_len = ipc_info->i_len; - - return tssemsg; -} - -static void ipc_recieve_msg(struct tsse_ipc *tsseipc, struct ipc_msg *msg) -{ - uint32_t u_len = msg->header.i_len - sizeof(struct ipc_header); - uint32_t *msg_data = NULL; - void __iomem *d2h = tsseipc->virt_addr + MAIN2HOST_IPC_OFFSET; - - msg_data = (uint32_t *)(d2h + sizeof(struct ipc_header)); - memcpy_fromio(msg->i_data, msg_data, u_len); - return; - -} - -static int msg_rout(struct tsse_ipc *tsseipc, struct tsse_msg *tssemsg) -{ - int ret = 0; - struct ipc_msg *msg; - struct msg_info *info; - uint32_t msg_class; - - msg = &tssemsg->ipc_payload; + msg->header.inst_id = ipc_info->inst_id; + msg->header.tgid = ipc_info->tgid; + msg->header.i_len = ipc_info->i_len; - ipc_recieve_msg(tsseipc, msg); - info = (struct msg_info *)msg->i_data; - msg_class = info->msg_class; - if (msg_class == IPC_MESSAGE_BOOT) { - service_rout(tsseipc, msg); - return 0; - } + device_msg_data = (uint8_t *)(d2h + sizeof(struct ipc_header)); + memcpy_fromio((uint8_t *)msg->i_data, device_msg_data, u_len); - return ret; + return msg; } static irqreturn_t tsse_ipc_d2h_irqhandler(int irq, void *dev_id) @@ -90,7 +71,6 @@ bool check_send_enbit(struct tsse_ipc *tsseipc) else return false; } -EXPORT_SYMBOL(check_send_enbit); void notify_device(struct tsse_ipc *tsseipc) { @@ -98,8 +78,11 @@ void notify_device(struct tsse_ipc *tsseipc) return; } -EXPORT_SYMBOL(notify_device); +/** + * Enable main2host interrupt, cleanup interrupt set value in host2main and main2host. + * No return value. +*/ static void ipc_hw_init(struct tsse_ipc *hw_ipc) { writel(0x1, hw_ipc->virt_addr + MAIN2HOST_INTR_ENABLE_OFFSET); @@ -111,37 +94,35 @@ static int ipc_init_msg(struct tsse_ipc *tsseipc) { u8 *h2d; u32 int_reg; - u32 rc; u32 cmd_len; + u32 i_len; struct ipc_msg *msg; struct msg_info *info_msg; - msg = (struct ipc_msg *)(kzalloc( - sizeof(struct ipc_msg) + sizeof(struct msg_info), GFP_ATOMIC)); + cmd_len = sizeof(uint32_t); + i_len = sizeof(struct ipc_header) + sizeof(struct msg_info) + cmd_len; + msg = (struct ipc_msg *)(kzalloc(i_len, GFP_ATOMIC)); if (!msg) { pr_info("%s(): msg kzalloc failed\n", __func__); - return -1; + return -EFAULT; } - cmd_len = sizeof(uint32_t); - msg->header.i_len = - sizeof(struct ipc_header) + sizeof(struct msg_info) + cmd_len; + msg->header.i_len = i_len; info_msg = (struct msg_info *)msg->i_data; info_msg->msg_class = IPC_MESSAGE_BASIC; - *(msg->i_data + sizeof(struct msg_info) / 4) = IPC_BASIC_CMD_HOST_INIT; + *(uint32_t *)((uint8_t *)msg->i_data + sizeof(struct msg_info)) = IPC_BASIC_CMD_HOST_INIT; mutex_lock(&tsseipc->list_lock); int_reg = readl(tsseipc->virt_addr + HOST2MAIN_INTR_SET_OFFSET); if ((int_reg & IPC_REGISTER_INT_SET) != 0) { - rc = -1; mutex_unlock(&tsseipc->list_lock); kfree(msg); - return rc; + return -EFAULT; } h2d = (u8 *)(tsseipc->virt_addr + HOST2MAIN_IPC_OFFSET); memcpy_toio(h2d, msg, sizeof(struct ipc_header)); - memcpy_toio(h2d + sizeof(struct ipc_header), (u32 *)msg->i_data, + memcpy_toio(h2d + sizeof(struct ipc_header), (u8 *)msg->i_data, sizeof(struct msg_info) + sizeof(uint32_t)); writel(0x1, tsseipc->virt_addr + HOST2MAIN_INTR_SET_OFFSET); @@ -156,13 +137,15 @@ static void tsse_ipc_bh_handler(unsigned long data) struct tsse_ipc *tsseipc = (struct tsse_ipc *)data; void __iomem *d2h_payload = tsseipc->virt_addr + MAIN2HOST_IPC_OFFSET; - struct tsse_msg *msg_tsse = get_msginf(d2h_payload); + struct ipc_msg *msg = get_msginf(d2h_payload); - if (!msg_tsse) { + if (!msg) { dev_err(tsseipc->dev, "get_msginf is NULL\n"); return; } - msg_rout(tsseipc, msg_tsse); + if (service_rout(tsseipc, msg)) + dev_err(tsseipc->dev, "illegal message class\n"); + kfree(msg); } int tsse_ipc_init(struct pci_dev *pdev) @@ -186,12 +169,18 @@ int tsse_ipc_init(struct pci_dev *pdev) rc = request_threaded_irq(pci_irq_vector(pdev, 0), NULL, tsse_ipc_d2h_irqhandler, IRQF_SHARED, "pf-ipc", ipc); + if (rc) { + dev_err(&pdev->dev, "request_threaded_irq failed\n"); + return rc; + } ipc_hw_init(ipc); - ipc_init_msg(ipc); - + rc = ipc_init_msg(ipc); + if (rc) { + dev_err(&pdev->dev, "ipc_init_msg failed\n"); + tsse_ipc_deinit(tdev); + } return rc; } -EXPORT_SYMBOL_GPL(tsse_ipc_init); void tsse_ipc_deinit(void *tdev_t) { @@ -202,8 +191,23 @@ void tsse_ipc_deinit(void *tdev_t) tdev = tdev_t; tsseipc = tdev->ipc; pdev = tsseipc->pdev; - free_irq(pci_irq_vector(pdev, 0), tdev->ipc); - return; + if (tsseipc) { + free_irq(pci_irq_vector(pdev, 0), tdev->ipc); + tdev->ipc = NULL; + } +} +int tsse_fw_manual_load_ipc(struct pci_dev *pdev) +{ + struct tsse_dev *tdev = pci_to_tsse_dev(pdev); + struct tsse_ipc *ipc = tdev->ipc; + int rc = -EFAULT; + + if (ipc) { + ipc_hw_init(ipc); + rc = ipc_init_msg(ipc); + if (rc) + dev_err(&pdev->dev, "ipc_init_msg failed\n"); + } + return rc; } -EXPORT_SYMBOL_GPL(tsse_ipc_deinit); diff --git a/drivers/crypto/montage/tsse/tsse_ipc.h b/drivers/crypto/montage/tsse/tsse_ipc.h index 59dcbf6eafc4..82f8df71c983 100644 --- a/drivers/crypto/montage/tsse/tsse_ipc.h +++ b/drivers/crypto/montage/tsse/tsse_ipc.h @@ -38,11 +38,11 @@ enum IPC_BASIC_CMD { IPC_BASIC_CMD_HOST_INIT = 0x1, - IPC_BASIC_CMD_PING = 0x2, + IPC_BASIC_CMD_PING = 0x2 }; enum IPC_BOOT_CMD { - IPC_BOOT_CMD_GET_FIRMWARE = 0x1, + IPC_BOOT_CMD_GET_FIRMWARE = 0x1 }; enum IPC_MESSAGE_CLASS { @@ -62,11 +62,6 @@ struct ipc_header { uint32_t reserved[2]; }; -struct ipc_data { - struct ipc_header header; - void *i_ptr; -}; - struct ipc_msg { struct ipc_header header; uint32_t i_data[]; @@ -92,11 +87,6 @@ struct ipc_layout { struct msg_info info; }; -struct tsse_msg { - struct list_head list; - struct ipc_msg ipc_payload; -}; - struct tsse_ipc { struct device *dev; struct pci_dev *pdev; @@ -107,6 +97,7 @@ struct tsse_ipc { int tsse_ipc_init(struct pci_dev *pdev); void tsse_ipc_deinit(void *tdev); +int tsse_fw_manual_load_ipc(struct pci_dev *pdev); bool check_send_enbit(struct tsse_ipc *tsseipc); void notify_device(struct tsse_ipc *tsseipc); #endif -- Gitee