+void __rte_hot
+dpaa2_dev_process_parallel_event(struct qbman_swp *swp,
+ const struct qbman_fd *fd,
+ const struct qbman_result *dq,
+ struct dpaa2_queue *rxq,
+ struct rte_event *ev)
+{
+ rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) +
+ DPAA2_FD_PTA_SIZE + 16));
+
+ ev->flow_id = rxq->ev.flow_id;
+ ev->sub_event_type = rxq->ev.sub_event_type;
+ ev->event_type = RTE_EVENT_TYPE_ETHDEV;
+ ev->op = RTE_EVENT_OP_NEW;
+ ev->sched_type = rxq->ev.sched_type;
+ ev->queue_id = rxq->ev.queue_id;
+ ev->priority = rxq->ev.priority;
+
+ ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id);
+
+ qbman_swp_dqrr_consume(swp, dq);
+}
+
+void __rte_hot
+dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused,
+ const struct qbman_fd *fd,
+ const struct qbman_result *dq,
+ struct dpaa2_queue *rxq,
+ struct rte_event *ev)
+{
+ uint8_t dqrr_index;
+
+ rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) +
+ DPAA2_FD_PTA_SIZE + 16));
+
+ ev->flow_id = rxq->ev.flow_id;
+ ev->sub_event_type = rxq->ev.sub_event_type;
+ ev->event_type = RTE_EVENT_TYPE_ETHDEV;
+ ev->op = RTE_EVENT_OP_NEW;
+ ev->sched_type = rxq->ev.sched_type;
+ ev->queue_id = rxq->ev.queue_id;
+ ev->priority = rxq->ev.priority;
+
+ ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id);
+
+ dqrr_index = qbman_get_dqrr_idx(dq);
+ *dpaa2_seqn(ev->mbuf) = dqrr_index + 1;
+ DPAA2_PER_LCORE_DQRR_SIZE++;
+ DPAA2_PER_LCORE_DQRR_HELD |= 1 << dqrr_index;
+ DPAA2_PER_LCORE_DQRR_MBUF(dqrr_index) = ev->mbuf;
+}
+
+void __rte_hot
+dpaa2_dev_process_ordered_event(struct qbman_swp *swp,
+ const struct qbman_fd *fd,
+ const struct qbman_result *dq,
+ struct dpaa2_queue *rxq,
+ struct rte_event *ev)
+{
+ rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) +
+ DPAA2_FD_PTA_SIZE + 16));
+
+ ev->flow_id = rxq->ev.flow_id;
+ ev->sub_event_type = rxq->ev.sub_event_type;
+ ev->event_type = RTE_EVENT_TYPE_ETHDEV;
+ ev->op = RTE_EVENT_OP_NEW;
+ ev->sched_type = rxq->ev.sched_type;
+ ev->queue_id = rxq->ev.queue_id;
+ ev->priority = rxq->ev.priority;
+
+ ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id);
+
+ *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP;
+ *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT;
+ *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_seqnum(dq) << DPAA2_EQCR_SEQNUM_SHIFT;
+
+ qbman_swp_dqrr_consume(swp, dq);
+}
+
+uint16_t
+dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+ /* Function receive frames for a given device and VQ */
+ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
+ struct qbman_result *dq_storage;
+ uint32_t fqid = dpaa2_q->fqid;
+ int ret, num_rx = 0, next_pull = nb_pkts, num_pulled;
+ uint8_t pending, status;
+ struct qbman_swp *swp;
+ const struct qbman_fd *fd;
+ struct qbman_pull_desc pulldesc;
+ struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
+ struct dpaa2_dev_priv *priv = eth_data->dev_private;
+
+ if (unlikely(dpaa2_enable_err_queue))
+ dump_err_pkts(priv->rx_err_vq);
+
+ if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
+ ret = dpaa2_affine_qbman_swp();
+ if (ret) {
+ DPAA2_PMD_ERR(
+ "Failed to allocate IO portal, tid: %d\n",
+ rte_gettid());
+ return 0;
+ }
+ }
+ swp = DPAA2_PER_LCORE_PORTAL;
+
+ do {
+ dq_storage = dpaa2_q->q_storage->dq_storage[0];
+ qbman_pull_desc_clear(&pulldesc);
+ qbman_pull_desc_set_fq(&pulldesc, fqid);
+ qbman_pull_desc_set_storage(&pulldesc, dq_storage,
+ (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
+
+ if (next_pull > dpaa2_dqrr_size) {
+ qbman_pull_desc_set_numframes(&pulldesc,
+ dpaa2_dqrr_size);
+ next_pull -= dpaa2_dqrr_size;
+ } else {
+ qbman_pull_desc_set_numframes(&pulldesc, next_pull);
+ next_pull = 0;
+ }
+
+ while (1) {
+ if (qbman_swp_pull(swp, &pulldesc)) {
+ DPAA2_PMD_DP_DEBUG(
+ "VDQ command is not issued.QBMAN is busy\n");
+ /* Portal was busy, try again */
+ continue;
+ }
+ break;
+ }
+
+ rte_prefetch0((void *)((size_t)(dq_storage + 1)));
+ /* Check if the previous issued command is completed. */
+ while (!qbman_check_command_complete(dq_storage))
+ ;
+
+ num_pulled = 0;
+ pending = 1;
+ do {
+ /* Loop until the dq_storage is updated with
+ * new token by QBMAN
+ */
+ while (!qbman_check_new_result(dq_storage))
+ ;
+ rte_prefetch0((void *)((size_t)(dq_storage + 2)));
+ /* Check whether Last Pull command is Expired and
+ * setting Condition for Loop termination
+ */
+ if (qbman_result_DQ_is_pull_complete(dq_storage)) {
+ pending = 0;
+ /* Check for valid frame. */
+ status = qbman_result_DQ_flags(dq_storage);
+ if (unlikely((status &
+ QBMAN_DQ_STAT_VALIDFRAME) == 0))
+ continue;
+ }
+ fd = qbman_result_DQ_fd(dq_storage);
+
+#ifndef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
+ if (dpaa2_svr_family != SVR_LX2160A) {
+ const struct qbman_fd *next_fd =
+ qbman_result_DQ_fd(dq_storage + 1);
+
+ /* Prefetch Annotation address for the parse
+ * results.
+ */
+ rte_prefetch0((DPAA2_IOVA_TO_VADDR(
+ DPAA2_GET_FD_ADDR(next_fd) +
+ DPAA2_FD_PTA_SIZE + 16)));
+ }
+#endif
+
+ if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg))
+ bufs[num_rx] = eth_sg_fd_to_mbuf(fd,
+ eth_data->port_id);
+ else
+ bufs[num_rx] = eth_fd_to_mbuf(fd,
+ eth_data->port_id);
+
+#if defined(RTE_LIBRTE_IEEE1588)
+ if (bufs[num_rx]->ol_flags & PKT_RX_IEEE1588_TMST) {
+ priv->rx_timestamp =
+ *dpaa2_timestamp_dynfield(bufs[num_rx]);
+ }
+#endif
+
+ if (eth_data->dev_conf.rxmode.offloads &
+ RTE_ETH_RX_OFFLOAD_VLAN_STRIP) {
+ rte_vlan_strip(bufs[num_rx]);
+ }
+
+ dq_storage++;
+ num_rx++;
+ num_pulled++;
+ } while (pending);
+ /* Last VDQ provided all packets and more packets are requested */
+ } while (next_pull && num_pulled == dpaa2_dqrr_size);
+
+ dpaa2_q->rx_pkts += num_rx;
+
+ return num_rx;
+}
+
+uint16_t dpaa2_dev_tx_conf(void *queue)
+{
+ /* Function receive frames for a given device and VQ */
+ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
+ struct qbman_result *dq_storage;
+ uint32_t fqid = dpaa2_q->fqid;
+ int ret, num_tx_conf = 0, num_pulled;
+ uint8_t pending, status;
+ struct qbman_swp *swp;
+ const struct qbman_fd *fd, *next_fd;
+ struct qbman_pull_desc pulldesc;
+ struct qbman_release_desc releasedesc;
+ uint32_t bpid;
+ uint64_t buf;
+#if defined(RTE_LIBRTE_IEEE1588)
+ struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
+ struct dpaa2_dev_priv *priv = eth_data->dev_private;
+ struct dpaa2_annot_hdr *annotation;
+ void *v_addr;
+ struct rte_mbuf *mbuf;
+#endif
+
+ if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
+ ret = dpaa2_affine_qbman_swp();
+ if (ret) {
+ DPAA2_PMD_ERR(
+ "Failed to allocate IO portal, tid: %d\n",
+ rte_gettid());
+ return 0;
+ }
+ }
+ swp = DPAA2_PER_LCORE_PORTAL;
+
+ do {
+ dq_storage = dpaa2_q->q_storage->dq_storage[0];
+ qbman_pull_desc_clear(&pulldesc);
+ qbman_pull_desc_set_fq(&pulldesc, fqid);
+ qbman_pull_desc_set_storage(&pulldesc, dq_storage,
+ (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
+
+ qbman_pull_desc_set_numframes(&pulldesc, dpaa2_dqrr_size);
+
+ while (1) {
+ if (qbman_swp_pull(swp, &pulldesc)) {
+ DPAA2_PMD_DP_DEBUG("VDQ command is not issued."
+ "QBMAN is busy\n");
+ /* Portal was busy, try again */
+ continue;
+ }
+ break;
+ }
+
+ rte_prefetch0((void *)((size_t)(dq_storage + 1)));
+ /* Check if the previous issued command is completed. */
+ while (!qbman_check_command_complete(dq_storage))
+ ;
+
+ num_pulled = 0;
+ pending = 1;
+ do {
+ /* Loop until the dq_storage is updated with
+ * new token by QBMAN
+ */
+ while (!qbman_check_new_result(dq_storage))
+ ;
+ rte_prefetch0((void *)((size_t)(dq_storage + 2)));
+ /* Check whether Last Pull command is Expired and
+ * setting Condition for Loop termination
+ */
+ if (qbman_result_DQ_is_pull_complete(dq_storage)) {
+ pending = 0;
+ /* Check for valid frame. */
+ status = qbman_result_DQ_flags(dq_storage);
+ if (unlikely((status &
+ QBMAN_DQ_STAT_VALIDFRAME) == 0))
+ continue;
+ }
+ fd = qbman_result_DQ_fd(dq_storage);
+
+ next_fd = qbman_result_DQ_fd(dq_storage + 1);
+ /* Prefetch Annotation address for the parse results */
+ rte_prefetch0((void *)(size_t)
+ (DPAA2_GET_FD_ADDR(next_fd) +
+ DPAA2_FD_PTA_SIZE + 16));
+
+ bpid = DPAA2_GET_FD_BPID(fd);
+
+ /* Create a release descriptor required for releasing
+ * buffers into QBMAN
+ */
+ qbman_release_desc_clear(&releasedesc);
+ qbman_release_desc_set_bpid(&releasedesc, bpid);
+
+ buf = DPAA2_GET_FD_ADDR(fd);
+ /* feed them to bman */
+ do {
+ ret = qbman_swp_release(swp, &releasedesc,
+ &buf, 1);
+ } while (ret == -EBUSY);
+
+ dq_storage++;
+ num_tx_conf++;
+ num_pulled++;
+#if defined(RTE_LIBRTE_IEEE1588)
+ v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd));
+ mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr,
+ rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
+
+ if (mbuf->ol_flags & PKT_TX_IEEE1588_TMST) {
+ annotation = (struct dpaa2_annot_hdr *)((size_t)
+ DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) +
+ DPAA2_FD_PTA_SIZE);
+ priv->tx_timestamp = annotation->word2;
+ }
+#endif
+ } while (pending);
+
+ /* Last VDQ provided all packets and more packets are requested */
+ } while (num_pulled == dpaa2_dqrr_size);
+
+ dpaa2_q->rx_pkts += num_tx_conf;
+
+ return num_tx_conf;
+}
+
+/* Configure the egress frame annotation for timestamp update */
+static void enable_tx_tstamp(struct qbman_fd *fd)
+{
+ struct dpaa2_faead *fd_faead;
+
+ /* Set frame annotation status field as valid */
+ (fd)->simple.frc |= DPAA2_FD_FRC_FASV;
+
+ /* Set frame annotation egress action descriptor as valid */
+ (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV;
+
+ /* Set Annotation Length as 128B */
+ (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL;
+
+ /* enable update of confirmation frame annotation */
+ fd_faead = (struct dpaa2_faead *)((size_t)
+ DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) +
+ DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET);
+ fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV |
+ DPAA2_ANNOT_FAEAD_UPD;
+}
+