summaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_classifier.c23
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_classifier.h9
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts2
-rw-r--r--drivers/staging/fsl_qbman/fsl_usdpaa.c15
-rw-r--r--drivers/staging/fsl_qbman/qman_high.c34
-rw-r--r--drivers/staging/fsl_qbman/qman_low.h40
6 files changed, 102 insertions, 21 deletions
diff --git a/drivers/staging/fsl_dpa_offload/dpa_classifier.c b/drivers/staging/fsl_dpa_offload/dpa_classifier.c
index a39fc69..5056b2e 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_classifier.c
+++ b/drivers/staging/fsl_dpa_offload/dpa_classifier.c
@@ -462,6 +462,9 @@ int dpa_classif_table_modify_miss_action(int td,
return -EBUSY;
}
}
+
+ memcpy(&ptable->miss_action, miss_action, sizeof(*miss_action));
+
RELEASE_OBJECT(ptable);
dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
@@ -3230,6 +3233,26 @@ static inline void key_apply_mask(const struct dpa_offload_lookup_key *key,
new_key[i] = key->byte[i] & key->mask[i];
}
+int dpa_classif_get_miss_action(int td, struct dpa_cls_tbl_action *miss_action)
+{
+ struct dpa_cls_table *ptable;
+
+ if (!miss_action)
+ return -EINVAL;
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+ if (ptable->miss_action.type == DPA_CLS_TBL_ACTION_NONE) {
+ /* No miss action was specified for this table */
+ RELEASE_OBJECT(ptable);
+ return -ENODEV;
+ } else
+ memcpy(miss_action, &ptable->miss_action, sizeof(*miss_action));
+
+ RELEASE_OBJECT(ptable);
+
+ return 0;
+}
+
static int nat_hm_check_params(const struct dpa_cls_hm_nat_params *nat_params)
{
unsigned int ip_ver = 0;
diff --git a/drivers/staging/fsl_dpa_offload/dpa_classifier.h b/drivers/staging/fsl_dpa_offload/dpa_classifier.h
index 0667782..659e1b7 100644
--- a/drivers/staging/fsl_dpa_offload/dpa_classifier.h
+++ b/drivers/staging/fsl_dpa_offload/dpa_classifier.h
@@ -206,6 +206,9 @@ struct dpa_cls_table {
/* (Initial) parameters of the DPA Classifier table. */
struct dpa_cls_tbl_params params;
+ /* Table miss action. */
+ struct dpa_cls_tbl_action miss_action;
+
/* Access control object for this table to avoid race conditions. */
struct mutex access;
};
@@ -675,6 +678,12 @@ int dpa_classif_import_static_hm(void *hm, int next_hmd, int *hmd);
void *dpa_classif_get_static_hm_handle(int hmd);
/*
+ * Provides details about the miss action configured on a classification
+ * table.
+ */
+int dpa_classif_get_miss_action(int td, struct dpa_cls_tbl_action *miss_action);
+
+/*
* Locks a header manipulation chain (marks as "used"). The header manipulation
* operations cannot be removed as long as they are locked. The function
* provides the FMan driver handle of the manip node which is chain head.
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts
index 537d3f2..7baa9b1 100644
--- a/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts
+++ b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts
@@ -149,7 +149,7 @@
/* Define frame queues for the OH port*/
/* <OH Rx error, OH Rx default> */
fsl,qman-frame-queues-oh = <0x6e 1 0x6f 1>;
- fsl,bman-buffer-pools = <&bp9>;
+ fsl,bman-buffer-pools = <&bp16>;
fsl,fman-oh-port = <&fman0_oh2>;
};
dpa_fman0_oh3: dpa-fman0-oh@3 {
diff --git a/drivers/staging/fsl_qbman/fsl_usdpaa.c b/drivers/staging/fsl_qbman/fsl_usdpaa.c
index 5d0eb4c..633a1a9 100644
--- a/drivers/staging/fsl_qbman/fsl_usdpaa.c
+++ b/drivers/staging/fsl_qbman/fsl_usdpaa.c
@@ -349,7 +349,8 @@ static int init_qm_portal(struct qm_portal_config *config,
}
/* Initialize the EQCR */
- if (qm_eqcr_init(portal, qm_eqcr_pvb, qm_eqcr_cce)) {
+ if (qm_eqcr_init(portal, qm_eqcr_pvb,
+ portal->eqcr.use_eqcr_ci_stashing ? 3 : 0, 1)) {
pr_err("Qman EQCR initialisation failed\n");
return 1;
}
@@ -486,6 +487,18 @@ __maybe_unused static void dump_frags(void)
}
+__maybe_unused static void dump_frags(void)
+{
+ struct mem_fragment *frag;
+ int i = 0;
+ list_for_each_entry(frag, &mem_list, list) {
+ pr_info("FRAG %d: base 0x%llx len 0x%llx root_len 0x%llx\n",
+ i, frag->base, frag->len, frag->root_len);
+ ++i;
+ }
+}
+
+
static int usdpaa_release(struct inode *inode, struct file *filp)
{
struct ctx *ctx = filp->private_data;
diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c
index e5e52b7..c8451f1 100644
--- a/drivers/staging/fsl_qbman/qman_high.c
+++ b/drivers/staging/fsl_qbman/qman_high.c
@@ -361,9 +361,6 @@ loop:
goto loop;
}
-
-
-
struct qman_portal *qman_create_portal(
struct qman_portal *portal,
const struct qm_portal_config *config,
@@ -382,12 +379,20 @@ struct qman_portal *qman_create_portal(
__p = &portal->p;
+ portal->p.eqcr.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
* for (de)reference... */
__p->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE];
__p->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI];
- if (qm_eqcr_init(__p, qm_eqcr_pvb, qm_eqcr_cce)) {
+ /*
+ * If CI-stashing is used, the current defaults use a threshold of 3,
+ * and stash with high-than-DQRR priority.
+ */
+ if (qm_eqcr_init(__p, qm_eqcr_pvb,
+ portal->p.eqcr.use_eqcr_ci_stashing ? 3 : 0, 1)) {
pr_err("Qman EQCR initialisation failed\n");
goto fail_eqcr;
}
@@ -1986,10 +1991,23 @@ static inline struct qm_eqcr_entry *try_eq_start(struct qman_portal **p,
(*p)->eqci_owned = fq;
}
#endif
- avail = qm_eqcr_get_avail(&(*p)->p);
- if (avail < 2)
- update_eqcr_ci(*p, avail);
- eq = qm_eqcr_start(&(*p)->p);
+ if ((*p)->p.eqcr.use_eqcr_ci_stashing) {
+ /*
+ * The stashing case is easy, only update if we need to in
+ * order to try and liberate ring entries.
+ */
+ eq = qm_eqcr_start_stash(&(*p)->p);
+ } else {
+ /*
+ * The non-stashing case is harder, need to prefetch ahead of
+ * time.
+ */
+ avail = qm_eqcr_get_avail(&(*p)->p);
+ if (avail < 2)
+ update_eqcr_ci(*p, avail);
+ eq = qm_eqcr_start_no_stash(&(*p)->p);
+ }
+
if (unlikely(!eq)) {
#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) &&
diff --git a/drivers/staging/fsl_qbman/qman_low.h b/drivers/staging/fsl_qbman/qman_low.h
index d63c722..0b5f16c 100644
--- a/drivers/staging/fsl_qbman/qman_low.h
+++ b/drivers/staging/fsl_qbman/qman_low.h
@@ -131,10 +131,6 @@ enum qm_eqcr_pmode { /* matches QCSP_CFG::EPM */
qm_eqcr_pce = 1, /* PI index, cache-enabled */
qm_eqcr_pvb = 2 /* valid-bit */
};
-enum qm_eqcr_cmode { /* s/w-only */
- qm_eqcr_cci, /* CI index, cache-inhibited */
- qm_eqcr_cce /* CI index, cache-enabled */
-};
enum qm_dqrr_dmode { /* matches QCSP_CFG::DP */
qm_dqrr_dpush = 0, /* SDQCR + VDQCR */
qm_dqrr_dpull = 1 /* PDQCR */
@@ -170,10 +166,10 @@ enum qm_mr_cmode { /* matches QCSP_CFG::MM */
struct qm_eqcr {
struct qm_eqcr_entry *ring, *cursor;
u8 ci, available, ithresh, vbit;
+ u32 use_eqcr_ci_stashing;
#ifdef CONFIG_FSL_DPA_CHECKING
u32 busy;
enum qm_eqcr_pmode pmode;
- enum qm_eqcr_cmode cmode;
#endif
};
@@ -283,7 +279,8 @@ static inline void EQCR_INC(struct qm_eqcr *eqcr)
static inline int qm_eqcr_init(struct qm_portal *portal,
enum qm_eqcr_pmode pmode,
- __maybe_unused enum qm_eqcr_cmode cmode)
+ unsigned int eq_stash_thresh,
+ int eq_stash_prio)
{
/* This use of 'register', as well as all other occurances, is because
* it has been observed to generate much faster code with gcc than is
@@ -305,9 +302,10 @@ static inline int qm_eqcr_init(struct qm_portal *portal,
#ifdef CONFIG_FSL_DPA_CHECKING
eqcr->busy = 0;
eqcr->pmode = pmode;
- eqcr->cmode = cmode;
#endif
cfg = (qm_in(CFG) & 0x00ffffff) |
+ (eq_stash_thresh << 28) | /* QCSP_CFG: EST */
+ (eq_stash_prio << 26) | /* QCSP_CFG: EP */
((pmode & 0x3) << 24); /* QCSP_CFG::EPM */
qm_out(CFG, cfg);
return 0;
@@ -328,7 +326,8 @@ static inline void qm_eqcr_finish(struct qm_portal *portal)
pr_crit("EQCR destroyed unquiesced\n");
}
-static inline struct qm_eqcr_entry *qm_eqcr_start(struct qm_portal *portal)
+static inline struct qm_eqcr_entry *qm_eqcr_start_no_stash(struct qm_portal
+ *portal)
{
register struct qm_eqcr *eqcr = &portal->eqcr;
DPA_ASSERT(!eqcr->busy);
@@ -343,6 +342,28 @@ static inline struct qm_eqcr_entry *qm_eqcr_start(struct qm_portal *portal)
return eqcr->cursor;
}
+static inline struct qm_eqcr_entry *qm_eqcr_start_stash(struct qm_portal
+ *portal)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ u8 diff, old_ci;
+
+ DPA_ASSERT(!eqcr->busy);
+ if (!eqcr->available) {
+ old_ci = eqcr->ci;
+ eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1);
+ diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci);
+ eqcr->available += diff;
+ if (!diff)
+ return NULL;
+ }
+#ifdef CONFIG_FSL_DPA_CHECKING
+ eqcr->busy = 1;
+#endif
+ dcbz_64(eqcr->cursor);
+ return eqcr->cursor;
+}
+
static inline void qm_eqcr_abort(struct qm_portal *portal)
{
__maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr;
@@ -436,7 +457,6 @@ static inline u8 qm_eqcr_cci_update(struct qm_portal *portal)
{
register struct qm_eqcr *eqcr = &portal->eqcr;
u8 diff, old_ci = eqcr->ci;
- DPA_ASSERT(eqcr->cmode == qm_eqcr_cci);
eqcr->ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1);
diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci);
eqcr->available += diff;
@@ -446,7 +466,6 @@ static inline u8 qm_eqcr_cci_update(struct qm_portal *portal)
static inline void qm_eqcr_cce_prefetch(struct qm_portal *portal)
{
__maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr;
- DPA_ASSERT(eqcr->cmode == qm_eqcr_cce);
qm_cl_touch_ro(EQCR_CI);
}
@@ -454,7 +473,6 @@ static inline u8 qm_eqcr_cce_update(struct qm_portal *portal)
{
register struct qm_eqcr *eqcr = &portal->eqcr;
u8 diff, old_ci = eqcr->ci;
- DPA_ASSERT(eqcr->cmode == qm_eqcr_cce);
eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1);
qm_cl_invalidate(EQCR_CI);
diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci);