soc: fsl: dpio: Adding QMAN multiple enqueue interface
authorYouri Querry <youri.querry_1@nxp.com>
Thu, 12 Dec 2019 17:01:13 +0000 (17:01 +0000)
committerLi Yang <leoyang.li@nxp.com>
Thu, 20 Feb 2020 00:06:16 +0000 (18:06 -0600)
Update of QMAN the interface to enqueue frame. We now support multiple
enqueue (qbman_swp_enqueue_multiple) and multiple enqueue with
a table of descriptor (qbman_swp_enqueue_multiple_desc).

Signed-off-by: Youri Querry <youri.querry_1@nxp.com>
Acked-by: Roy Pledge <roy.pledge@nxp.com>
Signed-off-by: Li Yang <leoyang.li@nxp.com>
drivers/soc/fsl/dpio/dpio-service.c
drivers/soc/fsl/dpio/qbman-portal.c
drivers/soc/fsl/dpio/qbman-portal.h
include/soc/fsl/dpaa2-io.h

index 518a8e0..cd4f641 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright 2014-2016 Freescale Semiconductor Inc.
- * Copyright 2016 NXP
+ * Copyright 2016-2019 NXP
  *
  */
 #include <linux/types.h>
@@ -433,6 +433,69 @@ int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d,
 EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq);
 
 /**
+ * dpaa2_io_service_enqueue_multiple_fq() - Enqueue multiple frames
+ * to a frame queue using one fqid.
+ * @d: the given DPIO service.
+ * @fqid: the given frame queue id.
+ * @fd: the frame descriptor which is enqueued.
+ * @nb: number of frames to be enqueud
+ *
+ * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready,
+ * or -ENODEV if there is no dpio service.
+ */
+int dpaa2_io_service_enqueue_multiple_fq(struct dpaa2_io *d,
+                               u32 fqid,
+                               const struct dpaa2_fd *fd,
+                               int nb)
+{
+       struct qbman_eq_desc ed;
+
+       d = service_select(d);
+       if (!d)
+               return -ENODEV;
+
+       qbman_eq_desc_clear(&ed);
+       qbman_eq_desc_set_no_orp(&ed, 0);
+       qbman_eq_desc_set_fq(&ed, fqid);
+
+       return qbman_swp_enqueue_multiple(d->swp, &ed, fd, 0, nb);
+}
+EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_fq);
+
+/**
+ * dpaa2_io_service_enqueue_multiple_desc_fq() - Enqueue multiple frames
+ * to different frame queue using a list of fqids.
+ * @d: the given DPIO service.
+ * @fqid: the given list of frame queue ids.
+ * @fd: the frame descriptor which is enqueued.
+ * @nb: number of frames to be enqueud
+ *
+ * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready,
+ * or -ENODEV if there is no dpio service.
+ */
+int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d,
+                               u32 *fqid,
+                               const struct dpaa2_fd *fd,
+                               int nb)
+{
+       int i;
+       struct qbman_eq_desc ed[32];
+
+       d = service_select(d);
+       if (!d)
+               return -ENODEV;
+
+       for (i = 0; i < nb; i++) {
+               qbman_eq_desc_clear(&ed[i]);
+               qbman_eq_desc_set_no_orp(&ed[i], 0);
+               qbman_eq_desc_set_fq(&ed[i], fqid[i]);
+       }
+
+       return qbman_swp_enqueue_multiple_desc(d->swp, &ed[0], fd, nb);
+}
+EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_desc_fq);
+
+/**
  * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD.
  * @d: the given DPIO service.
  * @qdid: the given queuing destination id.
@@ -526,7 +589,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire);
 
 /**
  * dpaa2_io_store_create() - Create the dma memory storage for dequeue result.
- * @max_frames: the maximum number of dequeued result for frames, must be <= 16.
+ * @max_frames: the maximum number of dequeued result for frames, must be <= 32.
  * @dev:        the device to allow mapping/unmapping the DMAable region.
  *
  * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)".
@@ -541,7 +604,7 @@ struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
        struct dpaa2_io_store *ret;
        size_t size;
 
-       if (!max_frames || (max_frames > 16))
+       if (!max_frames || (max_frames > 32))
                return NULL;
 
        ret = kmalloc(sizeof(*ret), GFP_KERNEL);
index c66f5b7..5a37ac8 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
- * Copyright 2016 NXP
+ * Copyright 2016-2019 NXP
  *
  */
 
 
 #include "qbman-portal.h"
 
-#define QMAN_REV_4000   0x04000000
-#define QMAN_REV_4100   0x04010000
-#define QMAN_REV_4101   0x04010001
-#define QMAN_REV_5000   0x05000000
-
-#define QMAN_REV_MASK   0xffff0000
-
 /* All QBMan command and result structures use this "valid bit" encoding */
 #define QB_VALID_BIT ((u32)0x80)
 
@@ -156,7 +149,7 @@ static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn,     u8 est, u8 rpm, u8 dcm,
  */
 struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
 {
-       struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL);
+       struct qbman_swp *p = kzalloc(sizeof(*p), GFP_KERNEL);
        u32 reg;
 
        if (!p)
@@ -467,22 +460,32 @@ static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p,
 int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
                      const struct dpaa2_fd *fd)
 {
-       struct qbman_eq_desc *p;
+       struct qbman_eq_desc_with_fd *p;
        u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR);
 
        if (!EQAR_SUCCESS(eqar))
                return -EBUSY;
 
        p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));
-       memcpy(&p->dca, &d->dca, 31);
+       /* This is mapped as DEVICE type memory, writes are
+        * with address alignment:
+        * desc.dca address alignment = 1
+        * desc.seqnum address alignment = 2
+        * desc.orpid address alignment = 4
+        * desc.tgtid address alignment = 8
+        */
+       p->desc.dca = d->dca;
+       p->desc.seqnum = d->seqnum;
+       p->desc.orpid = d->orpid;
+       memcpy(&p->desc.tgtid, &d->tgtid, 24);
        memcpy(&p->fd, fd, sizeof(*fd));
 
        if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {
                /* Set the verb byte, have to substitute in the valid-bit */
                dma_wmb();
-               p->verb = d->verb | EQAR_VB(eqar);
+               p->desc.verb = d->verb | EQAR_VB(eqar);
        } else {
-               p->verb = d->verb | EQAR_VB(eqar);
+               p->desc.verb = d->verb | EQAR_VB(eqar);
                dma_wmb();
                qbman_write_eqcr_am_rt_register(s, EQAR_IDX(eqar));
        }
@@ -490,6 +493,60 @@ int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
        return 0;
 }
 
+/**
+ * qbman_swp_enqueue_multiple() - Issue a multi enqueue command
+ * using one enqueue descriptor
+ * @s:  the software portal used for enqueue
+ * @d:  the enqueue descriptor
+ * @fd: table pointer of frame descriptor table to be enqueued
+ * @flags: table pointer of flags, not used for the moment
+ * @num_frames: number of fd to be enqueued
+ *
+ * Return the number of fd enqueued, or a negative error number.
+ */
+int qbman_swp_enqueue_multiple(struct qbman_swp *s,
+                              const struct qbman_eq_desc *d,
+                              const struct dpaa2_fd *fd,
+                              uint32_t *flags,
+                              int num_frames)
+{
+       int count = 0;
+
+       while (count < num_frames) {
+               if (qbman_swp_enqueue(s, d, fd) != 0)
+                       break;
+               count++;
+       }
+
+       return count;
+}
+
+/**
+ * qbman_swp_enqueue_multiple_desc() - Issue a multi enqueue command
+ * using multiple enqueue descriptor
+ * @s:  the software portal used for enqueue
+ * @d:  table of minimal enqueue descriptor
+ * @fd: table pointer of frame descriptor table to be enqueued
+ * @num_frames: number of fd to be enqueued
+ *
+ * Return the number of fd enqueued, or a negative error number.
+ */
+int qbman_swp_enqueue_multiple_desc(struct qbman_swp *s,
+                                   const struct qbman_eq_desc *d,
+                                   const struct dpaa2_fd *fd,
+                                   int num_frames)
+{
+       int count = 0;
+
+       while (count < num_frames) {
+               if (qbman_swp_enqueue(s, &(d[count]), fd) != 0)
+                       break;
+               count++;
+       }
+
+       return count;
+}
+
 /* Static (push) dequeue */
 
 /**
index f3ec5d2..ac58a97 100644 (file)
@@ -9,6 +9,13 @@
 
 #include <soc/fsl/dpaa2-fd.h>
 
+#define QMAN_REV_4000   0x04000000
+#define QMAN_REV_4100   0x04010000
+#define QMAN_REV_4101   0x04010001
+#define QMAN_REV_5000   0x05000000
+
+#define QMAN_REV_MASK   0xffff0000
+
 struct dpaa2_dq;
 struct qbman_swp;
 
@@ -81,6 +88,10 @@ struct qbman_eq_desc {
        u8 wae;
        u8 rspid;
        __le64 rsp_addr;
+};
+
+struct qbman_eq_desc_with_fd {
+       struct qbman_eq_desc desc;
        u8 fd[32];
 };
 
@@ -193,6 +204,19 @@ void *qbman_swp_mc_start(struct qbman_swp *p);
 void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb);
 void *qbman_swp_mc_result(struct qbman_swp *p);
 
+int
+qbman_swp_enqueue_multiple(struct qbman_swp *s,
+                          const struct qbman_eq_desc *d,
+                          const struct dpaa2_fd *fd,
+                          uint32_t *flags,
+                          int num_frames);
+
+int
+qbman_swp_enqueue_multiple_desc(struct qbman_swp *s,
+                               const struct qbman_eq_desc *d,
+                               const struct dpaa2_fd *fd,
+                               int num_frames);
+
 /**
  * qbman_result_is_DQ() - check if the dequeue result is a dequeue response
  * @dq: the dequeue result to be checked
index 672cfb5..c9d8499 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 /*
  * Copyright 2014-2016 Freescale Semiconductor Inc.
- * Copyright NXP
+ * Copyright 2017-2019 NXP
  *
  */
 #ifndef __FSL_DPAA2_IO_H
@@ -109,6 +109,10 @@ int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,
 
 int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid,
                                const struct dpaa2_fd *fd);
+int dpaa2_io_service_enqueue_multiple_fq(struct dpaa2_io *d, u32 fqid,
+                               const struct dpaa2_fd *fd, int number_of_frame);
+int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d, u32 *fqid,
+                               const struct dpaa2_fd *fd, int number_of_frame);
 int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
                                u16 qdbin, const struct dpaa2_fd *fd);
 int dpaa2_io_service_release(struct dpaa2_io *d, u16 bpid,