summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/fsl_qbman/qman_high.c46
-rw-r--r--include/linux/fsl_qman.h8
2 files changed, 54 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) {
diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h
index 3b594cc..95fdd38 100644
--- a/include/linux/fsl_qman.h
+++ b/include/linux/fsl_qman.h
@@ -2220,6 +2220,14 @@ int qman_create_cgr_to_dcp(struct qman_cgr *cgr, u32 flags, u16 dcp_portal,
int qman_delete_cgr(struct qman_cgr *cgr);
/**
+ * qman_delete_cgr_safe - Deregisters a congestion group object from any CPU
+ * @cgr: the 'cgr' object to deregister
+ *
+ * This will select the proper CPU and run there qman_delete_cgr().
+ */
+void qman_delete_cgr_safe(struct qman_cgr *cgr);
+
+/**
* qman_modify_cgr - Modify CGR fields
* @cgr: the 'cgr' object to modify
* @flags: QMAN_CGR_FLAG_* values