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 <quic_ingridg@quicinc.com>
This commit is contained in:
Ingrid Gallardo
2022-09-16 14:59:56 -07:00
parent 54256aa9e0
commit ecef24aa62
8 changed files with 252 additions and 121 deletions

View File

@@ -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 */
};
/**

View File

@@ -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

View File

@@ -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;

View File

@@ -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,

View File

@@ -3,6 +3,7 @@
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/of_platform.h>
#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");
/**
* 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));
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);
}

View File

@@ -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);

View File

@@ -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");

View File

@@ -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;
}