|
@@ -17,6 +17,15 @@
|
|
|
|
|
|
#define IS_HW_FENCE_TX_QUEUE(queue_type) ((queue_type) == HW_FENCE_TX_QUEUE - 1)
|
|
#define IS_HW_FENCE_TX_QUEUE(queue_type) ((queue_type) == HW_FENCE_TX_QUEUE - 1)
|
|
|
|
|
|
|
|
+#define REQUIRES_IDX_TRANSLATION(queue) \
|
|
|
|
+ ((queue)->rd_wr_idx_factor && ((queue)->rd_wr_idx_start || (queue)->rd_wr_idx_factor > 1))
|
|
|
|
+
|
|
|
|
+#define IDX_TRANSLATE_CUSTOM_TO_DEFAULT(queue, idx) \
|
|
|
|
+ (((idx) - (queue)->rd_wr_idx_start) * (queue)->rd_wr_idx_factor)
|
|
|
|
+
|
|
|
|
+#define IDX_TRANSLATE_DEFAULT_TO_CUSTOM(queue, idx) \
|
|
|
|
+ (((idx) / (queue)->rd_wr_idx_factor) + (queue)->rd_wr_idx_start)
|
|
|
|
+
|
|
inline u64 hw_fence_get_qtime(struct hw_fence_driver_data *drv_data)
|
|
inline u64 hw_fence_get_qtime(struct hw_fence_driver_data *drv_data)
|
|
{
|
|
{
|
|
#ifdef HWFENCE_USE_SLEEP_TIMER
|
|
#ifdef HWFENCE_USE_SLEEP_TIMER
|
|
@@ -184,18 +193,21 @@ char *_get_queue_type(int queue_type)
|
|
return (queue_type == (HW_FENCE_RX_QUEUE - 1)) ? "RXQ" : "TXQ";
|
|
return (queue_type == (HW_FENCE_RX_QUEUE - 1)) ? "RXQ" : "TXQ";
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void _translate_queue_indexes_custom_to_default(struct msm_hw_fence_queue *queue,
|
|
|
|
+ u32 *read_idx, u32 *write_idx)
|
|
|
|
+{
|
|
|
|
+ if (REQUIRES_IDX_TRANSLATION(queue)) {
|
|
|
|
+ *read_idx = IDX_TRANSLATE_CUSTOM_TO_DEFAULT(queue, *read_idx);
|
|
|
|
+ *write_idx = IDX_TRANSLATE_CUSTOM_TO_DEFAULT(queue, *write_idx);
|
|
|
|
+ HWFNC_DBG_Q("rd_idx_u32:%lu wr_idx_u32:%lu rd_wr_idx start:%lu factor:%lu\n",
|
|
|
|
+ *read_idx, *write_idx, queue->rd_wr_idx_start, queue->rd_wr_idx_factor);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
int hw_fence_read_queue(struct msm_hw_fence_client *hw_fence_client,
|
|
int hw_fence_read_queue(struct msm_hw_fence_client *hw_fence_client,
|
|
struct msm_hw_fence_queue_payload *payload, int queue_type)
|
|
struct msm_hw_fence_queue_payload *payload, int queue_type)
|
|
{
|
|
{
|
|
- struct msm_hw_fence_hfi_queue_header *hfi_header;
|
|
|
|
struct msm_hw_fence_queue *queue;
|
|
struct msm_hw_fence_queue *queue;
|
|
- u32 read_idx;
|
|
|
|
- u32 write_idx;
|
|
|
|
- u32 to_read_idx;
|
|
|
|
- u32 *read_ptr;
|
|
|
|
- u32 payload_size_u32;
|
|
|
|
- u32 q_size_u32;
|
|
|
|
- struct msm_hw_fence_queue_payload *read_ptr_payload;
|
|
|
|
|
|
|
|
if (queue_type >= HW_FENCE_CLIENT_QUEUES || !hw_fence_client || !payload) {
|
|
if (queue_type >= HW_FENCE_CLIENT_QUEUES || !hw_fence_client || !payload) {
|
|
HWFNC_ERR("Invalid queue type:%s hw_fence_client:0x%pK payload:0x%pK\n", queue_type,
|
|
HWFNC_ERR("Invalid queue type:%s hw_fence_client:0x%pK payload:0x%pK\n", queue_type,
|
|
@@ -204,6 +216,20 @@ int hw_fence_read_queue(struct msm_hw_fence_client *hw_fence_client,
|
|
}
|
|
}
|
|
|
|
|
|
queue = &hw_fence_client->queues[queue_type];
|
|
queue = &hw_fence_client->queues[queue_type];
|
|
|
|
+ HWFNC_DBG_Q("read client:%lu queue:0x%pK\n", hw_fence_client->client_id, queue);
|
|
|
|
+
|
|
|
|
+ return hw_fence_read_queue_helper(queue, payload);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int hw_fence_read_queue_helper(struct msm_hw_fence_queue *queue,
|
|
|
|
+ struct msm_hw_fence_queue_payload *payload)
|
|
|
|
+{
|
|
|
|
+ struct msm_hw_fence_hfi_queue_header *hfi_header;
|
|
|
|
+ u32 read_idx, write_idx, to_read_idx;
|
|
|
|
+ u32 *read_ptr;
|
|
|
|
+ u32 payload_size_u32, q_size_u32;
|
|
|
|
+ struct msm_hw_fence_queue_payload *read_ptr_payload;
|
|
|
|
+
|
|
hfi_header = queue->va_header;
|
|
hfi_header = queue->va_header;
|
|
|
|
|
|
q_size_u32 = (queue->q_size_bytes / sizeof(u32));
|
|
q_size_u32 = (queue->q_size_bytes / sizeof(u32));
|
|
@@ -223,20 +249,14 @@ int hw_fence_read_queue(struct msm_hw_fence_client *hw_fence_client,
|
|
write_idx = readl_relaxed(&hfi_header->write_index);
|
|
write_idx = readl_relaxed(&hfi_header->write_index);
|
|
|
|
|
|
/* translate read and write indexes from custom indexing to dwords with no offset */
|
|
/* translate read and write indexes from custom indexing to dwords with no offset */
|
|
- if (queue->rd_wr_idx_start || queue->rd_wr_idx_factor != 1) {
|
|
|
|
- read_idx = (read_idx - queue->rd_wr_idx_start) * queue->rd_wr_idx_factor;
|
|
|
|
- write_idx = (write_idx - queue->rd_wr_idx_start) * queue->rd_wr_idx_factor;
|
|
|
|
- HWFNC_DBG_Q("rd_idx_u32:%lu wr_idx_u32:%lu rd_wr_idx start:%lu factor:%lu\n",
|
|
|
|
- read_idx, write_idx, queue->rd_wr_idx_start, queue->rd_wr_idx_factor);
|
|
|
|
- }
|
|
|
|
|
|
+ _translate_queue_indexes_custom_to_default(queue, &read_idx, &write_idx);
|
|
|
|
|
|
- HWFNC_DBG_Q("read client:%d rd_ptr:0x%pK wr_ptr:0x%pK rd_idx:%d wr_idx:%d queue:0x%pK\n",
|
|
|
|
- hw_fence_client->client_id, &hfi_header->read_index, &hfi_header->write_index,
|
|
|
|
- read_idx, write_idx, queue);
|
|
|
|
|
|
+ HWFNC_DBG_Q("read rd_ptr:0x%pK wr_ptr:0x%pK rd_idx:%d wr_idx:%d queue:0x%pK\n",
|
|
|
|
+ &hfi_header->read_index, &hfi_header->write_index, read_idx, write_idx, queue);
|
|
|
|
|
|
if (read_idx == write_idx) {
|
|
if (read_idx == write_idx) {
|
|
HWFNC_DBG_Q("Nothing to read!\n");
|
|
HWFNC_DBG_Q("Nothing to read!\n");
|
|
- return 0;
|
|
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
/* Move the pointer where we need to read and cast it */
|
|
/* Move the pointer where we need to read and cast it */
|
|
@@ -257,19 +277,14 @@ int hw_fence_read_queue(struct msm_hw_fence_client *hw_fence_client,
|
|
to_read_idx = 0;
|
|
to_read_idx = 0;
|
|
|
|
|
|
/* translate to_read_idx to custom indexing with offset */
|
|
/* translate to_read_idx to custom indexing with offset */
|
|
- if (queue->rd_wr_idx_start || queue->rd_wr_idx_factor != 1) {
|
|
|
|
- to_read_idx = (to_read_idx / queue->rd_wr_idx_factor) + queue->rd_wr_idx_start;
|
|
|
|
|
|
+ if (REQUIRES_IDX_TRANSLATION(queue)) {
|
|
|
|
+ to_read_idx = IDX_TRANSLATE_DEFAULT_TO_CUSTOM(queue, to_read_idx);
|
|
HWFNC_DBG_Q("translated to_read_idx:%lu rd_wr_idx start:%lu factor:%lu\n",
|
|
HWFNC_DBG_Q("translated to_read_idx:%lu rd_wr_idx start:%lu factor:%lu\n",
|
|
to_read_idx, queue->rd_wr_idx_start, queue->rd_wr_idx_factor);
|
|
to_read_idx, queue->rd_wr_idx_start, queue->rd_wr_idx_factor);
|
|
}
|
|
}
|
|
|
|
|
|
/* Read the Client Queue */
|
|
/* Read the Client Queue */
|
|
- payload->ctxt_id = readq_relaxed(&read_ptr_payload->ctxt_id);
|
|
|
|
- payload->seqno = readq_relaxed(&read_ptr_payload->seqno);
|
|
|
|
- payload->hash = readq_relaxed(&read_ptr_payload->hash);
|
|
|
|
- payload->flags = readq_relaxed(&read_ptr_payload->flags);
|
|
|
|
- payload->client_data = readq_relaxed(&read_ptr_payload->client_data);
|
|
|
|
- payload->error = readl_relaxed(&read_ptr_payload->error);
|
|
|
|
|
|
+ *payload = *read_ptr_payload;
|
|
|
|
|
|
/* update the read index */
|
|
/* update the read index */
|
|
writel_relaxed(to_read_idx, &hfi_header->read_index);
|
|
writel_relaxed(to_read_idx, &hfi_header->read_index);
|
|
@@ -281,6 +296,34 @@ int hw_fence_read_queue(struct msm_hw_fence_client *hw_fence_client,
|
|
return to_read_idx == write_idx ? 0 : 1;
|
|
return to_read_idx == write_idx ? 0 : 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int _get_update_queue_params(struct msm_hw_fence_queue *queue,
|
|
|
|
+ struct msm_hw_fence_hfi_queue_header **hfi_header, u32 *q_size_u32, u32 *payload_size,
|
|
|
|
+ u32 *payload_size_u32, u32 **wr_ptr)
|
|
|
|
+{
|
|
|
|
+ if (!queue) {
|
|
|
|
+ HWFNC_ERR("invalid queue\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *hfi_header = queue->va_header;
|
|
|
|
+ if (!*hfi_header) {
|
|
|
|
+ HWFNC_ERR("Invalid queue hfi_header\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *q_size_u32 = (queue->q_size_bytes / sizeof(u32));
|
|
|
|
+ *payload_size = sizeof(struct msm_hw_fence_queue_payload);
|
|
|
|
+ *payload_size_u32 = (*payload_size / sizeof(u32));
|
|
|
|
+
|
|
|
|
+ /* if skipping update wr_index, then use hfi_header->tx_wm instead */
|
|
|
|
+ if (queue->skip_wr_idx)
|
|
|
|
+ *wr_ptr = &((*hfi_header)->tx_wm);
|
|
|
|
+ else
|
|
|
|
+ *wr_ptr = &((*hfi_header)->write_index);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* This function writes to the queue of the client. The 'queue_type' determines
|
|
* This function writes to the queue of the client. The 'queue_type' determines
|
|
* if this function is writing to the rx or tx queue
|
|
* if this function is writing to the rx or tx queue
|
|
@@ -312,23 +355,13 @@ int hw_fence_update_queue(struct hw_fence_driver_data *drv_data,
|
|
}
|
|
}
|
|
|
|
|
|
queue = &hw_fence_client->queues[queue_type];
|
|
queue = &hw_fence_client->queues[queue_type];
|
|
- hfi_header = queue->va_header;
|
|
|
|
-
|
|
|
|
- q_size_u32 = (queue->q_size_bytes / sizeof(u32));
|
|
|
|
- payload_size = sizeof(struct msm_hw_fence_queue_payload);
|
|
|
|
- payload_size_u32 = (payload_size / sizeof(u32));
|
|
|
|
-
|
|
|
|
- if (!hfi_header) {
|
|
|
|
- HWFNC_ERR("Invalid queue\n");
|
|
|
|
|
|
+ if (_get_update_queue_params(queue, &hfi_header, &q_size_u32, &payload_size,
|
|
|
|
+ &payload_size_u32, &wr_ptr)) {
|
|
|
|
+ HWFNC_ERR("Invalid client:%d q_type:%d queue\n", hw_fence_client->client_id,
|
|
|
|
+ queue_type);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- /* if skipping update wr_index, then use hfi_header->tx_wm instead */
|
|
|
|
- if (queue->skip_wr_idx)
|
|
|
|
- wr_ptr = &hfi_header->tx_wm;
|
|
|
|
- else
|
|
|
|
- wr_ptr = &hfi_header->write_index;
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* We need to lock the client if there is an Rx Queue update, since that
|
|
* We need to lock the client if there is an Rx Queue update, since that
|
|
* is the only time when HW Fence driver can have a race condition updating
|
|
* is the only time when HW Fence driver can have a race condition updating
|
|
@@ -361,12 +394,7 @@ int hw_fence_update_queue(struct hw_fence_driver_data *drv_data,
|
|
read_idx, write_idx, queue, queue_type, queue->skip_wr_idx ? "true" : "false");
|
|
read_idx, write_idx, queue, queue_type, queue->skip_wr_idx ? "true" : "false");
|
|
|
|
|
|
/* translate read and write indexes from custom indexing to dwords with no offset */
|
|
/* translate read and write indexes from custom indexing to dwords with no offset */
|
|
- if (queue->rd_wr_idx_start || queue->rd_wr_idx_factor != 1) {
|
|
|
|
- read_idx = (read_idx - queue->rd_wr_idx_start) * queue->rd_wr_idx_factor;
|
|
|
|
- write_idx = (write_idx - queue->rd_wr_idx_start) * queue->rd_wr_idx_factor;
|
|
|
|
- HWFNC_DBG_Q("rd_idx_u32:%lu wr_idx_u32:%lu rd_wr_idx start:%lu factor:%lu\n",
|
|
|
|
- read_idx, write_idx, queue->rd_wr_idx_start, queue->rd_wr_idx_factor);
|
|
|
|
- }
|
|
|
|
|
|
+ _translate_queue_indexes_custom_to_default(queue, &read_idx, &write_idx);
|
|
|
|
|
|
/* Check queue to make sure message will fit */
|
|
/* Check queue to make sure message will fit */
|
|
q_free_u32 = read_idx <= write_idx ? (q_size_u32 - (write_idx - read_idx)) :
|
|
q_free_u32 = read_idx <= write_idx ? (q_size_u32 - (write_idx - read_idx)) :
|
|
@@ -402,8 +430,8 @@ int hw_fence_update_queue(struct hw_fence_driver_data *drv_data,
|
|
to_write_idx = 0;
|
|
to_write_idx = 0;
|
|
|
|
|
|
/* translate to_write_idx to custom indexing with offset */
|
|
/* translate to_write_idx to custom indexing with offset */
|
|
- if (queue->rd_wr_idx_start || queue->rd_wr_idx_factor != 1) {
|
|
|
|
- to_write_idx = (to_write_idx / queue->rd_wr_idx_factor) + queue->rd_wr_idx_start;
|
|
|
|
|
|
+ if (REQUIRES_IDX_TRANSLATION(queue)) {
|
|
|
|
+ to_write_idx = IDX_TRANSLATE_DEFAULT_TO_CUSTOM(queue, to_write_idx);
|
|
HWFNC_DBG_Q("translated to_write_idx:%lu rd_wr_idx start:%lu factor:%lu\n",
|
|
HWFNC_DBG_Q("translated to_write_idx:%lu rd_wr_idx start:%lu factor:%lu\n",
|
|
to_write_idx, queue->rd_wr_idx_start, queue->rd_wr_idx_factor);
|
|
to_write_idx, queue->rd_wr_idx_start, queue->rd_wr_idx_factor);
|
|
}
|
|
}
|
|
@@ -438,6 +466,90 @@ exit:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+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)
|
|
|
|
+{
|
|
|
|
+ u32 q_size_u32, payload_size, payload_size_u32, read_idx, write_idx, second_idx, *wr_ptr;
|
|
|
|
+ struct msm_hw_fence_queue_payload tmp, *first_payload, *second_payload;
|
|
|
|
+ struct msm_hw_fence_hfi_queue_header *hfi_header;
|
|
|
|
+ struct msm_hw_fence_queue *queue;
|
|
|
|
+ int ret = 0;
|
|
|
|
+
|
|
|
|
+ queue = &hw_fence_client->queues[HW_FENCE_TX_QUEUE - 1];
|
|
|
|
+ if (_get_update_queue_params(queue, &hfi_header, &q_size_u32, &payload_size,
|
|
|
|
+ &payload_size_u32, &wr_ptr)) {
|
|
|
|
+ HWFNC_ERR("Invalid client:%d tx queue\n", hw_fence_client->client_id);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Make sure data is ready before read */
|
|
|
|
+ mb();
|
|
|
|
+
|
|
|
|
+ /* Get read and write index */
|
|
|
|
+ read_idx = hfi_header->read_index;
|
|
|
|
+ write_idx = *wr_ptr;
|
|
|
|
+
|
|
|
|
+ /* translate read and write indexes from custom indexing to dwords with no offset */
|
|
|
|
+ _translate_queue_indexes_custom_to_default(queue, &read_idx, &write_idx);
|
|
|
|
+
|
|
|
|
+ if (read_idx == write_idx) {
|
|
|
|
+ HWFNC_DBG_Q("Empty queue, no entry matches with hash:%llu\n", hash);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ first_payload = (struct msm_hw_fence_queue_payload *)((u32 *)queue->va_queue + read_idx);
|
|
|
|
+ HWFNC_DBG_Q("client:%d txq: va=0x%pK pa=0x%pK idx:%d ptr_payload:0x%pK\n",
|
|
|
|
+ hw_fence_client->client_id, queue->va_queue, queue->pa_queue, read_idx,
|
|
|
|
+ first_payload);
|
|
|
|
+
|
|
|
|
+ if (first_payload->hash == hash) {
|
|
|
|
+ /* Swap not needed, update first payload in client queue with fence error */
|
|
|
|
+ first_payload->error = error;
|
|
|
|
+ } else {
|
|
|
|
+ /* Check whether second entry matches hash */
|
|
|
|
+ second_idx = read_idx + payload_size_u32;
|
|
|
|
+
|
|
|
|
+ /* wrap-around case */
|
|
|
|
+ if (second_idx >= q_size_u32)
|
|
|
|
+ second_idx = 0;
|
|
|
|
+
|
|
|
|
+ if (second_idx == write_idx) {
|
|
|
|
+ HWFNC_ERR("Failed to find matching entry with hash:%llu\n", hash);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ second_payload = (struct msm_hw_fence_queue_payload *)
|
|
|
|
+ ((u32 *)queue->va_queue + second_idx);
|
|
|
|
+ HWFNC_DBG_Q("client:%d txq: va=0x%pK pa=0x%pK idx:%d ptr_payload:0x%pK\n",
|
|
|
|
+ hw_fence_client->client_id, queue->va_queue, queue->pa_queue, second_idx,
|
|
|
|
+ second_payload);
|
|
|
|
+
|
|
|
|
+ if (second_payload->hash != hash) {
|
|
|
|
+ HWFNC_ERR("hash:%llu not found in first two queue payloads:%u, %u\n", hash,
|
|
|
|
+ read_idx, second_idx);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* swap first and second payload, updating error field in new first payload */
|
|
|
|
+ tmp = *first_payload;
|
|
|
|
+ *first_payload = *second_payload;
|
|
|
|
+ first_payload->error = error;
|
|
|
|
+ *second_payload = tmp;
|
|
|
|
+
|
|
|
|
+ HWFNC_DBG_L("client_id:%d txq move from idx:%u to idx:%u hash:%llu c:%llu s:%llu\n",
|
|
|
|
+ hw_fence_client->client_id, read_idx, second_idx, hash, tmp.ctxt_id,
|
|
|
|
+ tmp.seqno);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* update memory for the messages */
|
|
|
|
+ wmb();
|
|
|
|
+
|
|
|
|
+ HWFNC_DBG_L("client_id:%d update tx queue index:%u hash:%llu error:%u\n",
|
|
|
|
+ hw_fence_client->client_id, read_idx, hash, error);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static int init_global_locks(struct hw_fence_driver_data *drv_data)
|
|
static int init_global_locks(struct hw_fence_driver_data *drv_data)
|
|
{
|
|
{
|
|
struct msm_hw_fence_mem_addr *mem_descriptor;
|
|
struct msm_hw_fence_mem_addr *mem_descriptor;
|
|
@@ -1204,15 +1316,22 @@ static void _fence_ctl_signal(struct hw_fence_driver_data *drv_data,
|
|
|
|
|
|
HWFNC_DBG_H("We must signal the client now! hfence hash:%llu\n", hash);
|
|
HWFNC_DBG_H("We must signal the client now! hfence hash:%llu\n", hash);
|
|
|
|
|
|
- /* Write to Rx queue */
|
|
|
|
- if (hw_fence_client->update_rxq)
|
|
|
|
- hw_fence_update_queue(drv_data, hw_fence_client, hw_fence->ctx_id,
|
|
|
|
- hw_fence->seq_id, hash, flags, client_data, error, HW_FENCE_RX_QUEUE - 1);
|
|
|
|
-
|
|
|
|
- /* Signal the hw fence now */
|
|
|
|
- if (hw_fence_client->send_ipc)
|
|
|
|
- hw_fence_ipcc_trigger_signal(drv_data, tx_client_id, rx_client_id,
|
|
|
|
- hw_fence_client->ipc_signal_id);
|
|
|
|
|
|
+ /* Call fence error callback */
|
|
|
|
+ if (error && hw_fence_client->fence_error_cb) {
|
|
|
|
+ hw_fence_utils_fence_error_cb(hw_fence_client, hw_fence->ctx_id, hw_fence->seq_id,
|
|
|
|
+ hash, flags, error);
|
|
|
|
+ } else {
|
|
|
|
+ /* Write to Rx queue */
|
|
|
|
+ if (hw_fence_client->update_rxq)
|
|
|
|
+ hw_fence_update_queue(drv_data, hw_fence_client, hw_fence->ctx_id,
|
|
|
|
+ hw_fence->seq_id, hash, flags, client_data, error,
|
|
|
|
+ HW_FENCE_RX_QUEUE - 1);
|
|
|
|
+
|
|
|
|
+ /* Signal the hw fence now */
|
|
|
|
+ if (hw_fence_client->send_ipc)
|
|
|
|
+ hw_fence_ipcc_trigger_signal(drv_data, tx_client_id, rx_client_id,
|
|
|
|
+ hw_fence_client->ipc_signal_id);
|
|
|
|
+ }
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_DEBUG_FS)
|
|
#if IS_ENABLED(CONFIG_DEBUG_FS)
|
|
if (hw_fence_client->client_id >= HW_FENCE_CLIENT_ID_VAL0
|
|
if (hw_fence_client->client_id >= HW_FENCE_CLIENT_ID_VAL0
|
|
@@ -1355,6 +1474,7 @@ int hw_fence_process_fence_array(struct hw_fence_driver_data *drv_data,
|
|
|
|
|
|
/* child fence is already signaled */
|
|
/* child fence is already signaled */
|
|
GLOBAL_ATOMIC_STORE(drv_data, &join_fence->lock, 1); /* lock */
|
|
GLOBAL_ATOMIC_STORE(drv_data, &join_fence->lock, 1); /* lock */
|
|
|
|
+ join_fence->error |= hw_fence_child->error;
|
|
if (--join_fence->pending_child_cnt == 0)
|
|
if (--join_fence->pending_child_cnt == 0)
|
|
signal_join_fence = true;
|
|
signal_join_fence = true;
|
|
|
|
|
|
@@ -1400,8 +1520,8 @@ int hw_fence_process_fence_array(struct hw_fence_driver_data *drv_data,
|
|
if (signal_join_fence) {
|
|
if (signal_join_fence) {
|
|
|
|
|
|
/* signal the join hw fence */
|
|
/* signal the join hw fence */
|
|
- _fence_ctl_signal(drv_data, hw_fence_client, join_fence, *hash_join_fence, 0, 0,
|
|
|
|
- client_data);
|
|
|
|
|
|
+ _fence_ctl_signal(drv_data, hw_fence_client, join_fence, *hash_join_fence, 0,
|
|
|
|
+ client_data, join_fence->error);
|
|
set_bit(MSM_HW_FENCE_FLAG_SIGNALED_BIT, &array->base.flags);
|
|
set_bit(MSM_HW_FENCE_FLAG_SIGNALED_BIT, &array->base.flags);
|
|
|
|
|
|
/*
|
|
/*
|