static int k3_udma_glue_cfg_rx_flow()

in ti/k3-udma-glue.c [656:787]


static int k3_udma_glue_cfg_rx_flow(struct k3_udma_glue_rx_channel *rx_chn,
				    u32 flow_idx,
				    struct k3_udma_glue_rx_flow_cfg *flow_cfg)
{
	struct k3_udma_glue_rx_flow *flow = &rx_chn->flows[flow_idx];
	const struct udma_tisci_rm *tisci_rm = rx_chn->common.tisci_rm;
	struct device *dev = rx_chn->common.dev;
	struct ti_sci_msg_rm_udmap_flow_cfg req;
	int rx_ring_id;
	int rx_ringfdq_id;
	int ret = 0;

	flow->udma_rflow = xudma_rflow_get(rx_chn->common.udmax,
					   flow->udma_rflow_id);
	if (IS_ERR(flow->udma_rflow)) {
		ret = PTR_ERR(flow->udma_rflow);
		dev_err(dev, "UDMAX rflow get err %d\n", ret);
		return ret;
	}

	if (flow->udma_rflow_id != xudma_rflow_get_id(flow->udma_rflow)) {
		ret = -ENODEV;
		goto err_rflow_put;
	}

	if (xudma_is_pktdma(rx_chn->common.udmax)) {
		rx_ringfdq_id = flow->udma_rflow_id +
				xudma_get_rflow_ring_offset(rx_chn->common.udmax);
		rx_ring_id = 0;
	} else {
		rx_ring_id = flow_cfg->ring_rxq_id;
		rx_ringfdq_id = flow_cfg->ring_rxfdq0_id;
	}

	/* request and cfg rings */
	ret =  k3_ringacc_request_rings_pair(rx_chn->common.ringacc,
					     rx_ringfdq_id, rx_ring_id,
					     &flow->ringrxfdq,
					     &flow->ringrx);
	if (ret) {
		dev_err(dev, "Failed to get RX/RXFDQ rings %d\n", ret);
		goto err_rflow_put;
	}

	/* Set the dma_dev for the rings to be configured */
	flow_cfg->rx_cfg.dma_dev = k3_udma_glue_rx_get_dma_device(rx_chn);
	flow_cfg->rxfdq_cfg.dma_dev = flow_cfg->rx_cfg.dma_dev;

	/* Set the ASEL value for DMA rings of PKTDMA */
	if (xudma_is_pktdma(rx_chn->common.udmax)) {
		flow_cfg->rx_cfg.asel = rx_chn->common.atype_asel;
		flow_cfg->rxfdq_cfg.asel = rx_chn->common.atype_asel;
	}

	ret = k3_ringacc_ring_cfg(flow->ringrx, &flow_cfg->rx_cfg);
	if (ret) {
		dev_err(dev, "Failed to cfg ringrx %d\n", ret);
		goto err_ringrxfdq_free;
	}

	ret = k3_ringacc_ring_cfg(flow->ringrxfdq, &flow_cfg->rxfdq_cfg);
	if (ret) {
		dev_err(dev, "Failed to cfg ringrxfdq %d\n", ret);
		goto err_ringrxfdq_free;
	}

	if (rx_chn->remote) {
		rx_ring_id = TI_SCI_RESOURCE_NULL;
		rx_ringfdq_id = TI_SCI_RESOURCE_NULL;
	} else {
		rx_ring_id = k3_ringacc_get_ring_id(flow->ringrx);
		rx_ringfdq_id = k3_ringacc_get_ring_id(flow->ringrxfdq);
	}

	memset(&req, 0, sizeof(req));

	req.valid_params =
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_EINFO_PRESENT_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PSINFO_PRESENT_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_ERROR_HANDLING_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DESC_TYPE_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_QNUM_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_SEL_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_SEL_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_SEL_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_SEL_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ0_SZ0_QNUM_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ1_QNUM_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ2_QNUM_VALID |
			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ3_QNUM_VALID;
	req.nav_id = tisci_rm->tisci_dev_id;
	req.flow_index = flow->udma_rflow_id;
	if (rx_chn->common.epib)
		req.rx_einfo_present = 1;
	if (rx_chn->common.psdata_size)
		req.rx_psinfo_present = 1;
	if (flow_cfg->rx_error_handling)
		req.rx_error_handling = 1;
	req.rx_desc_type = 0;
	req.rx_dest_qnum = rx_ring_id;
	req.rx_src_tag_hi_sel = 0;
	req.rx_src_tag_lo_sel = flow_cfg->src_tag_lo_sel;
	req.rx_dest_tag_hi_sel = 0;
	req.rx_dest_tag_lo_sel = 0;
	req.rx_fdq0_sz0_qnum = rx_ringfdq_id;
	req.rx_fdq1_qnum = rx_ringfdq_id;
	req.rx_fdq2_qnum = rx_ringfdq_id;
	req.rx_fdq3_qnum = rx_ringfdq_id;

	ret = tisci_rm->tisci_udmap_ops->rx_flow_cfg(tisci_rm->tisci, &req);
	if (ret) {
		dev_err(dev, "flow%d config failed: %d\n", flow->udma_rflow_id,
			ret);
		goto err_ringrxfdq_free;
	}

	rx_chn->flows_ready++;
	dev_dbg(dev, "flow%d config done. ready:%d\n",
		flow->udma_rflow_id, rx_chn->flows_ready);

	return 0;

err_ringrxfdq_free:
	k3_ringacc_ring_free(flow->ringrxfdq);
	k3_ringacc_ring_free(flow->ringrx);

err_rflow_put:
	xudma_rflow_put(rx_chn->common.udmax, flow->udma_rflow);
	flow->udma_rflow = NULL;

	return ret;
}