From ecef24aa6215f786549243d02f5a470a8b2d0c8a Mon Sep 17 00:00:00 2001 From: Ingrid Gallardo Date: Fri, 16 Sep 2022 14:59:56 -0700 Subject: [PATCH] mm-drivers: hw_fence: update ipc regs config to support phys-id Starting pineapple, each ipc client has a different physical-id and virtual-id for registers access and configuration. This change updates the ipc to handle this different configuration. Change-Id: I36fa84b07ffd209ce3fb323ff796f9e7721d7dd2 Signed-off-by: Ingrid Gallardo --- hw_fence/include/hw_fence_drv_debug.h | 33 ++-- hw_fence/include/hw_fence_drv_ipc.h | 37 +++- hw_fence/include/hw_fence_drv_priv.h | 12 +- hw_fence/src/hw_fence_drv_debug.c | 20 ++- hw_fence/src/hw_fence_drv_ipc.c | 235 ++++++++++++++++++-------- hw_fence/src/hw_fence_drv_priv.c | 4 +- hw_fence/src/hw_fence_ioctl.c | 11 +- hw_fence/src/msm_hw_fence.c | 21 ++- 8 files changed, 252 insertions(+), 121 deletions(-) diff --git a/hw_fence/include/hw_fence_drv_debug.h b/hw_fence/include/hw_fence_drv_debug.h index de0e6e7a37..4f22b94664 100644 --- a/hw_fence/include/hw_fence_drv_debug.h +++ b/hw_fence/include/hw_fence_drv_debug.h @@ -69,7 +69,8 @@ int process_validation_client_loopback(struct hw_fence_driver_data *drv_data, in extern const struct file_operations hw_sync_debugfs_fops; struct hw_fence_out_clients_map { - int ipc_client_id; /* ipc client id for the hw fence client */ + int ipc_client_id_vid; /* ipc client virtual id for the hw fence client */ + int ipc_client_id_pid; /* ipc client physical id for the hw fence client */ int ipc_signal_id; /* ipc signal id for the hw fence client */ }; @@ -81,21 +82,21 @@ struct hw_fence_out_clients_map { */ static const struct hw_fence_out_clients_map dbg_out_clients_signal_map_no_dpu[HW_FENCE_CLIENT_MAX] = { - {HW_FENCE_IPC_CLIENT_ID_APPS, 0}, /* CTRL_LOOPBACK */ - {HW_FENCE_IPC_CLIENT_ID_GPU, 0}, /* CTX0 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 2}, /* CTL0 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 4}, /* CTL1 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 6}, /* CTL2 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 8}, /* CTL3 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 10}, /* CTL4 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 12}, /* CTL5 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 21}, /* VAL0 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 22}, /* VAL1 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 23}, /* VAL2 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 24}, /* VAL3 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 25}, /* VAL4 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 26}, /* VAL5 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 27}, /* VAL6 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 0}, /* CTRL_LOOPBACK */ + {HW_FENCE_IPC_CLIENT_ID_GPU_VID, HW_FENCE_IPC_CLIENT_ID_GPU_VID, 0}, /* CTX0 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 2}, /* CTL0 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 4}, /* CTL1 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 6}, /* CTL2 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 8}, /* CTL3 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 10}, /* CTL4 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 12}, /* CTL5 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 21}, /* VAL0 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 22}, /* VAL1 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 23}, /* VAL2 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 24}, /* VAL3 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 25}, /* VAL4 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 26}, /* VAL5 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 27}, /* VAL6 */ }; /** diff --git a/hw_fence/include/hw_fence_drv_ipc.h b/hw_fence/include/hw_fence_drv_ipc.h index 8a3f922b36..e905ea8ed6 100644 --- a/hw_fence/include/hw_fence_drv_ipc.h +++ b/hw_fence/include/hw_fence_drv_ipc.h @@ -6,17 +6,26 @@ #ifndef __HW_FENCE_DRV_IPC_H #define __HW_FENCE_DRV_IPC_H -#define HW_FENCE_IPC_CLIENT_ID_APPS 8 -#define HW_FENCE_IPC_CLIENT_ID_GPU 9 -#define HW_FENCE_IPC_CLIENT_ID_DPU 25 +/* ipc clients virtual client-id */ +#define HW_FENCE_IPC_CLIENT_ID_APPS_VID 8 +#define HW_FENCE_IPC_CLIENT_ID_GPU_VID 9 +#define HW_FENCE_IPC_CLIENT_ID_DPU_VID 25 + +/* ipc clients physical client-id */ +#define HW_FENCE_IPC_CLIENT_ID_APPS_PID 3 +#define HW_FENCE_IPC_CLIENT_ID_GPU_PID 4 +#define HW_FENCE_IPC_CLIENT_ID_DPU_PID 9 #define HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_LAHAINA 2 #define HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_WAIPIO 1 -#define HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_KAILUA 2 +#define HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_KALAMA 2 +#define HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_PINEAPPLE 2 +#define HW_FENCE_IPC_FENCE_PROTOCOL_ID_PINEAPPLE 4 #define HW_FENCE_IPCC_HW_REV_100 0x00010000 /* Lahaina */ #define HW_FENCE_IPCC_HW_REV_110 0x00010100 /* Waipio */ -#define HW_FENCE_IPCC_HW_REV_170 0x00010700 /* Kailua */ +#define HW_FENCE_IPCC_HW_REV_170 0x00010700 /* Kalama */ +#define HW_FENCE_IPCC_HW_REV_203 0x00020003 /* Pineapple */ #define IPC_PROTOCOLp_CLIENTc_VERSION(base, p, c) (base + (0x40000*p) + (0x1000*c)) #define IPC_PROTOCOLp_CLIENTc_CONFIG(base, p, c) (base + 0x8 + (0x40000*p) + (0x1000*c)) @@ -55,8 +64,8 @@ int hw_fence_ipcc_enable_dpu_signaling(struct hw_fence_driver_data *drv_data); #endif /* HW_DPU_IPCC */ /** - * hw_fence_ipcc_get_client_id() - Returns the ipc client id that corresponds to the hw fence - * driver client. + * hw_fence_ipcc_get_client_virt_id() - Returns the ipc client virtual id that corresponds to the + * hw fence driver client. * @drv_data: driver data. * @client_id: hw fence driver client id. * @@ -64,7 +73,19 @@ int hw_fence_ipcc_enable_dpu_signaling(struct hw_fence_driver_data *drv_data); * * Return: client_id on success or negative errno (-EINVAL) */ -int hw_fence_ipcc_get_client_id(struct hw_fence_driver_data *drv_data, u32 client_id); +int hw_fence_ipcc_get_client_virt_id(struct hw_fence_driver_data *drv_data, u32 client_id); + +/** + * hw_fence_ipcc_get_client_phys_id() - Returns the ipc client physical id that corresponds to the + * hw fence driver client. + * @drv_data: driver data. + * @client_id: hw fence driver client id. + * + * The ipc client id returned by this API is used by the hw fence driver when signaling the fence. + * + * Return: client_id on success or negative errno (-EINVAL) + */ +int hw_fence_ipcc_get_client_phys_id(struct hw_fence_driver_data *drv_data, u32 client_id); /** * hw_fence_ipcc_get_signal_id() - Returns the ipc signal id that corresponds to the hw fence diff --git a/hw_fence/include/hw_fence_drv_priv.h b/hw_fence/include/hw_fence_drv_priv.h index de978eb316..14a302871d 100644 --- a/hw_fence/include/hw_fence_drv_priv.h +++ b/hw_fence/include/hw_fence_drv_priv.h @@ -148,7 +148,8 @@ enum payload_type { * @mem_descriptor: hfi header memory descriptor * @queues: queues descriptor * @ipc_signal_id: id of the signal to be triggered for this client - * @ipc_client_id: id of the ipc client for this hw fence driver client + * @ipc_client_vid: virtual id of the ipc client for this hw fence driver client + * @ipc_client_pid: physical id of the ipc client for this hw fence driver client * @update_rxq: bool to indicate if client uses rx-queue * @send_ipc: bool to indicate if client requires ipc interrupt for already signaled fences * @wait_queue: wait queue for the validation clients @@ -159,7 +160,8 @@ struct msm_hw_fence_client { struct msm_hw_fence_mem_addr mem_descriptor; struct msm_hw_fence_queue queues[HW_FENCE_CLIENT_QUEUES]; int ipc_signal_id; - int ipc_client_id; + int ipc_client_vid; + int ipc_client_pid; bool update_rxq; bool send_ipc; #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -238,7 +240,8 @@ struct msm_hw_fence_dbg_data { * @ipcc_io_mem: base for the ipcc io mem map * @ipcc_size: size of the ipcc io mem mapping * @protocol_id: ipcc protocol id used by this driver - * @ipcc_client_id: ipcc client id for this driver + * @ipcc_client_vid: ipcc client virtual-id for this driver + * @ipcc_client_pid: ipcc client physical-id for this driver * @ipc_clients_table: table with the ipcc mapping for each client of this driver * @qtime_reg_base: qtimer register base address * @qtime_io_mem: qtimer io mem map @@ -304,7 +307,8 @@ struct hw_fence_driver_data { void __iomem *ipcc_io_mem; uint32_t ipcc_size; u32 protocol_id; - u32 ipcc_client_id; + u32 ipcc_client_vid; + u32 ipcc_client_pid; /* table with mapping of ipc client for each hw-fence client */ struct hw_fence_client_ipc_map *ipc_clients_table; diff --git a/hw_fence/src/hw_fence_drv_debug.c b/hw_fence/src/hw_fence_drv_debug.c index 2dd3ae4ec6..a1db824278 100644 --- a/hw_fence/src/hw_fence_drv_debug.c +++ b/hw_fence/src/hw_fence_drv_debug.c @@ -106,8 +106,10 @@ static int _debugfs_ipcc_trigger(struct file *file, const char __user *user_buf, static ssize_t hw_fence_dbg_ipcc_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - return _debugfs_ipcc_trigger(file, user_buf, count, ppos, HW_FENCE_IPC_CLIENT_ID_APPS, - HW_FENCE_IPC_CLIENT_ID_APPS); + struct hw_fence_driver_data *drv_data = file->private_data; + + return _debugfs_ipcc_trigger(file, user_buf, count, ppos, drv_data->ipcc_client_pid, + drv_data->ipcc_client_vid); } #ifdef HW_DPU_IPCC @@ -124,8 +126,10 @@ static ssize_t hw_fence_dbg_ipcc_write(struct file *file, const char __user *use static ssize_t hw_fence_dbg_ipcc_dpu_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - return _debugfs_ipcc_trigger(file, user_buf, count, ppos, HW_FENCE_IPC_CLIENT_ID_APPS, - HW_FENCE_IPC_CLIENT_ID_DPU); + struct hw_fence_driver_data *drv_data = file->private_data; + + return _debugfs_ipcc_trigger(file, user_buf, count, ppos, drv_data->ipcc_client_pid, + hw_fence_ipcc_get_client_virt_id(drv_data, HW_FENCE_CLIENT_ID_CTL0)); } @@ -361,8 +365,8 @@ static ssize_t hw_fence_dbg_tx_and_signal_clients_wr(struct file *file, return -EINVAL; /* Write to ipcc to trigger the irq */ - tx_client = HW_FENCE_IPC_CLIENT_ID_APPS; - rx_client = HW_FENCE_IPC_CLIENT_ID_APPS; + tx_client = drv_data->ipcc_client_pid; + rx_client = drv_data->ipcc_client_vid; HWFNC_DBG_IRQ("client:%d tx_client:%d rx_client:%d signal:%d delay:%d in_data%d\n", client_id_src, tx_client, rx_client, signal_id, drv_data->debugfs_data.hw_fence_sim_release_delay, input_data); @@ -866,8 +870,8 @@ static ssize_t hw_fence_dbg_create_join_fence(struct file *file, } /* write to ipcc to trigger the irq */ - tx_client = HW_FENCE_IPC_CLIENT_ID_APPS; - rx_client = HW_FENCE_IPC_CLIENT_ID_APPS; + tx_client = drv_data->ipcc_client_pid; + rx_client = drv_data->ipcc_client_vid; hw_fence_ipcc_trigger_signal(drv_data, tx_client, rx_client, signal_id); usleep_range(drv_data->debugfs_data.hw_fence_sim_release_delay, diff --git a/hw_fence/src/hw_fence_drv_ipc.c b/hw_fence/src/hw_fence_drv_ipc.c index a36163db88..a3cccfbf31 100644 --- a/hw_fence/src/hw_fence_drv_ipc.c +++ b/hw_fence/src/hw_fence_drv_ipc.c @@ -3,6 +3,7 @@ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ +#include #include "hw_fence_drv_priv.h" #include "hw_fence_drv_utils.h" #include "hw_fence_drv_ipc.h" @@ -10,13 +11,15 @@ /** * struct hw_fence_client_ipc_map - map client id with ipc signal for trigger. - * @ipc_client_id: ipc client id for the hw-fence client. + * @ipc_client_id_virt: virtual ipc client id for the hw-fence client. + * @ipc_client_id_phys: physical ipc client id for the hw-fence client. * @ipc_signal_id: ipc signal id for the hw-fence client. * @update_rxq: bool to indicate if clinet uses rx-queue. * @send_ipc: bool to indicate if client requires ipc interrupt for signaled fences */ struct hw_fence_client_ipc_map { - int ipc_client_id; + int ipc_client_id_virt; + int ipc_client_id_phys; int ipc_signal_id; bool update_rxq; bool send_ipc; @@ -34,22 +37,22 @@ struct hw_fence_client_ipc_map { * {HW_FENCE_IPC_CLIENT_ID_APPS, 20}. */ struct hw_fence_client_ipc_map hw_fence_clients_ipc_map_no_dpu[HW_FENCE_CLIENT_MAX] = { - {HW_FENCE_IPC_CLIENT_ID_APPS, 1, true, true}, /* ctrl queue loopback */ - {HW_FENCE_IPC_CLIENT_ID_GPU, 0, false, false}, /* ctx0 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 14, false, true}, /* ctl0 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 15, false, true}, /* ctl1 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 16, false, true}, /* ctl2 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 17, false, true}, /* ctl3 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 18, false, true}, /* ctl4 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 19, false, true}, /* ctl5 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 1, true, true},/* ctrlq*/ + {HW_FENCE_IPC_CLIENT_ID_GPU_VID, HW_FENCE_IPC_CLIENT_ID_GPU_VID, 0, false, false},/* ctx0 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 14, false, true},/*ctl0*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 15, false, true},/*ctl1*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 16, false, true},/*ctl2*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 17, false, true},/*ctl3*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 18, false, true},/*ctl4*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 19, false, true},/*ctl5*/ #if IS_ENABLED(CONFIG_DEBUG_FS) - {HW_FENCE_IPC_CLIENT_ID_APPS, 21, true, true}, /* val0 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 22, true, true}, /* val1 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 23, true, true}, /* val2 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 24, true, true}, /* val3 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 25, true, true}, /* val4 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 26, true, true}, /* val5 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 27, true, true}, /* val6 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 21, true, true},/* val0*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 22, true, true},/* val1*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 23, true, true},/* val2*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 24, true, true},/* val3*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 25, true, true},/* val4*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 26, true, true},/* val5*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 27, true, true},/* val6*/ #endif /* CONFIG_DEBUG_FS */ }; @@ -62,31 +65,67 @@ struct hw_fence_client_ipc_map hw_fence_clients_ipc_map_no_dpu[HW_FENCE_CLIENT_M * Note that the index of this struct must match the enum hw_fence_client_id */ struct hw_fence_client_ipc_map hw_fence_clients_ipc_map[HW_FENCE_CLIENT_MAX] = { - {HW_FENCE_IPC_CLIENT_ID_APPS, 1, true, true}, /* ctrl queue loopback */ - {HW_FENCE_IPC_CLIENT_ID_GPU, 0, false, false}, /* ctx0 */ - {HW_FENCE_IPC_CLIENT_ID_DPU, 0, false, true}, /* ctl0 */ - {HW_FENCE_IPC_CLIENT_ID_DPU, 1, false, true}, /* ctl1 */ - {HW_FENCE_IPC_CLIENT_ID_DPU, 2, false, true}, /* ctl2 */ - {HW_FENCE_IPC_CLIENT_ID_DPU, 3, false, true}, /* ctl3 */ - {HW_FENCE_IPC_CLIENT_ID_DPU, 4, false, true}, /* ctl4 */ - {HW_FENCE_IPC_CLIENT_ID_DPU, 5, false, true}, /* ctl5 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 1, true, true},/*ctrl q*/ + {HW_FENCE_IPC_CLIENT_ID_GPU_VID, HW_FENCE_IPC_CLIENT_ID_GPU_VID, 0, false, false},/*ctx0 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 0, false, true},/* ctl0 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 1, false, true},/* ctl1 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 2, false, true},/* ctl2 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 3, false, true},/* ctl3 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 4, false, true},/* ctl4 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 5, false, true},/* ctl5 */ #if IS_ENABLED(CONFIG_DEBUG_FS) - {HW_FENCE_IPC_CLIENT_ID_APPS, 21, true, true}, /* val0 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 22, true, true}, /* val1 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 23, true, true}, /* val2 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 24, true, true}, /* val3 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 25, true, true}, /* val4 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 26, true, true}, /* val5 */ - {HW_FENCE_IPC_CLIENT_ID_APPS, 27, true, true}, /* val6 */ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 21, true, true},/* val0*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 22, true, true},/* val1*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 23, true, true},/* val2*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 24, true, true},/* val3*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 25, true, true},/* val4*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 26, true, true},/* val5*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 27, true, true},/* val6*/ #endif /* CONFIG_DEBUG_FS */ }; -int hw_fence_ipcc_get_client_id(struct hw_fence_driver_data *drv_data, u32 client_id) +/** + * struct hw_fence_clients_ipc_map_v2 - Table makes the 'client to signal' mapping, which is + * used by the hw fence driver to trigger ipc signal when hw fence is already + * signaled. + * This version is for targets that support dpu client id and IPC v2. + * + * Note that the index of this struct must match the enum hw_fence_client_id + */ +struct hw_fence_client_ipc_map hw_fence_clients_ipc_map_v2[HW_FENCE_CLIENT_MAX] = { + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 1, true, true},/*ctrlq */ + {HW_FENCE_IPC_CLIENT_ID_GPU_VID, HW_FENCE_IPC_CLIENT_ID_GPU_PID, 0, false, false},/* ctx0*/ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 0, false, true},/* ctl0 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 1, false, true},/* ctl1 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 2, false, true},/* ctl2 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 3, false, true},/* ctl3 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 4, false, true},/* ctl4 */ + {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 5, false, true},/* ctl5 */ +#if IS_ENABLED(CONFIG_DEBUG_FS) + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 21, true, true},/* val0*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 22, true, true},/* val1*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 23, true, true},/* val2*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 24, true, true},/* val3*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 25, true, true},/* val4*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 26, true, true},/* val5*/ + {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 27, true, true},/* val6*/ +#endif /* CONFIG_DEBUG_FS */ +}; + +int hw_fence_ipcc_get_client_virt_id(struct hw_fence_driver_data *drv_data, u32 client_id) { if (!drv_data || client_id >= HW_FENCE_CLIENT_MAX) return -EINVAL; - return drv_data->ipc_clients_table[client_id].ipc_client_id; + return drv_data->ipc_clients_table[client_id].ipc_client_id_virt; +} + +int hw_fence_ipcc_get_client_phys_id(struct hw_fence_driver_data *drv_data, u32 client_id) +{ + if (!drv_data || client_id >= HW_FENCE_CLIENT_MAX) + return -EINVAL; + + return drv_data->ipc_clients_table[client_id].ipc_client_id_phys; } int hw_fence_ipcc_get_signal_id(struct hw_fence_driver_data *drv_data, u32 client_id) @@ -114,36 +153,53 @@ bool hw_fence_ipcc_needs_ipc_irq(struct hw_fence_driver_data *drv_data, int clie } /** - * _get_ipc_client_name() - Returns ipc client name, used for debugging. + * _get_ipc_phys_client_name() - Returns ipc client name from its physical id, used for debugging. */ -static inline char *_get_ipc_client_name(u32 client_id) +static inline char *_get_ipc_phys_client_name(u32 client_id) { switch (client_id) { - case HW_FENCE_IPC_CLIENT_ID_APPS: - return "APPS"; - case HW_FENCE_IPC_CLIENT_ID_GPU: - return "GPU"; - case HW_FENCE_IPC_CLIENT_ID_DPU: - return "DPU"; + case HW_FENCE_IPC_CLIENT_ID_APPS_PID: + return "APPS_PID"; + case HW_FENCE_IPC_CLIENT_ID_GPU_PID: + return "GPU_PID"; + case HW_FENCE_IPC_CLIENT_ID_DPU_PID: + return "DPU_PID"; } - return "UNKNOWN"; + return "UNKNOWN_PID"; +} + +/** + * _get_ipc_virt_client_name() - Returns ipc client name from its virtual id, used for debugging. + */ +static inline char *_get_ipc_virt_client_name(u32 client_id) +{ + switch (client_id) { + case HW_FENCE_IPC_CLIENT_ID_APPS_VID: + return "APPS_VID"; + case HW_FENCE_IPC_CLIENT_ID_GPU_VID: + return "GPU_VID"; + case HW_FENCE_IPC_CLIENT_ID_DPU_VID: + return "DPU_VID"; + } + + return "UNKNOWN_VID"; } void hw_fence_ipcc_trigger_signal(struct hw_fence_driver_data *drv_data, - u32 tx_client_id, u32 rx_client_id, u32 signal_id) + u32 tx_client_pid, u32 rx_client_vid, u32 signal_id) { void __iomem *ptr; u32 val; /* Send signal */ ptr = IPC_PROTOCOLp_CLIENTc_SEND(drv_data->ipcc_io_mem, drv_data->protocol_id, - tx_client_id); - val = (rx_client_id << 16) | signal_id; + tx_client_pid); + val = (rx_client_vid << 16) | signal_id; HWFNC_DBG_IRQ("Sending ipcc from %s (%d) to %s (%d) signal_id:%d [wr:0x%x to off:0x%pK]\n", - _get_ipc_client_name(tx_client_id), tx_client_id, - _get_ipc_client_name(rx_client_id), rx_client_id, + _get_ipc_phys_client_name(tx_client_pid), tx_client_pid, + _get_ipc_virt_client_name(rx_client_vid), rx_client_vid, signal_id, val, ptr); HWFNC_DBG_H("Write:0x%x to RegOffset:0x%pK\n", val, ptr); writel_relaxed(val, ptr); @@ -162,22 +218,32 @@ static int _hw_fence_ipcc_hwrev_init(struct hw_fence_driver_data *drv_data, u32 { switch (hwrev) { case HW_FENCE_IPCC_HW_REV_100: - drv_data->ipcc_client_id = HW_FENCE_IPC_CLIENT_ID_APPS; + drv_data->ipcc_client_vid = HW_FENCE_IPC_CLIENT_ID_APPS_VID; + drv_data->ipcc_client_pid = HW_FENCE_IPC_CLIENT_ID_APPS_VID; drv_data->protocol_id = HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_LAHAINA; drv_data->ipc_clients_table = hw_fence_clients_ipc_map_no_dpu; HWFNC_DBG_INIT("ipcc protocol_id: Lahaina\n"); break; case HW_FENCE_IPCC_HW_REV_110: - drv_data->ipcc_client_id = HW_FENCE_IPC_CLIENT_ID_APPS; + drv_data->ipcc_client_vid = HW_FENCE_IPC_CLIENT_ID_APPS_VID; + drv_data->ipcc_client_pid = HW_FENCE_IPC_CLIENT_ID_APPS_VID; drv_data->protocol_id = HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_WAIPIO; drv_data->ipc_clients_table = hw_fence_clients_ipc_map_no_dpu; HWFNC_DBG_INIT("ipcc protocol_id: Waipio\n"); break; case HW_FENCE_IPCC_HW_REV_170: - drv_data->ipcc_client_id = HW_FENCE_IPC_CLIENT_ID_APPS; - drv_data->protocol_id = HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_KAILUA; + drv_data->ipcc_client_vid = HW_FENCE_IPC_CLIENT_ID_APPS_VID; + drv_data->ipcc_client_pid = HW_FENCE_IPC_CLIENT_ID_APPS_VID; + drv_data->protocol_id = HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_KALAMA; drv_data->ipc_clients_table = hw_fence_clients_ipc_map; - HWFNC_DBG_INIT("ipcc protocol_id: Kailua\n"); + HWFNC_DBG_INIT("ipcc protocol_id: Kalama\n"); + break; + case HW_FENCE_IPCC_HW_REV_203: + drv_data->ipcc_client_vid = HW_FENCE_IPC_CLIENT_ID_APPS_VID; + drv_data->ipcc_client_pid = HW_FENCE_IPC_CLIENT_ID_APPS_PID; + drv_data->protocol_id = HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_PINEAPPLE; /* Fence */ + drv_data->ipc_clients_table = hw_fence_clients_ipc_map_v2; + HWFNC_DBG_INIT("ipcc protocol_id: Pineapple\n"); break; default: return -1; @@ -190,13 +256,25 @@ int hw_fence_ipcc_enable_signaling(struct hw_fence_driver_data *drv_data) { void __iomem *ptr; u32 val; + int ret; HWFNC_DBG_H("enable ipc +\n"); - /* Read IPC Version from Client=0x8 (apps) for protocol=2 (compute_l1) */ - val = readl_relaxed(IPC_PROTOCOLp_CLIENTc_VERSION(drv_data->ipcc_io_mem, - HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_LAHAINA, HW_FENCE_IPC_CLIENT_ID_APPS)); - HWFNC_DBG_INIT("ipcc version:0x%x\n", val); + /** + * Attempt to read the ipc version from dt, if not available, then attempt + * to read from the registers. + */ + ret = of_property_read_u32(drv_data->dev->of_node, "qcom,hw-fence-ipc-ver", &val); + if (ret || !val) { + /* if no device tree prop, attempt to get the version from the registers*/ + HWFNC_DBG_H("missing hw fences ipc-ver entry or invalid ret:%d val:%d\n", ret, val); + + /* Read IPC Version from Client=0x8 (apps) for protocol=2 (compute_l1) */ + val = readl_relaxed(IPC_PROTOCOLp_CLIENTc_VERSION(drv_data->ipcc_io_mem, + HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_LAHAINA, + HW_FENCE_IPC_CLIENT_ID_APPS_VID)); + HWFNC_DBG_INIT("ipcc version:0x%x\n", val); + } if (_hw_fence_ipcc_hwrev_init(drv_data, val)) { HWFNC_ERR("ipcc protocol id not supported\n"); @@ -206,14 +284,14 @@ int hw_fence_ipcc_enable_signaling(struct hw_fence_driver_data *drv_data) /* Enable compute l1 (protocol_id = 2) */ val = 0x00000000; ptr = IPC_PROTOCOLp_CLIENTc_CONFIG(drv_data->ipcc_io_mem, drv_data->protocol_id, - HW_FENCE_IPC_CLIENT_ID_APPS); + drv_data->ipcc_client_pid); HWFNC_DBG_H("Write:0x%x to RegOffset:0x%pK\n", val, ptr); writel_relaxed(val, ptr); /* Enable Client-Signal pairs from APPS(NS) (0x8) to APPS(NS) (0x8) */ val = 0x000080000; ptr = IPC_PROTOCOLp_CLIENTc_RECV_SIGNAL_ENABLE(drv_data->ipcc_io_mem, drv_data->protocol_id, - HW_FENCE_IPC_CLIENT_ID_APPS); + drv_data->ipcc_client_pid); HWFNC_DBG_H("Write:0x%x to RegOffset:0x%pK\n", val, ptr); writel_relaxed(val, ptr); @@ -226,6 +304,7 @@ int hw_fence_ipcc_enable_signaling(struct hw_fence_driver_data *drv_data) int hw_fence_ipcc_enable_dpu_signaling(struct hw_fence_driver_data *drv_data) { struct hw_fence_client_ipc_map *hw_fence_client; + bool protocol_enabled = false; void __iomem *ptr; u32 val; int i; @@ -239,31 +318,41 @@ int hw_fence_ipcc_enable_dpu_signaling(struct hw_fence_driver_data *drv_data) HWFNC_DBG_H("ipcc_io_mem:0x%lx\n", (u64)drv_data->ipcc_io_mem); - /* - * Enable compute l1 (protocol_id = 2) for dpu (25) - * Sets bit(1) to clear when RECV_ID is read - */ - val = 0x00000001; - ptr = IPC_PROTOCOLp_CLIENTc_CONFIG(drv_data->ipcc_io_mem, drv_data->protocol_id, - HW_FENCE_IPC_CLIENT_ID_DPU); - HWFNC_DBG_H("Write:0x%x to RegOffset:0x%lx\n", val, (u64)ptr); - writel_relaxed(val, ptr); - HWFNC_DBG_H("Initialize dpu signals\n"); /* Enable Client-Signal pairs from DPU (25) to APPS(NS) (8) */ for (i = 0; i < HW_FENCE_CLIENT_MAX; i++) { hw_fence_client = &drv_data->ipc_clients_table[i]; /* skip any client that is not a dpu client */ - if (hw_fence_client->ipc_client_id != HW_FENCE_IPC_CLIENT_ID_DPU) + if (hw_fence_client->ipc_client_id_virt != HW_FENCE_IPC_CLIENT_ID_DPU_VID) continue; + if (!protocol_enabled) { + /* + * First DPU client will enable the protocol for dpu, e.g. compute l1 + * (protocol_id = 2) or fencing protocol, depending on the target, for the + * dpu client (vid = 25, pid = 9). + * Sets bit(1) to clear when RECV_ID is read + */ + val = 0x00000001; + ptr = IPC_PROTOCOLp_CLIENTc_CONFIG(drv_data->ipcc_io_mem, + drv_data->protocol_id, hw_fence_client->ipc_client_id_phys); + HWFNC_DBG_H("Write:0x%x to RegOffset:0x%lx\n", val, (u64)ptr); + writel_relaxed(val, ptr); + + protocol_enabled = true; + } + /* Enable signals for dpu client */ - HWFNC_DBG_H("dpu:%d client:%d signal:%d\n", hw_fence_client->ipc_client_id, i, + HWFNC_DBG_H("dpu client:%d vid:%d pid:%d signal:%d\n", i, + hw_fence_client->ipc_client_id_virt, hw_fence_client->ipc_client_id_phys, hw_fence_client->ipc_signal_id); - val = 0x000080000 | (hw_fence_client->ipc_signal_id & 0xFFFF); + + /* Enable input apps-signal for dpu */ + val = (HW_FENCE_IPC_CLIENT_ID_APPS_VID << 16) | + (hw_fence_client->ipc_signal_id & 0xFFFF); ptr = IPC_PROTOCOLp_CLIENTc_RECV_SIGNAL_ENABLE(drv_data->ipcc_io_mem, - drv_data->protocol_id, HW_FENCE_IPC_CLIENT_ID_DPU); + drv_data->protocol_id, hw_fence_client->ipc_client_id_phys); HWFNC_DBG_H("Write:0x%x to RegOffset:0x%lx\n", val, (u64)ptr); writel_relaxed(val, ptr); } diff --git a/hw_fence/src/hw_fence_drv_priv.c b/hw_fence/src/hw_fence_drv_priv.c index f820a824e5..c37374ade4 100644 --- a/hw_fence/src/hw_fence_drv_priv.c +++ b/hw_fence/src/hw_fence_drv_priv.c @@ -1047,8 +1047,8 @@ static void _fence_ctl_signal(struct hw_fence_driver_data *drv_data, struct msm_hw_fence_client *hw_fence_client, struct msm_hw_fence *hw_fence, u64 hash, u64 flags, u32 error) { - u32 tx_client_id = drv_data->ipcc_client_id; - u32 rx_client_id = hw_fence_client->ipc_client_id; + u32 tx_client_id = drv_data->ipcc_client_pid; /* phys id for tx client */ + u32 rx_client_id = hw_fence_client->ipc_client_vid; /* virt id for rx client */ HWFNC_DBG_H("We must signal the client now! hfence hash:%llu\n", hash); diff --git a/hw_fence/src/hw_fence_ioctl.c b/hw_fence/src/hw_fence_ioctl.c index 3ccd2dd7de..431bf658ed 100644 --- a/hw_fence/src/hw_fence_ioctl.c +++ b/hw_fence/src/hw_fence_ioctl.c @@ -546,6 +546,7 @@ static long hw_sync_ioctl_reg_for_wait(struct hw_sync_obj *obj, unsigned long ar static long hw_sync_ioctl_fence_signal(struct hw_sync_obj *obj, unsigned long arg) { + struct msm_hw_fence_client *hw_fence_client; struct hw_fence_sync_signal_data data; int ret, tx_client, rx_client, signal_id; @@ -556,6 +557,12 @@ static long hw_sync_ioctl_fence_signal(struct hw_sync_obj *obj, unsigned long ar return -EINVAL; } + hw_fence_client = (struct msm_hw_fence_client *)obj->client_handle; + if (!hw_fence_client) { + HWFNC_ERR("invalid client handle\n"); + return -EINVAL; + } + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; @@ -569,8 +576,8 @@ static long hw_sync_ioctl_fence_signal(struct hw_sync_obj *obj, unsigned long ar if (signal_id < 0) return -EINVAL; - tx_client = HW_FENCE_IPC_CLIENT_ID_APPS; - rx_client = HW_FENCE_IPC_CLIENT_ID_APPS; + tx_client = hw_fence_client->ipc_client_vid; + rx_client = hw_fence_client->ipc_client_pid; ret = msm_hw_fence_trigger_signal(obj->client_handle, tx_client, rx_client, signal_id); if (ret) { HWFNC_ERR("hw fence trigger signal has failed\n"); diff --git a/hw_fence/src/msm_hw_fence.c b/hw_fence/src/msm_hw_fence.c index 8eb520527f..8b8dfb0a59 100644 --- a/hw_fence/src/msm_hw_fence.c +++ b/hw_fence/src/msm_hw_fence.c @@ -54,10 +54,14 @@ void *msm_hw_fence_register(enum hw_fence_client_id client_id, mutex_unlock(&hw_fence_drv_data->clients_register_lock); hw_fence_client->client_id = client_id; - hw_fence_client->ipc_client_id = hw_fence_ipcc_get_client_id(hw_fence_drv_data, client_id); + hw_fence_client->ipc_client_vid = + hw_fence_ipcc_get_client_virt_id(hw_fence_drv_data, client_id); + hw_fence_client->ipc_client_pid = + hw_fence_ipcc_get_client_phys_id(hw_fence_drv_data, client_id); - if (hw_fence_client->ipc_client_id <= 0) { - HWFNC_ERR("Failed to find client:%d ipc id\n", client_id); + if (hw_fence_client->ipc_client_vid <= 0 || hw_fence_client->ipc_client_pid <= 0) { + HWFNC_ERR("Failed to find client:%d ipc vid:%d pid:%d\n", client_id, + hw_fence_client->ipc_client_vid, hw_fence_client->ipc_client_pid); ret = -EINVAL; goto error; } @@ -91,9 +95,9 @@ void *msm_hw_fence_register(enum hw_fence_client_id client_id, if (ret) goto error; - HWFNC_DBG_INIT("-- Initialized ptr:0x%p client_id:%d ipc_signal_id:%d ipc_client_id:%d\n", + HWFNC_DBG_INIT("-- Initialized ptr:0x%p client_id:%d ipc_signal_id:%d ipc vid:%d pid:%d\n", hw_fence_client, hw_fence_client->client_id, hw_fence_client->ipc_signal_id, - hw_fence_client->ipc_client_id); + hw_fence_client->ipc_client_vid, hw_fence_client->ipc_client_pid); #if IS_ENABLED(CONFIG_DEBUG_FS) init_waitqueue_head(&hw_fence_client->wait_queue); @@ -338,8 +342,9 @@ int msm_hw_fence_update_txq(void *client_handle, u64 handle, u64 flags, u32 erro } EXPORT_SYMBOL(msm_hw_fence_update_txq); +/* tx client has to be the physical, rx client virtual id*/ int msm_hw_fence_trigger_signal(void *client_handle, - u32 tx_client_id, u32 rx_client_id, + u32 tx_client_pid, u32 rx_client_vid, u32 signal_id) { struct msm_hw_fence_client *hw_fence_client; @@ -355,8 +360,8 @@ int msm_hw_fence_trigger_signal(void *client_handle, hw_fence_client = (struct msm_hw_fence_client *)client_handle; HWFNC_DBG_H("sending ipc for client:%d\n", hw_fence_client->client_id); - hw_fence_ipcc_trigger_signal(hw_fence_drv_data, tx_client_id, - rx_client_id, signal_id); + hw_fence_ipcc_trigger_signal(hw_fence_drv_data, tx_client_pid, + rx_client_vid, signal_id); return 0; }