bus/dpaa: support creating dynamic HW portal
[dpdk.git] / drivers / bus / dpaa / base / qbman / qman.c
index a53459f..d8fb25a 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "qman.h"
 #include <rte_branch_prediction.h>
+#include <rte_dpaa_bus.h>
 
 /* Compilation constants */
 #define DQRR_MAXFILL   15
@@ -503,7 +504,12 @@ struct qman_portal *qman_create_portal(
 
        p = &portal->p;
 
-       portal->use_eqcr_ci_stashing = ((qman_ip_rev >= QMAN_REV30) ? 1 : 0);
+       if (dpaa_svr_family == SVR_LS1043A_FAMILY)
+               portal->use_eqcr_ci_stashing = 3;
+       else
+               portal->use_eqcr_ci_stashing =
+                                       ((qman_ip_rev >= QMAN_REV30) ? 1 : 0);
+
        /*
         * prep the low-level portal struct with the mapped addresses from the
         * config, everything that follows depends on it and "config" is more
@@ -516,7 +522,7 @@ struct qman_portal *qman_create_portal(
         * and stash with high-than-DQRR priority.
         */
        if (qm_eqcr_init(p, qm_eqcr_pvb,
-                        portal->use_eqcr_ci_stashing ? 3 : 0, 1)) {
+                        portal->use_eqcr_ci_stashing, 1)) {
                pr_err("Qman EQCR initialisation failed\n");
                goto fail_eqcr;
        }
@@ -615,11 +621,52 @@ fail_eqcr:
        return NULL;
 }
 
+#define MAX_GLOBAL_PORTALS 8
+static struct qman_portal global_portals[MAX_GLOBAL_PORTALS];
+static int global_portals_used[MAX_GLOBAL_PORTALS];
+
+static struct qman_portal *
+qman_alloc_global_portal(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < MAX_GLOBAL_PORTALS; i++) {
+               if (global_portals_used[i] == 0) {
+                       global_portals_used[i] = 1;
+                       return &global_portals[i];
+               }
+       }
+       pr_err("No portal available (%x)\n", MAX_GLOBAL_PORTALS);
+
+       return NULL;
+}
+
+static int
+qman_free_global_portal(struct qman_portal *portal)
+{
+       unsigned int i;
+
+       for (i = 0; i < MAX_GLOBAL_PORTALS; i++) {
+               if (&global_portals[i] == portal) {
+                       global_portals_used[i] = 0;
+                       return 0;
+               }
+       }
+       return -1;
+}
+
 struct qman_portal *qman_create_affine_portal(const struct qm_portal_config *c,
-                                             const struct qman_cgrs *cgrs)
+                                             const struct qman_cgrs *cgrs,
+                                             int alloc)
 {
        struct qman_portal *res;
-       struct qman_portal *portal = get_affine_portal();
+       struct qman_portal *portal;
+
+       if (alloc)
+               portal = qman_alloc_global_portal();
+       else
+               portal = get_affine_portal();
+
        /* A criteria for calling this function (from qman_driver.c) is that
         * we're already affine to the cpu and won't schedule onto another cpu.
         */
@@ -669,13 +716,18 @@ void qman_destroy_portal(struct qman_portal *qm)
        spin_lock_destroy(&qm->cgr_lock);
 }
 
-const struct qm_portal_config *qman_destroy_affine_portal(void)
+const struct qm_portal_config *
+qman_destroy_affine_portal(struct qman_portal *qp)
 {
        /* We don't want to redirect if we're a slave, use "raw" */
-       struct qman_portal *qm = get_affine_portal();
+       struct qman_portal *qm;
        const struct qm_portal_config *pcfg;
        int cpu;
 
+       if (qp == NULL)
+               qm = get_affine_portal();
+       else
+               qm = qp;
        pcfg = qm->config;
        cpu = pcfg->cpu;
 
@@ -684,6 +736,9 @@ const struct qm_portal_config *qman_destroy_affine_portal(void)
        spin_lock(&affine_mask_lock);
        CPU_CLR(cpu, &affine_mask);
        spin_unlock(&affine_mask_lock);
+
+       qman_free_global_portal(qm);
+
        return pcfg;
 }
 
@@ -900,7 +955,7 @@ static inline unsigned int __poll_portal_fast(struct qman_portal *p,
        do {
                qm_dqrr_pvb_update(&p->p);
                dq = qm_dqrr_current(&p->p);
-               if (!dq)
+               if (unlikely(!dq))
                        break;
 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
        /* If running on an LE system the fields of the
@@ -1090,27 +1145,27 @@ void qman_start_dequeues(void)
                qm_dqrr_set_maxfill(&p->p, DQRR_MAXFILL);
 }
 
-void qman_static_dequeue_add(u32 pools)
+void qman_static_dequeue_add(u32 pools, struct qman_portal *qp)
 {
-       struct qman_portal *p = get_affine_portal();
+       struct qman_portal *p = qp ? qp : get_affine_portal();
 
        pools &= p->config->pools;
        p->sdqcr |= pools;
        qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
 }
 
-void qman_static_dequeue_del(u32 pools)
+void qman_static_dequeue_del(u32 pools, struct qman_portal *qp)
 {
-       struct qman_portal *p = get_affine_portal();
+       struct qman_portal *p = qp ? qp : get_affine_portal();
 
        pools &= p->config->pools;
        p->sdqcr &= ~pools;
        qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
 }
 
-u32 qman_static_dequeue_get(void)
+u32 qman_static_dequeue_get(struct qman_portal *qp)
 {
-       struct qman_portal *p = get_affine_portal();
+       struct qman_portal *p = qp ? qp : get_affine_portal();
        return p->sdqcr;
 }
 
@@ -1159,6 +1214,7 @@ int qman_create_fq(u32 fqid, u32 flags, struct qman_fq *fq)
        }
        spin_lock_init(&fq->fqlock);
        fq->fqid = fqid;
+       fq->fqid_le = cpu_to_be32(fqid);
        fq->flags = flags;
        fq->state = qman_fq_state_oos;
        fq->cgr_groupid = 0;
@@ -1947,7 +2003,7 @@ int qman_enqueue(struct qman_fq *fq, const struct qm_fd *fd, u32 flags)
 
 int qman_enqueue_multi(struct qman_fq *fq,
                       const struct qm_fd *fd,
-               int frames_to_send)
+                      int frames_to_send)
 {
        struct qman_portal *p = get_affine_portal();
        struct qm_portal *portal = &p->p;
@@ -1969,7 +2025,7 @@ int qman_enqueue_multi(struct qman_fq *fq,
 
        /* try to send as many frames as possible */
        while (eqcr->available && frames_to_send--) {
-               eq->fqid = cpu_to_be32(fq->fqid);
+               eq->fqid = fq->fqid_le;
 #ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
                eq->tag = cpu_to_be32(fq->key);
 #else