diff options
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/fsl_dpa_offload/dpa_classifier.c | 23 | ||||
-rw-r--r-- | drivers/staging/fsl_dpa_offload/dpa_classifier.h | 9 | ||||
-rw-r--r-- | drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts | 2 | ||||
-rw-r--r-- | drivers/staging/fsl_qbman/fsl_usdpaa.c | 15 | ||||
-rw-r--r-- | drivers/staging/fsl_qbman/qman_high.c | 34 | ||||
-rw-r--r-- | drivers/staging/fsl_qbman/qman_low.h | 40 |
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); |