diff options
author | Haiying Wang <Haiying.Wang@freescale.com> | 2013-03-11 20:43:14 (GMT) |
---|---|---|
committer | Fleming Andrew-AFLEMING <AFLEMING@freescale.com> | 2013-04-16 16:17:04 (GMT) |
commit | a513177be99be3d96b8eade6f26f3f0f589afb75 (patch) | |
tree | 05ccd4e63e64c1814de7307a87135cf910bd4412 | |
parent | cf620d252d9e85e6012dcd35ce7a38f73d903661 (diff) | |
download | linux-fsl-qoriq-a513177be99be3d96b8eade6f26f3f0f589afb75.tar.xz |
fsl_qman: use a single CGR list per-portal, not 256
CGR objects registered against a portal can receive CSCN notifications
via that portal, and this supports the existence of there being more than
one CGR object for the same CGRID (eg. two distinct drivers using the
same portal and using FQs that are subscribed to the same CGR). The
portal code was previously using a distinct list of registered CGRs for
every possible CGRID, ie. a 256-element array of lists! This meant that
when CSCN interrupts occurred and a 256-bit mask was calculated
indicating which CGRIDs had changed state, we would iterate that bitmask
and for each CGRID that had changed, we would iterate the corresponding
list from the array, invoking callbacks for all CGR objects.
Now, we just use a singe list for all CGRs, irrespective of CGRID. Rather
than iterating the bitmask by CGRID and, for each CGRID that had a
state-change, iterating the corresponding CGR list to invoke callbacks,
we now just iterate the single CGR list and for each CGR with a callback,
we check the bit in the bitmask corresponding to the CGRID to determine
whether to invoke the callback.
This is a more efficient use of memory (the 256-element array of lists
used 2KB per portal on 32-bit cores, 4KB on 64-bit), and the code becomes
simpler. And the "downside" doesn't occur, because there are never more
than a small handful of CGR objects per portal at most, and quite often
only one or two (or even none). So a single list is probably as efficient
or even better in the conventional use cases, and much less wasteful of
space.
Furthermore, this logic will be extended for CEETM CCGRs, of which there
are many more than for regular CGRs. So without this change, the
extensions for CEETM would continue the previous bad approach, but with 2
or 4 times the unwelcome footprint.
Signed-off-by: Geoff Thorpe <Geoff.Thorpe@freescale.com>
Change-Id: I00ff60edf191aabc9105c0b49e7437fad085f7dc
Reviewed-on: http://git.am.freescale.net:8181/1258
Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
-rw-r--r-- | drivers/staging/fsl_qbman/qman_high.c | 38 | ||||
-rw-r--r-- | drivers/staging/fsl_qbman/qman_private.h | 4 |
2 files changed, 19 insertions, 23 deletions
diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c index 04290a2..50d0008 100644 --- a/drivers/staging/fsl_qbman/qman_high.c +++ b/drivers/staging/fsl_qbman/qman_high.c @@ -99,8 +99,8 @@ struct qman_portal { char irqname[MAX_IRQNAME]; /* 2-element array. cgrs[0] is mask, cgrs[1] is snapshot. */ struct qman_cgrs *cgrs; - /* 256-element array, each is a linked-list of CSCN handlers. */ - struct list_head cgr_cbs[256]; + /* linked-list of CSCN handlers. */ + struct list_head cgr_cbs; /* list lock */ spinlock_t cgr_lock; }; @@ -390,8 +390,7 @@ struct qman_portal *qman_create_affine_portal( else /* if the given mask is NULL, assume all CGRs can be seen */ qman_cgrs_fill(&portal->cgrs[0]); - for (ret = 0; ret < __CGR_NUM; ret++) - INIT_LIST_HEAD(&portal->cgr_cbs[ret]); + INIT_LIST_HEAD(&portal->cgr_cbs); spin_lock_init(&portal->cgr_lock); portal->bits = 0; portal->slowpoll = 0; @@ -605,7 +604,6 @@ static u32 __poll_portal_slow(struct qman_portal *p, u32 is) struct qman_cgrs rr, c; struct qm_mc_result *mcr; struct qman_cgr *cgr; - int i; unsigned long irqflags __maybe_unused; spin_lock_irqsave(&p->cgr_lock, irqflags); @@ -627,11 +625,9 @@ static u32 __poll_portal_slow(struct qman_portal *p, u32 is) /* update snapshot */ qman_cgrs_cp(&p->cgrs[1], &rr); /* Invoke callback */ - qman_cgrs_for_each_1(i, &c) - list_for_each_entry(cgr, &p->cgr_cbs[i], node) { - if (cgr->cb) - cgr->cb(p, cgr, qman_cgrs_get(&rr, i)); - } + list_for_each_entry(cgr, &p->cgr_cbs, node) + if (cgr->cb && qman_cgrs_get(&c, cgr->cgrid)) + cgr->cb(p, cgr, qman_cgrs_get(&rr, cgr->cgrid)); spin_unlock_irqrestore(&p->cgr_lock, irqflags); } @@ -2063,9 +2059,8 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, cgr->chan = p->config->public_cfg.channel; spin_lock_irqsave(&p->cgr_lock, irqflags); - /* if no opts specified and I'm not the first for this portal, just add - * to the list */ - if ((opts == NULL) && !list_empty(&p->cgr_cbs[cgr->cgrid])) + /* if no opts specified, just add it to the list */ + if (!opts) goto add_list; ret = qman_query_cgr(cgr, &cgr_state); @@ -2090,7 +2085,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, if (ret) goto release_lock; add_list: - list_add(&cgr->node, &p->cgr_cbs[cgr->cgrid]); + list_add(&cgr->node, &p->cgr_cbs); /* Determine if newly added object requires its callback to be called */ ret = qman_query_cgr(cgr, &cgr_state); @@ -2156,6 +2151,7 @@ int qman_delete_cgr(struct qman_cgr *cgr) struct qm_mcr_querycgr cgr_state; struct qm_mcc_initcgr local_opts; int ret = 0; + struct qman_cgr *i; struct qman_portal *p = get_affine_portal(); if (cgr->chan != p->config->public_cfg.channel) { @@ -2168,13 +2164,17 @@ int qman_delete_cgr(struct qman_cgr *cgr) memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); spin_lock_irqsave(&p->cgr_lock, irqflags); list_del(&cgr->node); - /* If last in list, CSCN_TARG must be set accordingly */ - if (!list_empty(&p->cgr_cbs[cgr->cgrid])) - goto release_lock; + /* + * If there are no other CGR objects for this CGRID in the list, update + * CSCN_TARG accordingly + */ + list_for_each_entry(i, &p->cgr_cbs, node) + if ((i->cgrid == cgr->cgrid) && i->cb) + goto release_lock; ret = qman_query_cgr(cgr, &cgr_state); if (ret) { /* add back to the list */ - list_add(&cgr->node, &p->cgr_cbs[cgr->cgrid]); + list_add(&cgr->node, &p->cgr_cbs); goto release_lock; } /* Overwrite TARG */ @@ -2188,7 +2188,7 @@ int qman_delete_cgr(struct qman_cgr *cgr) ret = qman_modify_cgr(cgr, 0, &local_opts); if (ret) /* add back to the list */ - list_add(&cgr->node, &p->cgr_cbs[cgr->cgrid]); + list_add(&cgr->node, &p->cgr_cbs); release_lock: spin_unlock_irqrestore(&p->cgr_lock, irqflags); put_portal: diff --git a/drivers/staging/fsl_qbman/qman_private.h b/drivers/staging/fsl_qbman/qman_private.h index cea96d6..5945b34 100644 --- a/drivers/staging/fsl_qbman/qman_private.h +++ b/drivers/staging/fsl_qbman/qman_private.h @@ -98,10 +98,6 @@ static inline void qman_cgrs_xor(struct qman_cgrs *dest, *(_d++) = *(_a++) ^ *(_b++); } -#define qman_cgrs_for_each_1(cgr, cgrs) \ - for ((cgr) = -1; (cgr) = qman_cgrs_next((cgrs), (cgr)),\ - (cgr) < __CGR_NUM;) - /* used by CCSR and portal interrupt code */ enum qm_isr_reg { qm_isr_status = 0, |