diff options
author | Madalin Bucur <madalin.bucur@freescale.com> | 2015-01-15 10:32:38 (GMT) |
---|---|---|
committer | Madalin Bucur <madalin.bucur@freescale.com> | 2015-02-25 16:27:05 (GMT) |
commit | 350e0ecf99128144bd11c48fc2267007371701f1 (patch) | |
tree | ef2e7f8951be05a6f38594a543daaf344caea33f /drivers/staging | |
parent | 7bc67b0e3d1346d641aa5ff36540cce264d10265 (diff) | |
download | linux-fsl-qoriq-350e0ecf99128144bd11c48fc2267007371701f1.tar.xz |
fsl_qman: add qman_delete_cgr_safe()
Add qman_delete_cgr_safe() that can be called from any CPU.
This in turn schedules qman_delete_cgr() on the proper CPU.
Signed-off-by: Madalin Bucur <madalin.bucur@freescale.com>
Change-Id: I762e83108533a4e537a534e90073df26a6b7b09c
Reviewed-on: http://git.am.freescale.net:8181/28532
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Marian Cristian Rotariu <marian.rotariu@freescale.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/fsl_qbman/qman_high.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c index 374ebf6..c3a341c 100644 --- a/drivers/staging/fsl_qbman/qman_high.c +++ b/drivers/staging/fsl_qbman/qman_high.c @@ -2556,6 +2556,8 @@ EXPORT_SYMBOL(qman_modify_cgr); QM_CHANNEL_SWPORTAL0)) #define PORTAL_IDX(n) (n->config->public_cfg.channel - QM_CHANNEL_SWPORTAL0) +static u8 qman_cgr_cpus[__CGR_NUM]; + int qman_create_cgr(struct qman_cgr *cgr, u32 flags, struct qm_mcc_initcgr *opts) { @@ -2572,7 +2574,10 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, if (cgr->cgrid >= __CGR_NUM) return -EINVAL; + preempt_disable(); p = get_affine_portal(); + qman_cgr_cpus[cgr->cgrid] = smp_processor_id(); + preempt_enable(); memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); cgr->chan = p->config->public_cfg.channel; @@ -2715,6 +2720,47 @@ put_portal: } EXPORT_SYMBOL(qman_delete_cgr); +struct cgr_comp { + struct qman_cgr *cgr; + struct completion completion; +}; + +static int qman_delete_cgr_thread(void *p) +{ + struct cgr_comp *cgr_comp = (struct cgr_comp *)p; + int res; + + res = qman_delete_cgr((struct qman_cgr *)cgr_comp->cgr); + complete(&cgr_comp->completion); + + return res; +} + +void qman_delete_cgr_safe(struct qman_cgr *cgr) +{ + struct task_struct *thread; + struct cgr_comp cgr_comp; + + preempt_disable(); + if (qman_cgr_cpus[cgr->cgrid] != smp_processor_id()) { + init_completion(&cgr_comp.completion); + cgr_comp.cgr = cgr; + thread = kthread_create(qman_delete_cgr_thread, &cgr_comp, + "cgr_del"); + + if (likely(!IS_ERR(thread))) { + kthread_bind(thread, qman_cgr_cpus[cgr->cgrid]); + wake_up_process(thread); + wait_for_completion(&cgr_comp.completion); + preempt_enable(); + return; + } + } + qman_delete_cgr(cgr); + preempt_enable(); +} +EXPORT_SYMBOL(qman_delete_cgr_safe); + int qm_get_clock(u64 *clock_hz) { if (!qman_clk) { |