|
@@ -77,23 +77,31 @@
|
|
|
*/
|
|
|
struct hw_fence_client_type_desc hw_fence_client_types[HW_FENCE_MAX_CLIENT_TYPE] = {
|
|
|
{"gpu", HW_FENCE_CLIENT_ID_CTX0, HW_FENCE_CLIENT_TYPE_MAX_GPU, HW_FENCE_CLIENT_TYPE_MAX_GPU,
|
|
|
- HW_FENCE_CLIENT_QUEUES, 0, 0, false},
|
|
|
+ HW_FENCE_CLIENT_QUEUES, 0, 0, 0, 0, 0, 0, false},
|
|
|
{"dpu", HW_FENCE_CLIENT_ID_CTL0, HW_FENCE_CLIENT_TYPE_MAX_DPU, HW_FENCE_CLIENT_TYPE_MAX_DPU,
|
|
|
- HW_FENCE_CLIENT_QUEUES, 0, 0, false},
|
|
|
+ HW_FENCE_CLIENT_QUEUES, 0, 0, 0, 0, 0, 0, false},
|
|
|
{"val", HW_FENCE_CLIENT_ID_VAL0, HW_FENCE_CLIENT_TYPE_MAX_VAL, HW_FENCE_CLIENT_TYPE_MAX_VAL,
|
|
|
- HW_FENCE_CLIENT_QUEUES, 0, 0, false},
|
|
|
- {"ipe", HW_FENCE_CLIENT_ID_IPE, HW_FENCE_CLIENT_TYPE_MAX_IPE, 0,
|
|
|
- HW_FENCE_CLIENT_QUEUES, 0, 0, false},
|
|
|
- {"vpu", HW_FENCE_CLIENT_ID_VPU, HW_FENCE_CLIENT_TYPE_MAX_VPU, 0,
|
|
|
- HW_FENCE_CLIENT_QUEUES, 0, 0, false},
|
|
|
- {"ife0", HW_FENCE_CLIENT_ID_IFE0, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, true},
|
|
|
- {"ife1", HW_FENCE_CLIENT_ID_IFE1, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, true},
|
|
|
- {"ife2", HW_FENCE_CLIENT_ID_IFE2, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, true},
|
|
|
- {"ife3", HW_FENCE_CLIENT_ID_IFE3, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, true},
|
|
|
- {"ife4", HW_FENCE_CLIENT_ID_IFE4, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, true},
|
|
|
- {"ife5", HW_FENCE_CLIENT_ID_IFE5, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, true},
|
|
|
- {"ife6", HW_FENCE_CLIENT_ID_IFE6, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, true},
|
|
|
- {"ife7", HW_FENCE_CLIENT_ID_IFE7, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, true},
|
|
|
+ HW_FENCE_CLIENT_QUEUES, 0, 0, 0, 0, 0, 0, false},
|
|
|
+ {"ipe", HW_FENCE_CLIENT_ID_IPE, HW_FENCE_CLIENT_TYPE_MAX_IPE, 0, HW_FENCE_CLIENT_QUEUES,
|
|
|
+ 0, 0, 0, 0, 0, 0, false},
|
|
|
+ {"vpu", HW_FENCE_CLIENT_ID_VPU, HW_FENCE_CLIENT_TYPE_MAX_VPU, 0, HW_FENCE_CLIENT_QUEUES,
|
|
|
+ 0, 0, 0, 0, 0, 0, false},
|
|
|
+ {"ife0", HW_FENCE_CLIENT_ID_IFE0, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, 0, 0, 0, 0,
|
|
|
+ true},
|
|
|
+ {"ife1", HW_FENCE_CLIENT_ID_IFE1, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, 0, 0, 0, 0,
|
|
|
+ true},
|
|
|
+ {"ife2", HW_FENCE_CLIENT_ID_IFE2, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, 0, 0, 0, 0,
|
|
|
+ true},
|
|
|
+ {"ife3", HW_FENCE_CLIENT_ID_IFE3, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, 0, 0, 0, 0,
|
|
|
+ true},
|
|
|
+ {"ife4", HW_FENCE_CLIENT_ID_IFE4, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, 0, 0, 0, 0,
|
|
|
+ true},
|
|
|
+ {"ife5", HW_FENCE_CLIENT_ID_IFE5, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, 0, 0, 0, 0,
|
|
|
+ true},
|
|
|
+ {"ife6", HW_FENCE_CLIENT_ID_IFE6, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, 0, 0, 0, 0,
|
|
|
+ true},
|
|
|
+ {"ife7", HW_FENCE_CLIENT_ID_IFE7, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0, 0, 0, 0, 0,
|
|
|
+ true},
|
|
|
};
|
|
|
|
|
|
static void _lock(uint64_t *wait)
|
|
@@ -549,23 +557,16 @@ int hw_fence_utils_reserve_mem(struct hw_fence_driver_data *drv_data,
|
|
|
*size = drv_data->hw_fence_mem_fences_table_size;
|
|
|
break;
|
|
|
case HW_FENCE_MEM_RESERVE_CLIENT_QUEUE:
|
|
|
- if (client_id >= drv_data->clients_num) {
|
|
|
- HWFNC_ERR("unexpected client_id:%d\n", client_id);
|
|
|
+ if (client_id >= drv_data->clients_num ||
|
|
|
+ !drv_data->hw_fence_client_queue_size[client_id].type) {
|
|
|
+ HWFNC_ERR("unexpected client_id:%d for clients_num:%lu\n", client_id,
|
|
|
+ drv_data->clients_num);
|
|
|
ret = -EINVAL;
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
start_offset = drv_data->hw_fence_client_queue_size[client_id].start_offset;
|
|
|
- *size = drv_data->hw_fence_client_queue_size[client_id].mem_size;
|
|
|
-
|
|
|
- /*
|
|
|
- * If this error occurs when client should be valid, check that support for this
|
|
|
- * client has been configured in device-tree properties.
|
|
|
- */
|
|
|
- if (!*size) {
|
|
|
- HWFNC_ERR("invalid client_id:%d not reserved client queue\n", client_id);
|
|
|
- ret = -EINVAL;
|
|
|
- }
|
|
|
+ *size = drv_data->hw_fence_client_queue_size[client_id].type->mem_size;
|
|
|
break;
|
|
|
default:
|
|
|
HWFNC_ERR("Invalid mem reserve type:%d\n", type);
|
|
@@ -592,6 +593,92 @@ exit:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int _parse_client_queue_dt_props_extra(struct hw_fence_driver_data *drv_data,
|
|
|
+ struct hw_fence_client_type_desc *desc)
|
|
|
+{
|
|
|
+ u32 max_idx_from_zero, payload_size_u32 = HW_FENCE_CLIENT_QUEUE_PAYLOAD / sizeof(u32);
|
|
|
+ char name[40];
|
|
|
+ u32 tmp[4];
|
|
|
+ bool idx_by_payload = false;
|
|
|
+ int count, ret;
|
|
|
+
|
|
|
+ snprintf(name, sizeof(name), "qcom,hw-fence-client-type-%s-extra", desc->name);
|
|
|
+
|
|
|
+ /* check if property is present */
|
|
|
+ ret = of_property_read_bool(drv_data->dev->of_node, name);
|
|
|
+ if (!ret)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ count = of_property_count_u32_elems(drv_data->dev->of_node, name);
|
|
|
+ if (count <= 0 || count > 4) {
|
|
|
+ HWFNC_ERR("invalid %s extra dt props count:%d\n", desc->name, count);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = of_property_read_u32_array(drv_data->dev->of_node, name, tmp, count);
|
|
|
+ if (ret) {
|
|
|
+ HWFNC_ERR("Failed to read %s extra dt properties ret=%d count=%d\n", desc->name,
|
|
|
+ ret, count);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ desc->start_padding = tmp[0];
|
|
|
+ if (count >= 2)
|
|
|
+ desc->end_padding = tmp[1];
|
|
|
+ if (count >= 3)
|
|
|
+ desc->txq_idx_start = tmp[2];
|
|
|
+ if (count >= 4) {
|
|
|
+ if (tmp[3] > 1) {
|
|
|
+ HWFNC_ERR("%s invalid txq_idx_by_payload prop:%lu\n", desc->name, tmp[3]);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+ idx_by_payload = tmp[3];
|
|
|
+ desc->txq_idx_factor = idx_by_payload ? payload_size_u32 : 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (desc->start_padding % sizeof(u32) || desc->end_padding % sizeof(u32) ||
|
|
|
+ (desc->start_padding + desc->end_padding) % sizeof(u64)) {
|
|
|
+ HWFNC_ERR("%s start_padding:%lu end_padding:%lu violates mem alignment\n",
|
|
|
+ desc->name, desc->start_padding, desc->end_padding);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (desc->start_padding >= U32_MAX - HW_FENCE_HFI_CLIENT_HEADERS_SIZE(desc->queues_num)) {
|
|
|
+ HWFNC_ERR("%s client queues_num:%lu start_padding:%lu will overflow mem_size\n",
|
|
|
+ desc->name, desc->queues_num, desc->start_padding);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (desc->end_padding >= U32_MAX - HW_FENCE_HFI_CLIENT_HEADERS_SIZE(desc->queues_num) -
|
|
|
+ desc->start_padding) {
|
|
|
+ HWFNC_ERR("%s client q_num:%lu start_p:%lu end_p:%lu will overflow mem_size\n",
|
|
|
+ desc->name, desc->queues_num, desc->start_padding, desc->end_padding);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ max_idx_from_zero = idx_by_payload ? desc->queue_entries :
|
|
|
+ desc->queue_entries * payload_size_u32;
|
|
|
+ if (desc->txq_idx_start >= U32_MAX - max_idx_from_zero) {
|
|
|
+ HWFNC_ERR("%s txq_idx start:%lu by_payload:%s q_entries:%d will overflow txq_idx\n",
|
|
|
+ desc->name, desc->txq_idx_start, idx_by_payload ? "true" : "false",
|
|
|
+ desc->queue_entries);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ HWFNC_DBG_INIT("%s: start_p=%lu end_p=%lu txq_idx_start:%lu txq_idx_by_payload:%s\n",
|
|
|
+ desc->name, desc->start_padding, desc->end_padding, desc->txq_idx_start,
|
|
|
+ idx_by_payload ? "true" : "false");
|
|
|
+
|
|
|
+exit:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static int _parse_client_queue_dt_props_indv(struct hw_fence_driver_data *drv_data,
|
|
|
struct hw_fence_client_type_desc *desc)
|
|
|
{
|
|
@@ -600,7 +687,7 @@ static int _parse_client_queue_dt_props_indv(struct hw_fence_driver_data *drv_da
|
|
|
u32 queue_size;
|
|
|
int ret;
|
|
|
|
|
|
- /* parse client queue property from device-tree */
|
|
|
+ /* parse client queue properties from device-tree */
|
|
|
snprintf(name, sizeof(name), "qcom,hw-fence-client-type-%s", desc->name);
|
|
|
ret = of_property_read_u32_array(drv_data->dev->of_node, name, tmp, 4);
|
|
|
if (ret) {
|
|
@@ -626,6 +713,13 @@ static int _parse_client_queue_dt_props_indv(struct hw_fence_driver_data *drv_da
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ /* parse extra client queue properties from device-tree */
|
|
|
+ ret = _parse_client_queue_dt_props_extra(drv_data, desc);
|
|
|
+ if (ret) {
|
|
|
+ HWFNC_ERR("%s failed to parse extra dt props\n", desc->name);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
/* compute mem_size */
|
|
|
if (desc->queue_entries >= U32_MAX / HW_FENCE_CLIENT_QUEUE_PAYLOAD) {
|
|
|
HWFNC_ERR("%s client queue entries:%lu will overflow client queue size\n",
|
|
@@ -635,17 +729,18 @@ static int _parse_client_queue_dt_props_indv(struct hw_fence_driver_data *drv_da
|
|
|
|
|
|
queue_size = HW_FENCE_CLIENT_QUEUE_PAYLOAD * desc->queue_entries;
|
|
|
if (queue_size >= ((U32_MAX & PAGE_MASK) -
|
|
|
- HW_FENCE_HFI_CLIENT_HEADERS_SIZE(desc->queues_num)) / desc->queues_num) {
|
|
|
- HWFNC_ERR("%s client queue size:%lu will overflow client queue mem size\n",
|
|
|
- desc->name, queue_size);
|
|
|
+ (HW_FENCE_HFI_CLIENT_HEADERS_SIZE(desc->queues_num) +
|
|
|
+ desc->start_padding + desc->end_padding)) / desc->queues_num) {
|
|
|
+ HWFNC_ERR("%s client queue_sz:%lu start_p:%lu end_p:%lu will overflow mem size\n",
|
|
|
+ desc->name, queue_size, desc->start_padding, desc->end_padding);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
desc->mem_size = PAGE_ALIGN(HW_FENCE_HFI_CLIENT_HEADERS_SIZE(desc->queues_num) +
|
|
|
- (queue_size * desc->queues_num));
|
|
|
+ (queue_size * desc->queues_num) + desc->start_padding + desc->end_padding);
|
|
|
|
|
|
if (desc->mem_size > MAX_CLIENT_QUEUE_MEM_SIZE) {
|
|
|
- HWFNC_ERR("%s client queue mem_size:%lu greater than max client queue size:%lu\n",
|
|
|
+ HWFNC_ERR("%s client queue mem_size:%lu greater than max mem size:%lu\n",
|
|
|
desc->name, desc->mem_size, MAX_CLIENT_QUEUE_MEM_SIZE);
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -690,7 +785,7 @@ static int _parse_client_queue_dt_props(struct hw_fence_driver_data *drv_data)
|
|
|
drv_data->clients_num = HW_FENCE_MAX_STATIC_CLIENTS_INDEX + configurable_clients_num;
|
|
|
|
|
|
/* allocate memory for client queue size descriptors */
|
|
|
- size = drv_data->clients_num * sizeof(struct hw_fence_client_queue_size_desc);
|
|
|
+ size = drv_data->clients_num * sizeof(struct hw_fence_client_queue_desc);
|
|
|
drv_data->hw_fence_client_queue_size = kzalloc(size, GFP_KERNEL);
|
|
|
if (!drv_data->hw_fence_client_queue_size)
|
|
|
return -ENOMEM;
|
|
@@ -707,9 +802,7 @@ static int _parse_client_queue_dt_props(struct hw_fence_driver_data *drv_data)
|
|
|
hw_fence_utils_get_client_id_priv(drv_data, client_id_ext);
|
|
|
|
|
|
drv_data->hw_fence_client_queue_size[client_id] =
|
|
|
- (struct hw_fence_client_queue_size_desc)
|
|
|
- {desc->queues_num, desc->queue_entries, desc->mem_size,
|
|
|
- start_offset, desc->skip_txq_wr_idx};
|
|
|
+ (struct hw_fence_client_queue_desc){desc, start_offset};
|
|
|
HWFNC_DBG_INIT("%s client_id_ext:%lu client_id:%lu start_offset:%lu\n",
|
|
|
desc->name, client_id_ext, client_id, start_offset);
|
|
|
start_offset += desc->mem_size;
|
|
@@ -929,10 +1022,13 @@ enum hw_fence_client_id hw_fence_utils_get_client_id_priv(struct hw_fence_driver
|
|
|
return client_id_priv;
|
|
|
}
|
|
|
|
|
|
-bool hw_fence_utils_skips_txq_wr_idx(struct hw_fence_driver_data *drv_data, int client_id)
|
|
|
+int hw_fence_utils_get_queues_num(struct hw_fence_driver_data *drv_data, int client_id)
|
|
|
{
|
|
|
- if (!drv_data || client_id >= drv_data->clients_num)
|
|
|
- return false;
|
|
|
+ if (!drv_data || client_id >= drv_data->clients_num ||
|
|
|
+ !drv_data->hw_fence_client_queue_size[client_id].type) {
|
|
|
+ HWFNC_ERR("invalid access to client:%d queues_num\n", client_id);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- return drv_data->hw_fence_client_queue_size[client_id].skip_txq_wr_idx;
|
|
|
+ return drv_data->hw_fence_client_queue_size[client_id].type->queues_num;
|
|
|
}
|