replace common qcom sources with samsung ones

This commit is contained in:
SaschaNes
2025-08-12 22:13:00 +02:00
parent ba24dcded9
commit 6f7753de11
5682 changed files with 2450203 additions and 103634 deletions

View File

@@ -132,6 +132,13 @@
#define DMA_FENCE_HASH_TABLE_BIT (12) /* size of table = (1 << 12) = 4096 */
#define DMA_FENCE_HASH_TABLE_SIZE (1 << DMA_FENCE_HASH_TABLE_BIT)
enum hw_fence_lookup_ops {
HW_FENCE_LOOKUP_OP_CREATE = 0x1,
HW_FENCE_LOOKUP_OP_DESTROY,
HW_FENCE_LOOKUP_OP_CREATE_JOIN,
HW_FENCE_LOOKUP_OP_FIND_FENCE
};
/**
* enum hw_fence_client_data_id - Enum with the clients having client_data, an optional
* parameter passed from the waiting client and returned
@@ -251,7 +258,6 @@ struct msm_hw_fence_mem_data {
* @entry_rd: flag to indicate if debugfs dumps a single line or table
* @context_rd: debugfs setting to indicate which context id to dump
* @seqno_rd: debugfs setting to indicate which seqno to dump
* @client_id_rd: debugfs setting to indicate which client queue(s) to dump
* @hw_fence_sim_release_delay: delay in micro seconds for the debugfs node that simulates the
* hw-fences behavior, to release the hw-fences
* @create_hw_fences: boolean to continuosly create hw-fences within debugfs
@@ -265,7 +271,6 @@ struct msm_hw_fence_dbg_data {
bool entry_rd;
u64 context_rd;
u64 seqno_rd;
u32 client_id_rd;
u32 hw_fence_sim_release_delay;
bool create_hw_fences;
@@ -381,7 +386,6 @@ struct hw_fence_soccp {
* @clients_num: number of supported hw fence clients (configured based on device-tree)
* @hw_fences_tbl: pointer to the hw-fences table
* @hw_fences_tbl_cnt: number of elements in the hw-fence table
* @hlos_key_tbl: pointer to table of keys tracked by hlos only, same size as the hw-fences table
* @events: start address of hw fence debug events
* @total_events: total number of hw fence debug events supported
* @client_lock_tbl: pointer to the per-client locks table
@@ -448,7 +452,6 @@ struct hw_fence_driver_data {
/* HW Fences Table VA */
struct msm_hw_fence *hw_fences_tbl;
u64 *hlos_key_tbl;
u32 hw_fences_tbl_cnt;
/* events */
@@ -634,11 +637,11 @@ void hw_fence_cleanup_client(struct hw_fence_driver_data *drv_data,
void hw_fence_utils_reset_queues(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client);
int hw_fence_create(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, u64 hlos_key,
struct msm_hw_fence_client *hw_fence_client,
u64 context, u64 seqno, u64 *hash);
int hw_fence_add_callback(struct hw_fence_driver_data *drv_data, struct dma_fence *fence, u64 hash);
int hw_fence_destroy(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, u64 hlos_key,
struct msm_hw_fence_client *hw_fence_client,
u64 context, u64 seqno);
int hw_fence_destroy_with_hash(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, u64 hash);
@@ -658,7 +661,6 @@ int hw_fence_update_queue_helper(struct hw_fence_driver_data *drv_data, u32 clie
int hw_fence_update_existing_txq_payload(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, u64 hash, u32 error);
inline u64 hw_fence_get_qtime(struct hw_fence_driver_data *drv_data);
char *_get_queue_type(int queue_type);
int hw_fence_read_queue(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, struct msm_hw_fence_queue_payload *payload,
int queue_type);
@@ -670,7 +672,7 @@ int hw_fence_register_wait_client(struct hw_fence_driver_data *drv_data,
struct dma_fence *fence, struct msm_hw_fence_client *hw_fence_client, u64 context,
u64 seqno, u64 *hash, u64 client_data);
struct msm_hw_fence *msm_hw_fence_find(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, u64 hlos_key,
struct msm_hw_fence_client *hw_fence_client,
u64 context, u64 seqno, u64 *hash);
struct msm_hw_fence *hw_fence_find_with_dma_fence(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, struct dma_fence *fence, u64 *hash,

View File

@@ -31,11 +31,6 @@
#define ktime_compare_safe(A, B) ktime_compare(ktime_sub((A), (B)), ktime_set(0, 0))
#define HFENCE_QHDR_MSG \
"Client:%d %s q_sz_bytes:%u rd_idx:%u wr_idx:%u tx_wm:%u skips:%s start:%u factor:%u\n"
#define HFENCE_QPAYLOAD_MSG \
"%s[%d]: hash:%llu ctx:%llu seqno:%llu f:%llu d:%llu err:%u time:%llu type:%u\n"
u32 msm_hw_fence_debug_level = HW_FENCE_PRINTK;
/**
@@ -106,9 +101,9 @@ void hw_fence_debug_dump_fence(enum hw_fence_drv_prio prio, struct msm_hw_fence
}
#if IS_ENABLED(CONFIG_DEBUG_FS)
static int _get_debugfs_input_client_with_min(struct file *file,
static int _get_debugfs_input_client(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos,
struct hw_fence_driver_data **drv_data, int client_id_min)
struct hw_fence_driver_data **drv_data)
{
char buf[10];
int client_id;
@@ -131,23 +126,15 @@ static int _get_debugfs_input_client_with_min(struct file *file,
if (kstrtouint(buf, 0, &client_id))
return -EFAULT;
if (client_id < client_id_min || client_id >= (*drv_data)->clients_num) {
if (client_id < HW_FENCE_CLIENT_ID_CTX0 || client_id >= HW_FENCE_CLIENT_MAX) {
HWFNC_ERR("invalid client_id:%d min:%d max:%d\n", client_id,
client_id_min, (*drv_data)->clients_num);
HW_FENCE_CLIENT_ID_CTX0, HW_FENCE_CLIENT_MAX);
return -EINVAL;
}
return client_id;
}
static int _get_debugfs_input_client(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos,
struct hw_fence_driver_data **drv_data)
{
return _get_debugfs_input_client_with_min(file, user_buf, count, ppos, drv_data,
HW_FENCE_CLIENT_ID_CTX0);
}
static int _debugfs_ipcc_trigger(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos, u32 tx_client, u32 rx_client)
{
@@ -406,7 +393,7 @@ static ssize_t hw_fence_dbg_tx_and_signal_clients_wr(struct file *file,
client_info_src->seqno_cnt++;
/* Create hw fence for src client */
ret = hw_fence_create(drv_data, hw_fence_client, context, context, seqno, &hash);
ret = hw_fence_create(drv_data, hw_fence_client, context, seqno, &hash);
if (ret) {
HWFNC_ERR("Error creating HW fence\n");
goto exit;
@@ -574,7 +561,7 @@ static int dump_single_entry(struct hw_fence_driver_data *drv_data, char *buf, u
context = drv_data->debugfs_data.context_rd;
seqno = drv_data->debugfs_data.seqno_rd;
hw_fence = msm_hw_fence_find(drv_data, NULL, context, context, seqno, &hash);
hw_fence = msm_hw_fence_find(drv_data, NULL, context, seqno, &hash);
if (!hw_fence) {
HWFNC_ERR("no valid hfence found for context:%llu seqno:%llu hash:%llu",
context, seqno, hash);
@@ -693,7 +680,7 @@ static ssize_t hw_fence_dbg_dump_events_rd(struct file *file, char __user *user_
size_t user_buf_size, loff_t *ppos)
{
struct hw_fence_driver_data *drv_data;
u32 entry_size = sizeof(HFENCE_EVT_MSG), max_size = SZ_4K;
u32 entry_size = sizeof(struct msm_hw_fence_event), max_size = SZ_4K;
char *buf = NULL;
int len = 0;
static u64 start_time;
@@ -780,69 +767,45 @@ exit:
return len;
}
static int _dump_queue_header(struct hw_fence_driver_data *drv_data, enum hw_fence_drv_prio prio,
struct msm_hw_fence_queue *queue, int client_id, int queue_type, u32 **rd_idx_ptr,
u32 **wr_idx_ptr, u32 **tx_wm_ptr)
{
if (!drv_data || !queue || !rd_idx_ptr || !wr_idx_ptr || !tx_wm_ptr) {
HWFNC_ERR("invalid drv_data:0x%pK q:0x%pK rd_idx:0x%pK wr_idx:0x%pK tx_wm:0x%pK\n",
drv_data, queue, rd_idx_ptr, wr_idx_ptr, tx_wm_ptr);
return -EINVAL;
}
hw_fence_get_queue_idx_ptrs(drv_data, queue->va_header, rd_idx_ptr, wr_idx_ptr,
tx_wm_ptr);
HWFNC_DBG_DUMP(prio, HFENCE_QHDR_MSG, client_id, _get_queue_type(queue_type),
queue->q_size_bytes, **rd_idx_ptr, **wr_idx_ptr, **tx_wm_ptr,
queue->skip_wr_idx ? "true" : "false", queue->rd_wr_idx_start,
queue->rd_wr_idx_factor);
return 0;
}
static struct msm_hw_fence_queue_payload *_dump_queue_payload(enum hw_fence_drv_prio prio,
struct msm_hw_fence_queue *queue, int index, int queue_type)
{
struct msm_hw_fence_queue_payload *payload;
u32 *read_ptr;
u64 timestamp;
read_ptr = ((u32 *)queue->va_queue +
(index * (sizeof(struct msm_hw_fence_queue_payload) / sizeof(u32))));
payload = (struct msm_hw_fence_queue_payload *)read_ptr;
timestamp = (u64)payload->timestamp_lo | ((u64)payload->timestamp_hi << 32);
HWFNC_DBG_DUMP(prio, HFENCE_QPAYLOAD_MSG, _get_queue_type(queue_type),
index, payload->hash, payload->ctxt_id, payload->seqno, payload->flags,
payload->client_data, payload->error, timestamp, payload->type);
return payload;
}
static void _dump_queue(struct hw_fence_driver_data *drv_data, enum hw_fence_drv_prio prio,
struct msm_hw_fence_client *hw_fence_client, int queue_type)
{
struct msm_hw_fence_queue *queue;
u32 queue_entries, *rd_idx_ptr, *wr_idx_ptr, *tx_wm_ptr;
struct msm_hw_fence_queue_payload *payload;
u64 timestamp;
u32 *read_ptr, *rd_idx_ptr, *wr_idx_ptr, *tx_wm_ptr, queue_entries;
int i;
queue = &hw_fence_client->queues[queue_type];
queue = &hw_fence_client->queues[queue_type - 1];
if ((queue_type > hw_fence_client->queues_num) || !queue || !queue->va_header
|| !queue->va_queue) {
HWFNC_ERR("Cannot dump client:%d q_type:%s q_ptr:0x%pK q_header:0x%pK q_va:0x%pK\n",
hw_fence_client->client_id, _get_queue_type(queue_type), queue,
queue ? queue->va_header : NULL, queue ? queue->va_queue : NULL);
hw_fence_client->client_id,
(queue_type == HW_FENCE_TX_QUEUE) ? "TX QUEUE" : "RX QUEUE",
queue, queue ? queue->va_header : NULL, queue ? queue->va_queue : NULL);
return;
}
hw_fence_get_queue_idx_ptrs(drv_data, queue->va_header, &rd_idx_ptr, &wr_idx_ptr,
&tx_wm_ptr);
mb(); /* make sure data is ready before read */
_dump_queue_header(drv_data, prio, queue, hw_fence_client->client_id, queue_type,
&rd_idx_ptr, &wr_idx_ptr, &tx_wm_ptr);
HWFNC_DBG_DUMP(prio, "%s va:0x%pK rd_idx:%u wr_idx:%u tx_wm:%u q_size_bytes:%u\n",
(queue_type == HW_FENCE_TX_QUEUE) ? "TX QUEUE" : "RX QUEUE", queue->va_queue,
*rd_idx_ptr, *wr_idx_ptr, *tx_wm_ptr, queue->q_size_bytes);
queue_entries = queue->q_size_bytes / HW_FENCE_CLIENT_QUEUE_PAYLOAD;
for (i = 0; i < queue_entries; i++) {
_dump_queue_payload(prio, queue, i, queue_type);
read_ptr = ((u32 *)queue->va_queue +
(i * (sizeof(struct msm_hw_fence_queue_payload) / sizeof(u32))));
payload = (struct msm_hw_fence_queue_payload *)read_ptr;
timestamp = (u64)payload->timestamp_lo | ((u64)payload->timestamp_hi << 32);
HWFNC_DBG_DUMP(prio,
"%s[%d]: hash:%llu ctx:%llu seqno:%llu f:%llu d:%llu err:%u time:%llu\n",
(queue_type == HW_FENCE_TX_QUEUE) ? "tx" : "rx", i, payload->hash,
payload->ctxt_id, payload->seqno, payload->flags, payload->client_data,
payload->error, timestamp);
}
}
@@ -854,61 +817,28 @@ void hw_fence_debug_dump_queues(struct hw_fence_driver_data *drv_data, enum hw_f
return;
}
HWFNC_DBG_DUMP(prio, "Queues for client %d\n", hw_fence_client->client_id);
if (hw_fence_client->queues_num == HW_FENCE_CLIENT_QUEUES)
_dump_queue(drv_data, prio, hw_fence_client, HW_FENCE_RX_QUEUE - 1);
_dump_queue(drv_data, prio, hw_fence_client, HW_FENCE_TX_QUEUE - 1);
_dump_queue(drv_data, prio, hw_fence_client, HW_FENCE_RX_QUEUE);
_dump_queue(drv_data, prio, hw_fence_client, HW_FENCE_TX_QUEUE);
}
/**
* hw_fence_dbg_dump_queues_wr() - debugfs wr to control the dump of hw-fences queues.
* hw_fence_dbg_dump_queues_wr() - debugfs wr to dump the hw-fences queues.
* @file: file handler.
* @user_buf: user buffer content for debugfs.
* @count: size of the user buffer.
* @ppos: position offset of the user buffer.
*
* This debugfs receives as parameter either zero to dump the ctrl queues or the client_id for
* which to dump client queues in the next read of the same debugfs node.
* This debugfs dumps the hw-fence queues. Takes as input the desired client to dump.
* Dumps to debug msgs the contents of the TX and RX queues for that client, if they exist.
*/
static ssize_t hw_fence_dbg_dump_queues_wr(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
static ssize_t hw_fence_dbg_dump_queues_wr(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hw_fence_driver_data *drv_data;
int client_id;
client_id = _get_debugfs_input_client_with_min(file, user_buf, count, ppos, &drv_data, 0);
if (client_id < 0)
return -EINVAL;
drv_data->debugfs_data.client_id_rd = client_id;
return count;
}
/**
* hw_fence_dbg_dump_queues_rd() - debugfs read to dump ctrl or client queues.
* @file: file handler.
* @user_buf: user buffer content for debugfs.
* @user_buf_size: size of the user buffer.
* @ppos: position offset of the user buffer.
*
* This debugfs dumps either hw-fence ctrl queues or the client queues of a given client. The user
* can provide zero (to print the ctrl queues) or the client_id of interest by writing to this
* debugfs node (see documentation for the write in 'hw_fence_dbg_dump_queues_wr'). By default,
* dumps the ctrl queues.
*/
static ssize_t hw_fence_dbg_dump_queues_rd(struct file *file, char __user *user_buf,
size_t user_buf_size, loff_t *ppos)
{
struct hw_fence_driver_data *drv_data;
struct msm_hw_fence_client *hw_fence_client;
struct msm_hw_fence_queue *queue;
u32 entry_size = sizeof(HFENCE_QPAYLOAD_MSG), max_size = SZ_4K;
u32 client_id, queue_entries, queues_num, *rd_idx_ptr, *wr_idx_ptr, *tx_wm_ptr;
char *buf = NULL;
int len = 0;
static u32 index, queue_type;
static bool qhdr_dumped;
if (!file || !file->private_data) {
HWFNC_ERR("unexpected data file:0x%pK private_data:0x%pK\n", file,
file ? file->private_data : NULL);
@@ -916,95 +846,17 @@ static ssize_t hw_fence_dbg_dump_queues_rd(struct file *file, char __user *user_
}
drv_data = file->private_data;
client_id = drv_data->debugfs_data.client_id_rd;
if (client_id == 0) {
queue = &drv_data->ctrl_queues[queue_type];
queues_num = HW_FENCE_CTRL_QUEUES;
} else {
if (!drv_data->clients[client_id]) {
HWFNC_ERR("client %d not initialized\n", client_id);
return -EINVAL;
}
hw_fence_client = drv_data->clients[client_id];
queue = &hw_fence_client->queues[queue_type];
queues_num = hw_fence_client->queues_num;
}
queue_entries = queue->q_size_bytes / HW_FENCE_CLIENT_QUEUE_PAYLOAD;
client_id = _get_debugfs_input_client(file, user_buf, count, ppos, &drv_data);
if (client_id < 0)
return -EINVAL;
if (queue_type >= queues_num) {
HWFNC_DBG_H("no more data client_id:%d q_num:%u q_entries:%u\n", client_id,
queues_num, queue_entries);
queue_type = 0;
index = 0;
return 0;
}
if (!queue || !queue->va_header || !queue->va_queue) {
HWFNC_ERR("client:%d %s q_ptr:0x%pK qhdr_va:0x%pK q_va:0x%pK uninitialized\n",
client_id, _get_queue_type(queue_type), queue,
queue ? queue->va_header : NULL, queue ? queue->va_queue : NULL);
if (!drv_data->clients[client_id]) {
HWFNC_ERR("client %d not initialized\n", client_id);
return -EINVAL;
}
hw_fence_debug_dump_queues(drv_data, HW_FENCE_PRINTK, drv_data->clients[client_id]);
if (user_buf_size < entry_size) {
HWFNC_ERR("Not enough buff size:%zu to dump entries:%d\n", user_buf_size,
entry_size);
return -EINVAL;
}
buf = kvzalloc(max_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (!qhdr_dumped) {
mb(); /* make sure data is ready before read */
_dump_queue_header(drv_data, HW_FENCE_INFO, queue, client_id, queue_type,
&rd_idx_ptr, &wr_idx_ptr, &tx_wm_ptr);
len += scnprintf(buf + len, max_size - len, HFENCE_QHDR_MSG, client_id,
_get_queue_type(queue_type), queue->q_size_bytes, *rd_idx_ptr, *wr_idx_ptr,
*tx_wm_ptr, queue->skip_wr_idx ? "true" : "false", queue->rd_wr_idx_start,
queue->rd_wr_idx_factor);
qhdr_dumped = true;
}
for (; index < queue_entries && len < (max_size - entry_size); index++) {
struct msm_hw_fence_queue_payload *payload;
u64 timestamp;
payload = _dump_queue_payload(HW_FENCE_INFO, queue, index, queue_type);
if (!(payload->hash || payload->ctxt_id || payload->seqno || payload->flags ||
payload->client_data || payload->error || payload->timestamp_lo ||
payload->timestamp_hi || payload->type))
continue;
timestamp = (u64)payload->timestamp_lo | ((u64)payload->timestamp_hi << 32);
len += scnprintf(buf + len, max_size - len, HFENCE_QPAYLOAD_MSG,
_get_queue_type(queue_type), index, payload->hash, payload->ctxt_id,
payload->seqno, payload->flags, payload->client_data, payload->error,
timestamp, payload->type);
}
if (index >= queue_entries) {
index = 0;
queue_type++;
qhdr_dumped = false;
}
if (len <= 0 || len > user_buf_size) {
HWFNC_ERR("len:%d invalid buff size:%zu\n", len, user_buf_size);
len = 0;
goto exit;
}
if (copy_to_user(user_buf, buf, len)) {
HWFNC_ERR("failed to copy to user!\n");
len = -EFAULT;
goto exit;
}
*ppos += len;
exit:
kvfree(buf);
return len;
return count;
}
/**
@@ -1023,7 +875,7 @@ static ssize_t hw_fence_dbg_dump_table_rd(struct file *file, char __user *user_b
size_t user_buf_size, loff_t *ppos)
{
struct hw_fence_driver_data *drv_data;
int entry_size = sizeof(HFENCE_TBL_MSG);
int entry_size = sizeof(struct msm_hw_fence);
char *buf = NULL;
int len = 0, max_size = SZ_4K;
static u32 index, cnt;
@@ -1345,8 +1197,7 @@ static long _process_val_signal(struct hw_fence_driver_data *drv_data,
context = fence ? fence->context : 0;
seqno = fence ? fence->seqno : 0;
HWFNC_DBG_L("Client_id:%u attempting to process signalled fence:%llu\n",
hw_fence_client->client_id, hash);
while (read) {
read = hw_fence_read_queue(drv_data, hw_fence_client, &payload, queue_type);
if (read < 0) {
@@ -1354,8 +1205,8 @@ static long _process_val_signal(struct hw_fence_driver_data *drv_data,
hw_fence_client->client_id);
break;
}
HWFNC_DBG_L("Client_id: %u rxq read: hash:%llu, flags:%llu, error:%u\n",
hw_fence_client->client_id, payload.hash, payload.flags, payload.error);
HWFNC_DBG_L("rxq read: hash:%llu, flags:%llu, error:%u\n",
payload.hash, payload.flags, payload.error);
if ((fence && payload.ctxt_id == context && payload.seqno == seqno) ||
(mask && ((mask & hash) == (mask & payload.hash)))) {
*error = payload.error;
@@ -1370,10 +1221,9 @@ static long _process_val_signal(struct hw_fence_driver_data *drv_data,
}
}
HWFNC_ERR("fence received: hash:%llu ctx:%llu seq:%llu did not match expected fence\n",
payload.hash, payload.ctxt_id, payload.seqno);
HWFNC_ERR("Client_id:%u fence expected: hash:%llu ctx:%llu seq:%llu\n",
hw_fence_client->client_id, hash, context, seqno);
HWFNC_ERR("fence received did not match the fence expected\n");
HWFNC_ERR("received: hash:%llu ctx:%llu seq:%llu expected: hash:%llu ctx:%llu seq:%llu\n",
payload.hash, payload.ctxt_id, payload.seqno, hash, context, seqno);
return -EINVAL;
}
@@ -1391,8 +1241,6 @@ int hw_fence_debug_wait_val(struct hw_fence_driver_data *drv_data,
}
exp_ktime = ktime_add_ms(ktime_get(), timeout_ms);
HWFNC_DBG_L("Client_id:%u attempting to wait on fence:%llu\n",
hw_fence_client->client_id, hash);
while (ret) {
do {
ret = wait_event_timeout(hw_fence_client->wait_queue,
@@ -1403,8 +1251,7 @@ int hw_fence_debug_wait_val(struct hw_fence_driver_data *drv_data,
ktime_compare_safe(exp_ktime, cur_ktime) > 0);
if (!ret) {
HWFNC_ERR("Client_id: %u timed out waiting for the client signal %llu\n",
hw_fence_client->client_id, timeout_ms);
HWFNC_ERR("timed out waiting for the client signal %llu\n", timeout_ms);
/* Decrement the refcount that hw_sync_get_fence increments */
dma_fence_put(fence);
return -ETIMEDOUT;
@@ -1445,7 +1292,6 @@ static const struct file_operations hw_fence_dump_table_fops = {
static const struct file_operations hw_fence_dump_queues_fops = {
.open = simple_open,
.write = hw_fence_dbg_dump_queues_wr,
.read = hw_fence_dbg_dump_queues_rd,
};
static const struct file_operations hw_fence_dump_events_fops = {

View File

@@ -190,7 +190,7 @@ int hw_fence_interop_create_fence_from_import(struct synx_import_indv_params *pa
/* only synx clients can signal synx fences; no one can signal sw dma-fence from fw */
dummy_client.client_id = is_synx ? HW_FENCE_SYNX_FENCE_CLIENT_ID :
HW_FENCE_NATIVE_FENCE_CLIENT_ID;
ret = hw_fence_create(hw_fence_drv_data, &dummy_client, (u64)fence, fence->context,
ret = hw_fence_create(hw_fence_drv_data, &dummy_client, fence->context,
fence->seqno, &handle);
if (ret) {
HWFNC_ERR("failed create fence client:%d ctx:%llu seq:%llu is_synx:%s ret:%d\n",

View File

@@ -36,17 +36,6 @@
/* number of fences searched for HW Fence import */
#define HW_FENCE_FIND_THRESHOLD 10
/*
* Iterates through the hw-fence table populating hash and hw_fence pointers accordingly.
* Note: This internally takes the hw-fence lock during iteration so this loop must be
* exited by setting found = true.
*/
#define for_each_hw_fence(drv_data, hfence, hash, ctx, seqno, start, end, i, found) \
for ((i) = _hw_fence_iterator_init((drv_data), (hfence), (hash), (ctx), (seqno), \
(start), (end)); \
((i) < (end)) && !(found); \
(i) = _hw_fence_iterator_next((drv_data), (hfence), (hash), (i), (end), (found)))
inline u64 hw_fence_get_qtime(struct hw_fence_driver_data *drv_data)
{
#ifdef HWFENCE_USE_SLEEP_TIMER
@@ -661,10 +650,6 @@ static int init_hw_fences_table(struct hw_fence_driver_data *drv_data)
drv_data->hw_fences_tbl_cnt = drv_data->hw_fences_mem_desc.size /
sizeof(struct msm_hw_fence);
drv_data->hlos_key_tbl = kcalloc(drv_data->hw_fences_tbl_cnt, sizeof(u64), GFP_KERNEL);
if (!drv_data->hlos_key_tbl)
return -ENOMEM;
HWFNC_DBG_INIT("hw_fences_table:0x%pK cnt:%u\n", drv_data->hw_fences_tbl,
drv_data->hw_fences_tbl_cnt);
@@ -968,17 +953,45 @@ void hw_fence_cleanup_client(struct hw_fence_driver_data *drv_data,
kfree(hw_fence_client);
}
static inline int _calculate_hash(u64 context, u64 seqno, u64 m_size)
static inline int _calculate_hash(u32 table_total_entries, u64 context, u64 seqno,
u64 step, u64 *hash)
{
u64 a_multiplier = HW_FENCE_HASH_A_MULT;
u64 c_multiplier = HW_FENCE_HASH_C_MULT;
u64 b_multiplier = context + (context - 1); /* odd multiplier */
u64 m_size = table_total_entries;
int val = 0;
/*
* if m, is power of 2, we can optimize with right shift,
* for now we don't do it, to avoid assuming a power of two
*/
return (a_multiplier * seqno * b_multiplier + (c_multiplier * context)) % m_size;
if (step == 0) {
u64 a_multiplier = HW_FENCE_HASH_A_MULT;
u64 c_multiplier = HW_FENCE_HASH_C_MULT;
u64 b_multiplier = context + (context - 1); /* odd multiplier */
/*
* if m, is power of 2, we can optimize with right shift,
* for now we don't do it, to avoid assuming a power of two
*/
*hash = (a_multiplier * seqno * b_multiplier + (c_multiplier * context)) % m_size;
} else {
if (step >= m_size) {
/*
* If we already traversed the whole table, return failure since this means
* there are not available spots, table is either full or full-enough
* that we couldn't find an available spot after traverse the whole table.
* Ideally table shouldn't be so full that we cannot find a value after some
* iterations, so this maximum step size could be optimized to fail earlier.
*/
HWFNC_ERR("Fence Table tranversed and no available space!\n");
val = -EINVAL;
} else {
/*
* Linearly increment the hash value to find next element in the table
* note that this relies in the 'scrambled' data from the original hash
* Also, add a mod division to wrap-around in case that we reached the
* end of the table
*/
*hash = (*hash + 1) % m_size;
}
}
return val;
}
static inline struct msm_hw_fence *_get_hw_fence(u32 table_total_entries,
@@ -994,69 +1007,15 @@ static inline struct msm_hw_fence *_get_hw_fence(u32 table_total_entries,
return &hw_fences_tbl[hash];
}
static int _hw_fence_lookup_next(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence **hw_fence, u64 *hash, u32 init_step, u32 incr, u32 m_size)
static bool _is_hw_fence_free(struct msm_hw_fence *hw_fence, u64 context, u64 seqno)
{
*hash = (*hash + incr) % m_size;
*hw_fence = _get_hw_fence(m_size, drv_data->hw_fences_tbl, *hash);
if (!*hw_fence) {
HWFNC_ERR("failed to get hw-fence hash:%llu\n", *hash);
return m_size;
}
GLOBAL_ATOMIC_STORE(drv_data, &(*hw_fence)->lock, 1);
return init_step + incr;
/* If valid is set, the hw fence is not free */
return hw_fence->valid ? false : true;
}
/* returns initial step value and initializes hash and hw_fence */
static int _hw_fence_iterator_init(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence **hw_fence, u64 *hash, u64 context, u64 seqno, u32 start_step,
u32 end_step)
static bool _hw_fence_match(struct msm_hw_fence *hw_fence, u64 context, u64 seqno)
{
u32 m_size;
if (!drv_data || !hw_fence || !hash || start_step >= end_step ||
end_step > drv_data->hw_fences_tbl_cnt) {
HWFNC_ERR("invalid drv_data:0x%pK hwf:0x%pK h:0x%pK start:%u end:%u tbl_size:%u\n",
drv_data, hw_fence, hash, start_step, end_step,
drv_data ? drv_data->hw_fences_tbl_cnt : -1);
return end_step;
}
m_size = drv_data->hw_fences_tbl_cnt;
*hash = _calculate_hash(context, seqno, m_size);
HWFNC_DBG_LUT("ctx:%llu seq:%llu tbl_size:%u start_step:%u initial_hash:%llu\n", context,
seqno, m_size, start_step, *hash);
return _hw_fence_lookup_next(drv_data, hw_fence, hash, 0, start_step, m_size);
}
/* returns new step value and populates hash and hw_fence */
static int _hw_fence_iterator_next(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence **hw_fence, u64 *hash, u32 curr_step, u32 end_step, bool found)
{
u32 m_size = drv_data->hw_fences_tbl_cnt;
/* unlock previous entry */
GLOBAL_ATOMIC_STORE(drv_data, &(*hw_fence)->lock, 0);
if ((curr_step + 1) >= end_step || found) {
HWFNC_DBG_LUT("found:%s step:%d max:%d h:%llu v:%u ctx:%llu seq:%llu flg:0x%llx\n",
found ? "true" : "false", curr_step, end_step, *hash, (*hw_fence)->valid,
(*hw_fence)->ctx_id, (*hw_fence)->seq_id, (*hw_fence)->flags);
return found ? curr_step : curr_step + 1;
}
HWFNC_DBG_LUT("cmp failed resolving collision step:%u max:%u hash:%llu\n", curr_step + 1,
end_step, *hash);
return _hw_fence_lookup_next(drv_data, hw_fence, hash, curr_step, 1, m_size);
}
static bool _hw_fence_match(struct hw_fence_driver_data *drv_data, struct msm_hw_fence *hw_fence,
u64 hash, u64 context, u64 seqno, u64 hlos_key)
{
return (hw_fence->ctx_id == context) && (hw_fence->seq_id == seqno)
&& (drv_data->hlos_key_tbl[hash] == hlos_key);
return ((hw_fence->ctx_id == context && hw_fence->seq_id == seqno) ? true : false);
}
/* clears everything but the 'valid' field */
@@ -1088,9 +1047,34 @@ static void _cleanup_hw_fence(struct msm_hw_fence *hw_fence)
memset(hw_fence->client_data, 0, sizeof(hw_fence->client_data));
}
/* This function must be called with the hw fence lock */
static int _reserve_hw_fence(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence *hw_fence, u32 client_id,
u64 context, u64 seqno, u32 hash, u32 pending_child_cnt)
{
_cleanup_hw_fence(hw_fence);
/* reserve this HW fence */
hw_fence->valid = 1;
hw_fence->ctx_id = context;
hw_fence->seq_id = seqno;
hw_fence->flags = 0; /* fence just reserved, there shouldn't be any flags set */
hw_fence->fence_allocator = client_id;
hw_fence->fence_create_time = hw_fence_get_qtime(drv_data);
/* one released by creating client; one released by FCTL */
hw_fence->refcount = HW_FENCE_FCTL_REFCOUNT + 1;
HWFNC_DBG_LUT("Reserved fence client:%d ctx:%llu seq:%llu hash:%u\n",
client_id, context, seqno, hash);
return 0;
}
/* This function must be called with the hw fence lock */
static int _unreserve_hw_fence(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence *hw_fence, u32 hash)
struct msm_hw_fence *hw_fence, u32 client_id,
u64 context, u64 seqno, u32 hash, u32 pending_child_cnt)
{
if (hw_fence->refcount & HW_FENCE_HLOS_REFCOUNT_MASK)
hw_fence->refcount--;
@@ -1103,18 +1087,10 @@ static int _unreserve_hw_fence(struct hw_fence_driver_data *drv_data,
/* unreserve this HW fence */
hw_fence->valid = 0;
/**
* Note: If last hwfence refcount is removed from fctl then this entry will not be
* cleared. This is okay because the entry will be set to a new value at the time
* of next fence creation.
*/
drv_data->hlos_key_tbl[hash] = 0;
}
HWFNC_DBG_LUT("Removed ref on fence alloc:%d ctx:%llu seq:%llu refcount:0x%x hash:%u\n",
hw_fence->fence_allocator, hw_fence->ctx_id, hw_fence->seq_id, hw_fence->refcount,
hash);
HWFNC_DBG_LUT("Unreserved fence client:%d ctx:%llu seq:%llu hash:%u refcount:%x\n",
client_id, context, seqno, hash, hw_fence->refcount);
return 0;
}
@@ -1156,14 +1132,14 @@ int hw_fence_destroy_refcount(struct hw_fence_driver_data *drv_data, u64 hash, u
}
/* This function must be called with the hw fence lock */
static int _reserve_hw_fence(struct hw_fence_driver_data *drv_data,
static int _reserve_join_fence(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence *hw_fence, u32 client_id, u64 context,
u64 seqno, u32 hash, u32 pending_child_cnt, u64 hlos_key)
u64 seqno, u32 hash, u32 pending_child_cnt)
{
_cleanup_hw_fence(hw_fence);
/* reserve this HW fence */
hw_fence->valid = 1;
hw_fence->valid = true;
hw_fence->ctx_id = context;
hw_fence->seq_id = seqno;
@@ -1174,17 +1150,16 @@ static int _reserve_hw_fence(struct hw_fence_driver_data *drv_data,
hw_fence->pending_child_cnt = pending_child_cnt;
drv_data->hlos_key_tbl[hash] = hlos_key;
HWFNC_DBG_LUT("Reserved fence client:%d ctx:%llu seq:%llu pending_child:%u hash:%u\n",
client_id, context, seqno, pending_child_cnt, hash);
HWFNC_DBG_LUT("Reserved join fence client:%d ctx:%llu seq:%llu hash:%u\n",
client_id, context, seqno, hash);
return 0;
}
/* This function must be called with the hw fence lock */
static int _fence_found(struct hw_fence_driver_data *drv_data, struct msm_hw_fence *hw_fence,
u32 hash)
static int _fence_found(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence *hw_fence, u32 client_id,
u64 context, u64 seqno, u32 hash, u32 pending_child_cnt)
{
if ((hw_fence->refcount & HW_FENCE_HLOS_REFCOUNT_MASK) == HW_FENCE_HLOS_REFCOUNT_MASK)
return -EINVAL;
@@ -1194,125 +1169,176 @@ static int _fence_found(struct hw_fence_driver_data *drv_data, struct msm_hw_fen
* is done, the refcount needs to be decremented either explicitly by the client or as part
* of processing in HW Fence Driver.
*/
hw_fence->refcount++;
HWFNC_DBG_LUT("Found fence alloc:%d ctx:%llu seq:%llu refcount:0x%x hash:%u\n",
hw_fence->fence_allocator, hw_fence->ctx_id, hw_fence->seq_id, hw_fence->refcount,
hash);
HWFNC_DBG_LUT("Found fence client:%d ctx:%llu seq:%llu hash:%u ref:0x%x\n",
client_id, context, seqno, hash, hw_fence->refcount);
return 0;
}
struct msm_hw_fence *_hw_fence_lookup_and_create_range(struct hw_fence_driver_data *drv_data,
u32 client_id, u64 hlos_key, u64 context, u64 seqno, u32 pending_child_cnt, u64 *hash,
u32 start_step, u32 end_step, u64 flags)
char *_get_op_mode(enum hw_fence_lookup_ops op_code)
{
struct msm_hw_fence *hw_fence;
bool hw_fence_found;
int ret = 0;
u32 step;
if (!drv_data || !hash) {
HWFNC_ERR("Invalid input for hw_fence_lookup drv_data:0x%pK hash:0x%pK\n",
drv_data, hash);
return NULL;
switch (op_code) {
case HW_FENCE_LOOKUP_OP_CREATE:
return "CREATE";
case HW_FENCE_LOOKUP_OP_DESTROY:
return "DESTROY";
case HW_FENCE_LOOKUP_OP_CREATE_JOIN:
return "CREATE_JOIN";
case HW_FENCE_LOOKUP_OP_FIND_FENCE:
return "FIND_FENCE";
default:
return "UNKNOWN";
}
for_each_hw_fence(drv_data, &hw_fence, hash, context, seqno, start_step, end_step,
step, hw_fence_found) {
if (!hw_fence->valid) {
/* Process the hw fence found by the algorithm */
ret = _reserve_hw_fence(drv_data, hw_fence, client_id, context, seqno,
*hash, pending_child_cnt, hlos_key);
/* update memory table with processing */
wmb();
HWFNC_DBG_L("client_id:%u ctx:%llu seqno:%llu hash:%llu step:%u\n",
client_id, context, seqno, *hash, step);
hw_fence_found = true;
} else if (_hw_fence_match(drv_data, hw_fence, *hash, context, seqno, hlos_key)) {
hw_fence_found = true;
if (flags & MSM_HW_FENCE_FLAG_CREATE_SIGNALED)
ret = _fence_found(drv_data, hw_fence, *hash);
else
ret = -EALREADY;
HWFNC_DBG_L("client_id:%u ctx:%llu seqno:%llu hash:%llu step:%u\n",
client_id, context, seqno, *hash, step);
}
}
if (ret == -EALREADY) {
HWFNC_ERR("can't create hfence w/ same ctx:%llu seq:%llu hlos_key:0x%pK\n",
context, seqno, (context == hlos_key) ? NULL : (void *)hlos_key);
return NULL;
}
/* If we iterated through the whole list and didn't find available fences, return null */
if (!hw_fence_found || ret) {
HWFNC_DBG_LUT("fail to process create hw_fence ctx:%llu seq:%llu start:%u end:%u\n",
context, seqno, start_step, end_step);
return NULL;
}
return hw_fence;
}
struct msm_hw_fence *_hw_fence_lookup_and_create(struct hw_fence_driver_data *drv_data,
u32 client_id, u64 hlos_key, u64 context, u64 seqno, u32 pending_child_cnt, u64 *hash)
{
return _hw_fence_lookup_and_create_range(drv_data, client_id, hlos_key, context, seqno,
pending_child_cnt, hash, 0, drv_data->hw_fences_tbl_cnt, 0);
return "UNKNOWN";
}
struct msm_hw_fence *_hw_fence_lookup_and_process_range(struct hw_fence_driver_data *drv_data,
u64 hlos_key, u64 context, u64 seqno, u64 *hash, u32 start_step, u32 end_step,
int (*process_fn)(struct hw_fence_driver_data *drv_data, struct msm_hw_fence *hfence,
u32 hash))
struct msm_hw_fence *hw_fences_tbl, u64 context, u64 seqno, u32 client_id,
u32 pending_child_cnt, enum hw_fence_lookup_ops op_code, u64 *hash, u64 flags,
u64 start_step, u64 end_step)
{
struct msm_hw_fence *hw_fence;
bool hw_fence_found;
bool (*compare_fnc)(struct msm_hw_fence *hfence, u64 context, u64 seqno);
int (*process_fnc)(struct hw_fence_driver_data *drv_data, struct msm_hw_fence *hfence,
u32 client_id, u64 context, u64 seqno, u32 hash, u32 pending);
struct msm_hw_fence *hw_fence = NULL;
u64 step = start_step;
int ret = 0;
u32 step;
bool hw_fence_found = false;
if (!drv_data || !hash || !process_fn) {
HWFNC_ERR("Invalid input drv_data:0x%pK hash:0x%pK process_fn:0x%pK\n",
drv_data, hash, process_fn);
if (!hash | !drv_data | !hw_fences_tbl) {
HWFNC_ERR("Invalid input for hw_fence_lookup\n");
return NULL;
}
for_each_hw_fence(drv_data, &hw_fence, hash, context, seqno, start_step, end_step, step,
hw_fence_found) {
if (_hw_fence_match(drv_data, hw_fence, *hash, context, seqno, hlos_key)) {
/* Process the hw fence found by the algorithm */
ret = process_fn(drv_data, hw_fence, *hash);
HWFNC_DBG_L("ctx:%llu seqno:%llu hash:%llu step:%u\n", context, seqno,
*hash, step);
hw_fence_found = true;
/*
* When start_step != 0, the hash is already initialized at the correct value and should
* not be reset.
*/
if (!step)
*hash = ~0;
HWFNC_DBG_LUT("hw_fence_lookup: %d\n", op_code);
switch (op_code) {
case HW_FENCE_LOOKUP_OP_CREATE:
compare_fnc = &_is_hw_fence_free;
process_fnc = &_reserve_hw_fence;
break;
case HW_FENCE_LOOKUP_OP_DESTROY:
compare_fnc = &_hw_fence_match;
process_fnc = &_unreserve_hw_fence;
break;
case HW_FENCE_LOOKUP_OP_CREATE_JOIN:
compare_fnc = &_is_hw_fence_free;
process_fnc = &_reserve_join_fence;
break;
case HW_FENCE_LOOKUP_OP_FIND_FENCE:
compare_fnc = &_hw_fence_match;
process_fnc = &_fence_found;
break;
default:
HWFNC_ERR("Unknown op code:%d\n", op_code);
return NULL;
}
while (!hw_fence_found && (step < end_step)) {
/* Calculate the Hash for the Fence */
ret = _calculate_hash(drv_data->hw_fence_table_entries, context, seqno, step, hash);
if (ret) {
HWFNC_ERR("error calculating hash ctx:%llu seqno:%llu hash:%llu\n",
context, seqno, *hash);
break;
}
HWFNC_DBG_LUT("calculated hash:%llu [ctx:%llu seqno:%llu]\n", *hash, context,
seqno);
/* Get element from the table using the hash */
hw_fence = _get_hw_fence(drv_data->hw_fence_table_entries, hw_fences_tbl, *hash);
HWFNC_DBG_LUT("hw_fence_tbl:0x%pK hw_fence:0x%pK, hash:%llu valid:0x%x\n",
hw_fences_tbl, hw_fence, *hash, hw_fence ? hw_fence->valid : 0xbad);
if (!hw_fence) {
HWFNC_ERR("bad hw fence ctx:%llu seqno:%llu hash:%llu\n",
context, seqno, *hash);
break;
}
GLOBAL_ATOMIC_STORE(drv_data, &hw_fence->lock, 1);
/* compare to either find a free fence or find an allocated fence */
if (compare_fnc(hw_fence, context, seqno)) {
/* Process the hw fence found by the algorithm */
if (process_fnc) {
ret = process_fnc(drv_data, hw_fence, client_id, context, seqno,
*hash, pending_child_cnt);
/* update memory table with processing */
wmb();
}
HWFNC_DBG_L("client_id:%u op:%s ctx:%llu seqno:%llu hash:%llu step:%llu\n",
client_id, _get_op_mode(op_code), context, seqno, *hash, step);
hw_fence_found = true;
} else {
if ((op_code == HW_FENCE_LOOKUP_OP_CREATE ||
op_code == HW_FENCE_LOOKUP_OP_CREATE_JOIN) &&
seqno == hw_fence->seq_id && context == hw_fence->ctx_id) {
if (flags & MSM_HW_FENCE_FLAG_CREATE_SIGNALED) {
/* hw-fence created for importing client */
ret = _fence_found(drv_data, hw_fence, client_id, context,
seqno, *hash, pending_child_cnt);
hw_fence_found = true;
} else {
ret = -EALREADY;
}
GLOBAL_ATOMIC_STORE(drv_data, &hw_fence->lock, 0);
if (ret == -EALREADY)
HWFNC_ERR("can't create hfence w/ same ctx:%llu seq:%llu\n",
context, seqno);
break;
}
/* compare can fail if we have a collision, we will linearly resolve it */
HWFNC_DBG_H("compare failed for hash:%llu [ctx:%llu seqno:%llu]\n", *hash,
context, seqno);
}
GLOBAL_ATOMIC_STORE(drv_data, &hw_fence->lock, 0);
if (hw_fence_found && ret)
HWFNC_ERR("failed process_func client:%u op:%s ctx:%llu seq:%llu h:%llu\n",
client_id, _get_op_mode(op_code), context, seqno, *hash);
/* Increment step for the next loop */
step++;
}
/* If we iterated through the whole list and didn't find available fences, return null */
if (!hw_fence_found || ret) {
HWFNC_DBG_LUT("fail to process create hw_fence ctx:%llu seq:%llu\n",
context, seqno);
return NULL;
/* If we iterated through the whole list and didn't find the fence, return null */
if (!hw_fence_found) {
HWFNC_DBG_LUT("fail to process hw-fence op_code:%d step:%llu\n", op_code, step);
hw_fence = NULL;
}
HWFNC_DBG_LUT("lookup:%d hw_fence:%pK ctx:%llu seqno:%llu hash:%llu flags:0x%llx\n",
op_code, hw_fence, context, seqno, *hash, hw_fence ? hw_fence->flags : -1);
return hw_fence;
}
struct msm_hw_fence *_hw_fence_lookup_and_process(struct hw_fence_driver_data *drv_data,
u64 hlos_key, u64 context, u64 seqno, u64 *hash,
int (*process_fn)(struct hw_fence_driver_data *drv_data, struct msm_hw_fence *hfence,
u32 hash))
struct msm_hw_fence *hw_fences_tbl, u64 context, u64 seqno, u32 client_id,
u32 pending_child_cnt, enum hw_fence_lookup_ops op_code, u64 *hash, u64 flags)
{
return _hw_fence_lookup_and_process_range(drv_data, hlos_key, context, seqno, hash, 0,
drv_data->hw_fences_tbl_cnt, process_fn);
return _hw_fence_lookup_and_process_range(drv_data, hw_fences_tbl, context, seqno,
client_id, pending_child_cnt, op_code, hash, flags, 0,
drv_data->hw_fence_table_entries);
}
struct dma_fence *hw_dma_fence_init(struct msm_hw_fence_client *hw_fence_client, u64 context,
u64 seqno)
{
@@ -1414,7 +1440,7 @@ struct dma_fence *hw_fence_internal_dma_fence_create(struct hw_fence_driver_data
return ERR_PTR(-EINVAL);
}
ret = hw_fence_create(drv_data, hw_fence_client, (u64)fence, context, seqno, hash);
ret = hw_fence_create(drv_data, hw_fence_client, context, seqno, hash);
if (ret) {
HWFNC_ERR("failed to back internal dma-fence client:%d ctx:%llu seq:%llu\n",
hw_fence_client->client_id, context, seqno);
@@ -1539,14 +1565,16 @@ static int hw_fence_dma_fence_table_del(struct hw_fence_driver_data *drv_data, u
}
int hw_fence_create(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, u64 hlos_key, u64 context,
u64 seqno, u64 *hash)
struct msm_hw_fence_client *hw_fence_client,
u64 context, u64 seqno, u64 *hash)
{
u32 client_id = hw_fence_client->client_id;
struct msm_hw_fence *hw_fences_tbl = drv_data->hw_fences_tbl;
int ret = 0;
/* allocate hw fence in table */
if (!_hw_fence_lookup_and_create(drv_data, client_id, hlos_key, context, seqno, 0, hash)) {
if (!_hw_fence_lookup_and_process(drv_data, hw_fences_tbl,
context, seqno, client_id, 0, HW_FENCE_LOOKUP_OP_CREATE, hash, 0)) {
HWFNC_ERR("Fail to create fence client:%u ctx:%llu seqno:%llu\n",
client_id, context, seqno);
ret = -EINVAL;
@@ -1574,16 +1602,18 @@ int hw_fence_create(struct hw_fence_driver_data *drv_data,
}
int hw_fence_destroy(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, u64 hlos_key, u64 context, u64 seqno)
struct msm_hw_fence_client *hw_fence_client,
u64 context, u64 seqno)
{
u32 client_id = hw_fence_client->client_id;
struct msm_hw_fence *hw_fences_tbl = drv_data->hw_fences_tbl;
int ret = 0;
u64 hash;
/* decrement refcount on hw-fence */
if (!_hw_fence_lookup_and_process(drv_data, hlos_key, context, seqno, &hash,
&_unreserve_hw_fence)) {
HWFNC_ERR("Fail removing ref on fence client:%u ctx:%llu seqno:%llu\n",
if (!_hw_fence_lookup_and_process(drv_data, hw_fences_tbl,
context, seqno, client_id, 0, HW_FENCE_LOOKUP_OP_DESTROY, &hash, 0)) {
HWFNC_ERR("Fail destroying fence client:%u ctx:%llu seqno:%llu\n",
client_id, context, seqno);
ret = -EINVAL;
}
@@ -1689,8 +1719,9 @@ static struct msm_hw_fence *_hw_fence_process_join_fence(struct hw_fence_driver_
if (create) {
/* allocate the fence */
join_fence = _hw_fence_lookup_and_create(drv_data, client_id, (u64)array, context,
seqno, pending_child_cnt, hash);
join_fence = _hw_fence_lookup_and_process(drv_data, hw_fences_tbl, context,
seqno, client_id, pending_child_cnt, HW_FENCE_LOOKUP_OP_CREATE_JOIN, hash,
0);
if (!join_fence)
HWFNC_ERR("Fail to create join fence client:%u ctx:%llu seqno:%llu\n",
client_id, context, seqno);
@@ -1703,15 +1734,16 @@ static struct msm_hw_fence *_hw_fence_process_join_fence(struct hw_fence_driver_
}
struct msm_hw_fence *msm_hw_fence_find(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence_client *hw_fence_client, u64 hlos_key, u64 context,
u64 seqno, u64 *hash)
struct msm_hw_fence_client *hw_fence_client,
u64 context, u64 seqno, u64 *hash)
{
struct msm_hw_fence *hw_fences_tbl = drv_data->hw_fences_tbl;
struct msm_hw_fence *hw_fence;
u32 client_id = hw_fence_client ? hw_fence_client->client_id : ~0;
/* find the hw fence */
hw_fence = _hw_fence_lookup_and_process(drv_data, hlos_key, context, seqno, hash,
&_fence_found);
hw_fence = _hw_fence_lookup_and_process(drv_data, hw_fences_tbl, context,
seqno, client_id, 0, HW_FENCE_LOOKUP_OP_FIND_FENCE, hash, 0);
if (!hw_fence)
HWFNC_ERR("Fail to find hw fence client:%u ctx:%llu seqno:%llu\n",
client_id, context, seqno);
@@ -2040,8 +2072,7 @@ int hw_fence_register_wait_client(struct hw_fence_driver_data *drv_data,
hw_fence = hw_fence_find_with_dma_fence(drv_data, hw_fence_client, fence, hash,
&is_signaled, true);
else
hw_fence = msm_hw_fence_find(drv_data, hw_fence_client, context, context, seqno,
hash);
hw_fence = msm_hw_fence_find(drv_data, hw_fence_client, context, seqno, hash);
if (!hw_fence) {
HWFNC_ERR("Cannot find fence!\n");
return -EINVAL;
@@ -2214,11 +2245,12 @@ static void _signal_fence_if_unsignaled(struct hw_fence_driver_data *drv_data,
struct msm_hw_fence *_create_signaled_hw_fence(struct hw_fence_driver_data *drv_data,
u32 client_id, struct dma_fence *fence, u64 *hash)
{
struct msm_hw_fence *hw_fences_tbl = drv_data->hw_fences_tbl;
struct msm_hw_fence *hw_fence;
/* create new hw-fence for signaled dma-fence */
hw_fence = _hw_fence_lookup_and_create_range(drv_data, client_id, (u64)fence,
fence->context, fence->seqno, 0, hash, 0, drv_data->hw_fences_tbl_cnt,
hw_fence = _hw_fence_lookup_and_process(drv_data, hw_fences_tbl,
fence->context, fence->seqno, client_id, 0, HW_FENCE_LOOKUP_OP_CREATE, hash,
MSM_HW_FENCE_FLAG_CREATE_SIGNALED);
if (hw_fence) {
_signal_fence_if_unsignaled(drv_data, hw_fence, *hash, fence->error, true);
@@ -2238,6 +2270,7 @@ struct msm_hw_fence *hw_fence_find_with_dma_fence(struct hw_fence_driver_data *d
bool *is_signaled, bool create)
{
u32 step, end_step, client_id = hw_fence_client ? hw_fence_client->client_id : 0xff;
struct msm_hw_fence *hw_fences_tbl = drv_data->hw_fences_tbl;
struct msm_hw_fence *hw_fence = NULL;
if (!create && dma_fence_is_signaled(fence)) {
@@ -2246,11 +2279,12 @@ struct msm_hw_fence *hw_fence_find_with_dma_fence(struct hw_fence_driver_data *d
return NULL;
}
for (step = 0; step < drv_data->hw_fences_tbl_cnt; step += HW_FENCE_FIND_THRESHOLD) {
end_step = (step + HW_FENCE_FIND_THRESHOLD > drv_data->hw_fences_tbl_cnt) ?
drv_data->hw_fences_tbl_cnt : step + HW_FENCE_FIND_THRESHOLD;
hw_fence = _hw_fence_lookup_and_process_range(drv_data, (u64)fence, fence->context,
fence->seqno, hash, step, end_step, _fence_found);
for (step = 0; step < drv_data->hw_fence_table_entries; step += HW_FENCE_FIND_THRESHOLD) {
end_step = (step + HW_FENCE_FIND_THRESHOLD > drv_data->hw_fence_table_entries) ?
drv_data->hw_fence_table_entries : step + HW_FENCE_FIND_THRESHOLD;
hw_fence = _hw_fence_lookup_and_process_range(drv_data, hw_fences_tbl,
fence->context, fence->seqno, client_id, 0, HW_FENCE_LOOKUP_OP_FIND_FENCE,
hash, 0, step, end_step);
if (hw_fence) {
/* successfully found backing hw-fence*/
*is_signaled = false;

View File

@@ -411,7 +411,7 @@ static int _process_ctrl_rx_queue(struct hw_fence_driver_data *drv_data)
&drv_data->ctrl_queues[HW_FENCE_RX_QUEUE - 1], &payload);
if (read < 0) {
HWFNC_DBG_Q("unable to read ctrl rxq\n");
return 0;
return read;
}
switch (payload.type) {
case HW_FENCE_PAYLOAD_TYPE_2:

View File

@@ -291,7 +291,7 @@ int msm_hw_fence_create(void *client_handle,
}
/* Create the HW Fence, i.e. add entry in the Global Table for this Fence */
ret = hw_fence_create(hw_fence_drv_data, hw_fence_client, (u64)fence, fence->context,
ret = hw_fence_create(hw_fence_drv_data, hw_fence_client, fence->context,
fence->seqno, params->handle);
if (ret) {
HWFNC_ERR("Error creating HW fence\n");
@@ -358,7 +358,7 @@ int msm_hw_fence_destroy(void *client_handle,
}
/* Destroy the HW Fence, i.e. remove entry in the Global Table for the Fence */
ret = hw_fence_destroy(hw_fence_drv_data, hw_fence_client, (u64)fence,
ret = hw_fence_destroy(hw_fence_drv_data, hw_fence_client,
fence->context, fence->seqno);
if (ret) {
HWFNC_ERR("Error destroying the HW fence\n");
@@ -758,7 +758,7 @@ int msm_hw_fence_dump_fence(void *client_handle, struct dma_fence *fence)
}
hw_fence_client = (struct msm_hw_fence_client *)client_handle;
hw_fence = msm_hw_fence_find(hw_fence_drv_data, hw_fence_client, (u64)fence, fence->context,
hw_fence = msm_hw_fence_find(hw_fence_drv_data, hw_fence_client, fence->context,
fence->seqno, &hash);
if (!hw_fence) {
HWFNC_ERR("failed to find hw-fence client_id:%d fence:0x%pK ctx:%llu seqno:%llu\n",
@@ -908,7 +908,6 @@ static int msm_hw_fence_remove(struct platform_device *pdev)
/* free memory allocations as part of hw_fence_drv_data */
kfree(hw_fence_drv_data->ipc_clients_table);
kfree(hw_fence_drv_data->hw_fence_client_queue_size);
kfree(hw_fence_drv_data->hlos_key_tbl);
if (hw_fence_drv_data->cpu_addr_cookie)
dma_free_attrs(hw_fence_drv_data->dev, hw_fence_drv_data->size,
hw_fence_drv_data->cpu_addr_cookie, hw_fence_drv_data->res.start,

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
@@ -407,13 +407,6 @@ static int spec_sync_bind_array(struct fence_bind_data *sync_bind_info)
user_fds[i], sync_bind_info->out_bind_fd);
ret = -EINVAL;
goto bind_invalid;
} else if (user_fence->context == fence_array->base.context &&
user_fence->seqno == fence_array->base.seqno) {
pr_err("invalid spec fence, ufd:%d o_b_fd:%d ctx:%lld seqno:%lld\n",
user_fds[i], sync_bind_info->out_bind_fd,
user_fence->context, user_fence->seqno);
ret = -EINVAL;
goto bind_invalid;
}
fence_array->fences[i] = user_fence;
/*