+int
+tf_msg_session_resc_qcaps(struct tf *tfp,
+ enum tf_dir dir,
+ uint16_t size,
+ struct tf_rm_resc_req_entry *query,
+ enum tf_rm_resc_resv_strategy *resv_strategy)
+{
+ int rc;
+ int i;
+ struct tfp_send_msg_parms parms = { 0 };
+ struct hwrm_tf_session_resc_qcaps_input req = { 0 };
+ struct hwrm_tf_session_resc_qcaps_output resp = { 0 };
+ uint8_t fw_session_id;
+ struct tf_msg_dma_buf qcaps_buf = { 0 };
+ struct tf_rm_resc_req_entry *data;
+ int dma_size;
+
+ if (size == 0 || query == NULL || resv_strategy == NULL) {
+ TFP_DRV_LOG(ERR,
+ "%s: Resource QCAPS parameter error, rc:%s\n",
+ tf_dir_2_str(dir),
+ strerror(-EINVAL));
+ return -EINVAL;
+ }
+
+ rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: Unable to lookup FW id, rc:%s\n",
+ tf_dir_2_str(dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Prepare DMA buffer */
+ dma_size = size * sizeof(struct tf_rm_resc_req_entry);
+ rc = tf_msg_alloc_dma_buf(&qcaps_buf, dma_size);
+ if (rc)
+ return rc;
+
+ /* Populate the request */
+ req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
+ req.flags = tfp_cpu_to_le_16(dir);
+ req.qcaps_size = size;
+ req.qcaps_addr = qcaps_buf.pa_addr;
+
+ parms.tf_type = HWRM_TF_SESSION_RESC_QCAPS;
+ parms.req_data = (uint32_t *)&req;
+ parms.req_size = sizeof(req);
+ parms.resp_data = (uint32_t *)&resp;
+ parms.resp_size = sizeof(resp);
+ parms.mailbox = TF_KONG_MB;
+
+ rc = tfp_send_msg_direct(tfp, &parms);
+ if (rc)
+ return rc;
+
+ /* Process the response
+ * Should always get expected number of entries
+ */
+ if (resp.size != size) {
+ TFP_DRV_LOG(ERR,
+ "%s: QCAPS message error, rc:%s\n",
+ tf_dir_2_str(dir),
+ strerror(-EINVAL));
+ return -EINVAL;
+ }
+
+ /* Post process the response */
+ data = (struct tf_rm_resc_req_entry *)qcaps_buf.va_addr;
+ for (i = 0; i < size; i++) {
+ query[i].type = tfp_cpu_to_le_32(data[i].type);
+ query[i].min = tfp_le_to_cpu_16(data[i].min);
+ query[i].max = tfp_le_to_cpu_16(data[i].max);
+ }
+
+ *resv_strategy = resp.flags &
+ HWRM_TF_SESSION_RESC_QCAPS_OUTPUT_FLAGS_SESS_RESV_STRATEGY_MASK;
+
+ tf_msg_free_dma_buf(&qcaps_buf);
+
+ return rc;
+}
+
+int
+tf_msg_session_resc_alloc(struct tf *tfp,
+ enum tf_dir dir,
+ uint16_t size,
+ struct tf_rm_resc_req_entry *request,
+ struct tf_rm_resc_entry *resv)
+{
+ int rc;
+ int i;
+ struct tfp_send_msg_parms parms = { 0 };
+ struct hwrm_tf_session_resc_alloc_input req = { 0 };
+ struct hwrm_tf_session_resc_alloc_output resp = { 0 };
+ uint8_t fw_session_id;
+ struct tf_msg_dma_buf req_buf = { 0 };
+ struct tf_msg_dma_buf resv_buf = { 0 };
+ struct tf_rm_resc_req_entry *req_data;
+ struct tf_rm_resc_entry *resv_data;
+ int dma_size;
+
+ rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: Unable to lookup FW id, rc:%s\n",
+ tf_dir_2_str(dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Prepare DMA buffers */
+ dma_size = size * sizeof(struct tf_rm_resc_req_entry);
+ rc = tf_msg_alloc_dma_buf(&req_buf, dma_size);
+ if (rc)
+ return rc;
+
+ dma_size = size * sizeof(struct tf_rm_resc_entry);
+ rc = tf_msg_alloc_dma_buf(&resv_buf, dma_size);
+ if (rc)
+ return rc;
+
+ /* Populate the request */
+ req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
+ req.flags = tfp_cpu_to_le_16(dir);
+ req.req_size = size;
+
+ req_data = (struct tf_rm_resc_req_entry *)req_buf.va_addr;
+ for (i = 0; i < size; i++) {
+ req_data[i].type = tfp_cpu_to_le_32(request[i].type);
+ req_data[i].min = tfp_cpu_to_le_16(request[i].min);
+ req_data[i].max = tfp_cpu_to_le_16(request[i].max);
+ }
+
+ req.req_addr = req_buf.pa_addr;
+ req.resp_addr = resv_buf.pa_addr;
+
+ parms.tf_type = HWRM_TF_SESSION_RESC_ALLOC;
+ parms.req_data = (uint32_t *)&req;
+ parms.req_size = sizeof(req);
+ parms.resp_data = (uint32_t *)&resp;
+ parms.resp_size = sizeof(resp);
+ parms.mailbox = TF_KONG_MB;
+
+ rc = tfp_send_msg_direct(tfp, &parms);
+ if (rc)
+ return rc;
+
+ /* Process the response
+ * Should always get expected number of entries
+ */
+ if (resp.size != size) {
+ TFP_DRV_LOG(ERR,
+ "%s: Alloc message error, rc:%s\n",
+ tf_dir_2_str(dir),
+ strerror(-EINVAL));
+ return -EINVAL;
+ }
+
+ /* Post process the response */
+ resv_data = (struct tf_rm_resc_entry *)resv_buf.va_addr;
+ for (i = 0; i < size; i++) {
+ resv[i].type = tfp_cpu_to_le_32(resv_data[i].type);
+ resv[i].start = tfp_cpu_to_le_16(resv_data[i].start);
+ resv[i].stride = tfp_cpu_to_le_16(resv_data[i].stride);
+ }
+
+ tf_msg_free_dma_buf(&req_buf);
+ tf_msg_free_dma_buf(&resv_buf);
+
+ return rc;
+}
+