bus/fslmc: add QBMAN API to do enqueue with multiple frames
[dpdk.git] / drivers / bus / fslmc / qbman / qbman_portal.c
index 97df703..f212829 100644 (file)
@@ -525,15 +525,26 @@ static int qbman_swp_enqueue_ring_mode(struct qbman_swp *s,
        return 0;
 }
 
-int qbman_swp_fill_ring(struct qbman_swp *s,
-                       const struct qbman_eq_desc *d,
-                       const struct qbman_fd *fd,
-                       __attribute__((unused)) uint8_t burst_index)
+int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
+                     const struct qbman_fd *fd)
+{
+       if (s->sys.eqcr_mode == qman_eqcr_vb_array)
+               return qbman_swp_enqueue_array_mode(s, d, fd);
+       else    /* Use ring mode by default */
+               return qbman_swp_enqueue_ring_mode(s, d, fd);
+}
+
+int qbman_swp_enqueue_multiple(struct qbman_swp *s,
+                              const struct qbman_eq_desc *d,
+                              const struct qbman_fd *fd,
+                              int num_frames)
 {
        uint32_t *p;
        const uint32_t *cl = qb_cl(d);
-       uint32_t eqcr_ci;
+       uint32_t eqcr_ci, eqcr_pi;
        uint8_t diff;
+       int i, num_enqueued = 0;
+       uint64_t addr_cena;
 
        if (!s->eqcr.available) {
                eqcr_ci = s->eqcr.ci;
@@ -543,62 +554,58 @@ int qbman_swp_fill_ring(struct qbman_swp *s,
                                   eqcr_ci, s->eqcr.ci);
                s->eqcr.available += diff;
                if (!diff)
-                       return -EBUSY;
+                       return 0;
        }
-       p = qbman_cena_write_start_wo_shadow(&s->sys,
-               QBMAN_CENA_SWP_EQCR((s->eqcr.pi/* +burst_index */) & 7));
-       memcpy(&p[1], &cl[1], 7 * 4);
-       memcpy(&p[8], fd, sizeof(struct qbman_fd));
-
-       /* lwsync(); */
-       p[0] = cl[0] | s->eqcr.pi_vb;
-
-       s->eqcr.pi++;
-       s->eqcr.pi &= 0xF;
-       s->eqcr.available--;
-       if (!(s->eqcr.pi & 7))
-               s->eqcr.pi_vb ^= QB_VALID_BIT;
-
-       return 0;
-}
 
-int qbman_swp_flush_ring(struct qbman_swp *s)
-{
-       void *ptr = s->sys.addr_cena;
+       eqcr_pi = s->eqcr.pi;
+       num_enqueued = (s->eqcr.available < num_frames) ?
+                       s->eqcr.available : num_frames;
+       s->eqcr.available -= num_enqueued;
+       /* Fill in the EQCR ring */
+       for (i = 0; i < num_enqueued; i++) {
+               p = qbman_cena_write_start_wo_shadow(&s->sys,
+                                       QBMAN_CENA_SWP_EQCR(eqcr_pi & 7));
+               memcpy(&p[1], &cl[1], 28);
+               memcpy(&p[8], &fd[i], sizeof(*fd));
+               eqcr_pi++;
+               eqcr_pi &= 0xF;
+       }
 
-       dcbf((uint64_t)ptr);
-       dcbf((uint64_t)ptr + 0x40);
-       dcbf((uint64_t)ptr + 0x80);
-       dcbf((uint64_t)ptr + 0xc0);
-       dcbf((uint64_t)ptr + 0x100);
-       dcbf((uint64_t)ptr + 0x140);
-       dcbf((uint64_t)ptr + 0x180);
-       dcbf((uint64_t)ptr + 0x1c0);
+       lwsync();
 
-       return 0;
-}
+       /* Set the verb byte, have to substitute in the valid-bit */
+       eqcr_pi = s->eqcr.pi;
+       for (i = 0; i < num_enqueued; i++) {
+               p = qbman_cena_write_start_wo_shadow(&s->sys,
+                                       QBMAN_CENA_SWP_EQCR(eqcr_pi & 7));
+               p[0] = cl[0] | s->eqcr.pi_vb;
+               eqcr_pi++;
+               eqcr_pi &= 0xF;
+               if (!(eqcr_pi & 7))
+                       s->eqcr.pi_vb ^= QB_VALID_BIT;
+       }
 
-void qbman_sync(void)
-{
-       lwsync();
-}
+       /* Flush all the cacheline without load/store in between */
+       eqcr_pi = s->eqcr.pi;
+       addr_cena = (uint64_t)s->sys.addr_cena;
+       for (i = 0; i < num_enqueued; i++) {
+               dcbf((uint64_t *)(addr_cena +
+                               QBMAN_CENA_SWP_EQCR(eqcr_pi & 7)));
+               eqcr_pi++;
+               eqcr_pi &= 0xF;
+       }
+       s->eqcr.pi = eqcr_pi;
 
-int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
-                     const struct qbman_fd *fd)
-{
-       if (s->sys.eqcr_mode == qman_eqcr_vb_array)
-               return qbman_swp_enqueue_array_mode(s, d, fd);
-       else    /* Use ring mode by default */
-               return qbman_swp_enqueue_ring_mode(s, d, fd);
+       return num_enqueued;
 }
 
-int qbman_swp_enqueue_multiple_eqdesc(struct qbman_swp *s,
-                              const struct qbman_eq_desc *d,
-                              const struct qbman_fd *fd,
-                              int num_frames)
+int qbman_swp_enqueue_multiple_desc(struct qbman_swp *s,
+                                   const struct qbman_eq_desc *d,
+                                   const struct qbman_fd *fd,
+                                   int num_frames)
 {
        uint32_t *p;
-       const uint32_t *cl = qb_cl(d);
+       const uint32_t *cl;
        uint32_t eqcr_ci, eqcr_pi;
        uint8_t diff;
        int i, num_enqueued = 0;
@@ -623,29 +630,26 @@ int qbman_swp_enqueue_multiple_eqdesc(struct qbman_swp *s,
        for (i = 0; i < num_enqueued; i++) {
                p = qbman_cena_write_start_wo_shadow(&s->sys,
                                        QBMAN_CENA_SWP_EQCR(eqcr_pi & 7));
+               cl = qb_cl(&d[i]);
                memcpy(&p[1], &cl[1], 28);
                memcpy(&p[8], &fd[i], sizeof(*fd));
                eqcr_pi++;
                eqcr_pi &= 0xF;
-               /*Pointing to the next enqueue descriptor*/
-               cl += (sizeof(struct qbman_eq_desc) / sizeof(uint32_t));
        }
 
        lwsync();
 
        /* Set the verb byte, have to substitute in the valid-bit */
        eqcr_pi = s->eqcr.pi;
-       cl = qb_cl(d);
        for (i = 0; i < num_enqueued; i++) {
                p = qbman_cena_write_start_wo_shadow(&s->sys,
                                        QBMAN_CENA_SWP_EQCR(eqcr_pi & 7));
+               cl = qb_cl(&d[i]);
                p[0] = cl[0] | s->eqcr.pi_vb;
                eqcr_pi++;
                eqcr_pi &= 0xF;
                if (!(eqcr_pi & 7))
                        s->eqcr.pi_vb ^= QB_VALID_BIT;
-               /*Pointing to the next enqueue descriptor*/
-               cl += (sizeof(struct qbman_eq_desc) / sizeof(uint32_t));
        }
 
        /* Flush all the cacheline without load/store in between */
@@ -1493,87 +1497,3 @@ struct qbman_result *qbman_get_dqrr_from_idx(struct qbman_swp *s, uint8_t idx)
        dq = qbman_cena_read(&s->sys, QBMAN_CENA_SWP_DQRR(idx));
        return dq;
 }
-
-int qbman_swp_send_multiple(struct qbman_swp *s,
-                           const struct qbman_eq_desc *d,
-                           const struct qbman_fd *fd,
-                           int frames_to_send)
-{
-       uint32_t *p;
-       const uint32_t *cl = qb_cl(d);
-       uint32_t eqcr_ci;
-       uint8_t diff;
-       int sent = 0;
-       int i;
-       int initial_pi = s->eqcr.pi;
-       uint64_t start_pointer;
-
-       if (!s->eqcr.available) {
-               eqcr_ci = s->eqcr.ci;
-               s->eqcr.ci = qbman_cena_read_reg(&s->sys,
-                                QBMAN_CENA_SWP_EQCR_CI) & 0xF;
-               diff = qm_cyc_diff(QBMAN_EQCR_SIZE,
-                                  eqcr_ci, s->eqcr.ci);
-               if (!diff)
-                       goto done;
-               s->eqcr.available += diff;
-       }
-
-       /* we are trying to send frames_to_send,
-        * if we have enough space in the ring
-        */
-       while (s->eqcr.available && frames_to_send--) {
-               p = qbman_cena_write_start_wo_shadow_fast(&s->sys,
-                                       QBMAN_CENA_SWP_EQCR((initial_pi) & 7));
-               /* Write command (except of first byte) and FD */
-               memcpy(&p[1], &cl[1], 7 * 4);
-               memcpy(&p[8], &fd[sent], sizeof(struct qbman_fd));
-
-               initial_pi++;
-               initial_pi &= 0xF;
-               s->eqcr.available--;
-               sent++;
-       }
-
-done:
-       initial_pi =  s->eqcr.pi;
-       lwsync();
-
-       /* in order for flushes to complete faster:
-        * we use a following trick: we record all lines in 32 bit word
-        */
-
-       initial_pi =  s->eqcr.pi;
-       for (i = 0; i < sent; i++) {
-               p = qbman_cena_write_start_wo_shadow_fast(&s->sys,
-                                       QBMAN_CENA_SWP_EQCR((initial_pi) & 7));
-
-               p[0] = cl[0] | s->eqcr.pi_vb;
-               initial_pi++;
-               initial_pi &= 0xF;
-
-               if (!(initial_pi & 7))
-                       s->eqcr.pi_vb ^= QB_VALID_BIT;
-       }
-
-       initial_pi = s->eqcr.pi;
-
-       /* We need  to flush all the lines but without
-        * load/store operations between them.
-        * We assign start_pointer before we start loop so that
-        * in loop we do not read it from memory
-        */
-       start_pointer = (uint64_t)s->sys.addr_cena;
-       for (i = 0; i < sent; i++) {
-               p = (uint32_t *)(start_pointer
-                                + QBMAN_CENA_SWP_EQCR(initial_pi & 7));
-               dcbf((uint64_t)p);
-               initial_pi++;
-               initial_pi &= 0xF;
-       }
-
-       /* Update producer index for the next call */
-       s->eqcr.pi = initial_pi;
-
-       return sent;
-}