|
@@ -21,16 +21,50 @@
|
|
|
*/
|
|
|
#define MAX_CLIENT_QUEUE_MEM_SIZE 0x100000
|
|
|
|
|
|
+/**
|
|
|
+ * HW_FENCE_MAX_CLIENT_TYPE_STATIC:
|
|
|
+ * Total number of client types without configurable number of sub-clients (GFX, DPU, VAL, IPE, VPU)
|
|
|
+ */
|
|
|
+#define HW_FENCE_MAX_CLIENT_TYPE_STATIC 5
|
|
|
+
|
|
|
+/**
|
|
|
+ * HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE:
|
|
|
+ * Maximum number of client types with configurable number of sub-clients (e.g. IFE)
|
|
|
+ */
|
|
|
+#define HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE 8
|
|
|
+
|
|
|
/**
|
|
|
* HW_FENCE_MAX_CLIENT_TYPE:
|
|
|
- * Total number of client types (GFX, DPU, VAL)
|
|
|
+ * Total number of client types with and without configurable number of sub-clients
|
|
|
*/
|
|
|
-#define HW_FENCE_MAX_CLIENT_TYPE 3
|
|
|
+#define HW_FENCE_MAX_CLIENT_TYPE (HW_FENCE_MAX_CLIENT_TYPE_STATIC + \
|
|
|
+ HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE)
|
|
|
+
|
|
|
+/**
|
|
|
+ * HW_FENCE_MAX_STATIC_CLIENTS_INDEX:
|
|
|
+ * Maximum number of static clients, i.e. clients without configurable numbers of sub-clients
|
|
|
+ */
|
|
|
+#define HW_FENCE_MAX_STATIC_CLIENTS_INDEX HW_FENCE_CLIENT_ID_IFE0
|
|
|
+
|
|
|
+/**
|
|
|
+ * HW_FENCE_MIN_RXQ_CLIENTS:
|
|
|
+ * Minimum number of static hw fence clients with rxq
|
|
|
+ */
|
|
|
+#define HW_FENCE_MIN_RXQ_CLIENTS HW_FENCE_CLIENT_ID_VAL6
|
|
|
+
|
|
|
+/**
|
|
|
+ * HW_FENCE_MIN_RXQ_CLIENT_TYPE:
|
|
|
+ * Minimum number of static hw fence client types with rxq (GFX, DPU, VAL)
|
|
|
+ */
|
|
|
+#define HW_FENCE_MIN_RXQ_CLIENT_TYPE 3
|
|
|
|
|
|
/* Maximum number of clients for each client type */
|
|
|
#define HW_FENCE_CLIENT_TYPE_MAX_GPU 1
|
|
|
#define HW_FENCE_CLIENT_TYPE_MAX_DPU 6
|
|
|
#define HW_FENCE_CLIENT_TYPE_MAX_VAL 7
|
|
|
+#define HW_FENCE_CLIENT_TYPE_MAX_IPE 1
|
|
|
+#define HW_FENCE_CLIENT_TYPE_MAX_VPU 1
|
|
|
+#define HW_FENCE_CLIENT_TYPE_MAX_IFE 32
|
|
|
|
|
|
/**
|
|
|
* struct hw_fence_client_type_desc - Structure holding client type properties, including static
|
|
@@ -71,7 +105,8 @@ struct hw_fence_client_type_desc {
|
|
|
* 1. Client types must be in the same order as client_ids within the enum 'hw_fence_client_id'.
|
|
|
* 2. Each HW Fence client ID must be described by one of the client types in this table.
|
|
|
* 3. A new client type must set: name, init_id, max_clients_num, clients_num, and queues_num.
|
|
|
- * 4. HW_FENCE_MAX_CLIENT_TYPE must be incremented for new client types.
|
|
|
+ * 4. Either constant HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE or HW_FENCE_MAX_CLIENT_TYPE_STATIC must
|
|
|
+ * be incremented as appropriate for new client types.
|
|
|
*/
|
|
|
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,
|
|
@@ -80,6 +115,18 @@ struct hw_fence_client_type_desc hw_fence_client_types[HW_FENCE_MAX_CLIENT_TYPE]
|
|
|
HW_FENCE_CLIENT_QUEUES, 0, 0},
|
|
|
{"val", HW_FENCE_CLIENT_ID_VAL0, HW_FENCE_CLIENT_TYPE_MAX_VAL, HW_FENCE_CLIENT_TYPE_MAX_VAL,
|
|
|
HW_FENCE_CLIENT_QUEUES, 0, 0},
|
|
|
+ {"ipe", HW_FENCE_CLIENT_ID_IPE, HW_FENCE_CLIENT_TYPE_MAX_IPE, 0,
|
|
|
+ HW_FENCE_CLIENT_QUEUES, 0, 0},
|
|
|
+ {"vpu", HW_FENCE_CLIENT_ID_VPU, HW_FENCE_CLIENT_TYPE_MAX_VPU, 0,
|
|
|
+ HW_FENCE_CLIENT_QUEUES, 0, 0},
|
|
|
+ {"ife0", HW_FENCE_CLIENT_ID_IFE0, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
|
|
|
+ {"ife1", HW_FENCE_CLIENT_ID_IFE1, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
|
|
|
+ {"ife2", HW_FENCE_CLIENT_ID_IFE2, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
|
|
|
+ {"ife3", HW_FENCE_CLIENT_ID_IFE3, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
|
|
|
+ {"ife4", HW_FENCE_CLIENT_ID_IFE4, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
|
|
|
+ {"ife5", HW_FENCE_CLIENT_ID_IFE5, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
|
|
|
+ {"ife6", HW_FENCE_CLIENT_ID_IFE6, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
|
|
|
+ {"ife7", HW_FENCE_CLIENT_ID_IFE7, HW_FENCE_CLIENT_TYPE_MAX_IFE, 0, 1, 0, 0},
|
|
|
};
|
|
|
|
|
|
static void _lock(uint64_t *wait)
|
|
@@ -527,15 +574,16 @@ int hw_fence_utils_reserve_mem(struct hw_fence_driver_data *drv_data,
|
|
|
case HW_FENCE_MEM_RESERVE_LOCKS_REGION:
|
|
|
/* Locks region starts at the end of the ctrl queues */
|
|
|
start_offset = drv_data->hw_fence_mem_ctrl_queues_size;
|
|
|
- *size = HW_FENCE_MEM_LOCKS_SIZE;
|
|
|
+ *size = HW_FENCE_MEM_LOCKS_SIZE(drv_data->rxq_clients_num);
|
|
|
break;
|
|
|
case HW_FENCE_MEM_RESERVE_TABLE:
|
|
|
/* HW Fence table starts at the end of the Locks region */
|
|
|
- start_offset = drv_data->hw_fence_mem_ctrl_queues_size + HW_FENCE_MEM_LOCKS_SIZE;
|
|
|
+ start_offset = drv_data->hw_fence_mem_ctrl_queues_size +
|
|
|
+ HW_FENCE_MEM_LOCKS_SIZE(drv_data->rxq_clients_num);
|
|
|
*size = drv_data->hw_fence_mem_fences_table_size;
|
|
|
break;
|
|
|
case HW_FENCE_MEM_RESERVE_CLIENT_QUEUE:
|
|
|
- if (client_id >= HW_FENCE_CLIENT_MAX) {
|
|
|
+ if (client_id >= drv_data->clients_num) {
|
|
|
HWFNC_ERR("unexpected client_id:%d\n", client_id);
|
|
|
ret = -EINVAL;
|
|
|
goto exit;
|
|
@@ -641,9 +689,10 @@ static int _parse_client_queue_dt_props(struct hw_fence_driver_data *drv_data)
|
|
|
struct hw_fence_client_type_desc *desc;
|
|
|
int i, j, ret;
|
|
|
u32 start_offset;
|
|
|
+ size_t size;
|
|
|
+ int configurable_clients_num = 0;
|
|
|
|
|
|
- start_offset = PAGE_ALIGN(drv_data->hw_fence_mem_ctrl_queues_size +
|
|
|
- HW_FENCE_MEM_LOCKS_SIZE + drv_data->hw_fence_mem_fences_table_size);
|
|
|
+ drv_data->rxq_clients_num = HW_FENCE_MIN_RXQ_CLIENTS;
|
|
|
for (i = 0; i < HW_FENCE_MAX_CLIENT_TYPE; i++) {
|
|
|
desc = &hw_fence_client_types[i];
|
|
|
ret = _parse_client_queue_dt_props_indv(drv_data, desc);
|
|
@@ -653,12 +702,43 @@ static int _parse_client_queue_dt_props(struct hw_fence_driver_data *drv_data)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- /* initialize client queue size desc for each client */
|
|
|
+ if (i >= HW_FENCE_MIN_RXQ_CLIENT_TYPE &&
|
|
|
+ desc->queues_num == HW_FENCE_CLIENT_QUEUES)
|
|
|
+ drv_data->rxq_clients_num += desc->clients_num;
|
|
|
+
|
|
|
+ if (i >= HW_FENCE_MAX_CLIENT_TYPE_STATIC)
|
|
|
+ configurable_clients_num += desc->clients_num;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* store client type descriptors for configurable client indexing logic */
|
|
|
+ drv_data->hw_fence_client_types = hw_fence_client_types;
|
|
|
+
|
|
|
+ /* clients and size desc are allocated for all static clients regardless of device-tree */
|
|
|
+ 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);
|
|
|
+ drv_data->hw_fence_client_queue_size = kzalloc(size, GFP_KERNEL);
|
|
|
+ if (!drv_data->hw_fence_client_queue_size)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ /* initialize client queue size desc for each client */
|
|
|
+ start_offset = PAGE_ALIGN(drv_data->hw_fence_mem_ctrl_queues_size +
|
|
|
+ HW_FENCE_MEM_LOCKS_SIZE(drv_data->rxq_clients_num) +
|
|
|
+ drv_data->hw_fence_mem_fences_table_size);
|
|
|
+ for (i = 0; i < HW_FENCE_MAX_CLIENT_TYPE; i++) {
|
|
|
+ desc = &hw_fence_client_types[i];
|
|
|
for (j = 0; j < desc->clients_num; j++) {
|
|
|
- drv_data->hw_fence_client_queue_size[desc->init_id + j] =
|
|
|
+ enum hw_fence_client_id client_id_ext = desc->init_id + j;
|
|
|
+ enum hw_fence_client_id client_id =
|
|
|
+ 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};
|
|
|
+ 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;
|
|
|
}
|
|
|
}
|
|
@@ -670,6 +750,7 @@ static int _parse_client_queue_dt_props(struct hw_fence_driver_data *drv_data)
|
|
|
int hw_fence_utils_parse_dt_props(struct hw_fence_driver_data *drv_data)
|
|
|
{
|
|
|
int ret;
|
|
|
+ size_t size;
|
|
|
u32 val = 0;
|
|
|
|
|
|
ret = of_property_read_u32(drv_data->dev->of_node, "qcom,hw-fence-table-entries", &val);
|
|
@@ -721,11 +802,20 @@ int hw_fence_utils_parse_dt_props(struct hw_fence_driver_data *drv_data)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ /* allocate clients */
|
|
|
+
|
|
|
+ size = drv_data->clients_num * sizeof(struct msm_hw_fence_client *);
|
|
|
+ drv_data->clients = kzalloc(size, GFP_KERNEL);
|
|
|
+ if (!drv_data->clients)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
HWFNC_DBG_INIT("table: entries=%lu mem_size=%lu queue: entries=%lu\b",
|
|
|
drv_data->hw_fence_table_entries, drv_data->hw_fence_mem_fences_table_size,
|
|
|
drv_data->hw_fence_queue_entries);
|
|
|
HWFNC_DBG_INIT("ctrl queue: size=%lu mem_size=%lu\b",
|
|
|
drv_data->hw_fence_ctrl_queue_size, drv_data->hw_fence_mem_ctrl_queues_size);
|
|
|
+ HWFNC_DBG_INIT("clients_num: %lu, total_mem_size:%lu\n", drv_data->clients_num,
|
|
|
+ drv_data->used_mem_size);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -837,3 +927,31 @@ int hw_fence_utils_map_ctl_start(struct hw_fence_driver_data *drv_data)
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+enum hw_fence_client_id hw_fence_utils_get_client_id_priv(struct hw_fence_driver_data *drv_data,
|
|
|
+ enum hw_fence_client_id client_id)
|
|
|
+{
|
|
|
+ int i, client_type, offset;
|
|
|
+ enum hw_fence_client_id client_id_priv;
|
|
|
+
|
|
|
+ if (client_id < HW_FENCE_MAX_STATIC_CLIENTS_INDEX)
|
|
|
+ return client_id;
|
|
|
+
|
|
|
+ /* consolidate external 'hw_fence_client_id' enum into consecutive internal client IDs */
|
|
|
+ client_type = HW_FENCE_MAX_CLIENT_TYPE_STATIC +
|
|
|
+ (client_id - HW_FENCE_MAX_STATIC_CLIENTS_INDEX) /
|
|
|
+ MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT;
|
|
|
+ offset = (client_id - HW_FENCE_MAX_STATIC_CLIENTS_INDEX) %
|
|
|
+ MSM_HW_FENCE_MAX_SIGNAL_PER_CLIENT;
|
|
|
+
|
|
|
+ /* invalid client id out of range of supported configurable sub-clients */
|
|
|
+ if (offset >= drv_data->hw_fence_client_types[client_type].clients_num)
|
|
|
+ return HW_FENCE_CLIENT_MAX;
|
|
|
+
|
|
|
+ client_id_priv = HW_FENCE_MAX_STATIC_CLIENTS_INDEX + offset;
|
|
|
+
|
|
|
+ for (i = HW_FENCE_MAX_CLIENT_TYPE_STATIC; i < client_type; i++)
|
|
|
+ client_id_priv += drv_data->hw_fence_client_types[i].clients_num;
|
|
|
+
|
|
|
+ return client_id_priv;
|
|
|
+}
|