drm/edid/firmware: Add built-in edid/1280x720.bin firmware
[platform/kernel/linux-starfive.git] / kernel / workqueue.c
index 7cd5f5e..4dd494f 100644 (file)
@@ -326,7 +326,7 @@ static struct rcuwait manager_wait = __RCUWAIT_INITIALIZER(manager_wait);
 static LIST_HEAD(workqueues);          /* PR: list of all workqueues */
 static bool workqueue_freezing;                /* PL: have wqs started freezing? */
 
-/* PL: allowable cpus for unbound wqs and work items */
+/* PL&A: allowable cpus for unbound wqs and work items */
 static cpumask_var_t wq_unbound_cpumask;
 
 /* CPU where unbound work was last round robin scheduled from this CPU */
@@ -3952,7 +3952,8 @@ static void apply_wqattrs_cleanup(struct apply_wqattrs_ctx *ctx)
 /* allocate the attrs and pwqs for later installation */
 static struct apply_wqattrs_ctx *
 apply_wqattrs_prepare(struct workqueue_struct *wq,
-                     const struct workqueue_attrs *attrs)
+                     const struct workqueue_attrs *attrs,
+                     const cpumask_var_t unbound_cpumask)
 {
        struct apply_wqattrs_ctx *ctx;
        struct workqueue_attrs *new_attrs, *tmp_attrs;
@@ -3968,14 +3969,15 @@ apply_wqattrs_prepare(struct workqueue_struct *wq,
                goto out_free;
 
        /*
-        * Calculate the attrs of the default pwq.
+        * Calculate the attrs of the default pwq with unbound_cpumask
+        * which is wq_unbound_cpumask or to set to wq_unbound_cpumask.
         * If the user configured cpumask doesn't overlap with the
         * wq_unbound_cpumask, we fallback to the wq_unbound_cpumask.
         */
        copy_workqueue_attrs(new_attrs, attrs);
-       cpumask_and(new_attrs->cpumask, new_attrs->cpumask, wq_unbound_cpumask);
+       cpumask_and(new_attrs->cpumask, new_attrs->cpumask, unbound_cpumask);
        if (unlikely(cpumask_empty(new_attrs->cpumask)))
-               cpumask_copy(new_attrs->cpumask, wq_unbound_cpumask);
+               cpumask_copy(new_attrs->cpumask, unbound_cpumask);
 
        /*
         * We may create multiple pwqs with differing cpumasks.  Make a
@@ -4072,7 +4074,7 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq,
                wq->flags &= ~__WQ_ORDERED;
        }
 
-       ctx = apply_wqattrs_prepare(wq, attrs);
+       ctx = apply_wqattrs_prepare(wq, attrs, wq_unbound_cpumask);
        if (!ctx)
                return -ENOMEM;
 
@@ -4848,10 +4850,16 @@ static void show_one_worker_pool(struct worker_pool *pool)
        struct worker *worker;
        bool first = true;
        unsigned long flags;
+       unsigned long hung = 0;
 
        raw_spin_lock_irqsave(&pool->lock, flags);
        if (pool->nr_workers == pool->nr_idle)
                goto next_pool;
+
+       /* How long the first pending work is waiting for a worker. */
+       if (!list_empty(&pool->worklist))
+               hung = jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000;
+
        /*
         * Defer printing to avoid deadlocks in console drivers that
         * queue work while holding locks also taken in their write
@@ -4860,9 +4868,7 @@ static void show_one_worker_pool(struct worker_pool *pool)
        printk_deferred_enter();
        pr_info("pool %d:", pool->id);
        pr_cont_pool_info(pool);
-       pr_cont(" hung=%us workers=%d",
-               jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,
-               pool->nr_workers);
+       pr_cont(" hung=%lus workers=%d", hung, pool->nr_workers);
        if (pool->manager)
                pr_cont(" manager: %d",
                        task_pid_nr(pool->manager->task));
@@ -5334,7 +5340,7 @@ out_unlock:
 }
 #endif /* CONFIG_FREEZER */
 
-static int workqueue_apply_unbound_cpumask(void)
+static int workqueue_apply_unbound_cpumask(const cpumask_var_t unbound_cpumask)
 {
        LIST_HEAD(ctxs);
        int ret = 0;
@@ -5350,7 +5356,7 @@ static int workqueue_apply_unbound_cpumask(void)
                if (wq->flags & __WQ_ORDERED)
                        continue;
 
-               ctx = apply_wqattrs_prepare(wq, wq->unbound_attrs);
+               ctx = apply_wqattrs_prepare(wq, wq->unbound_attrs, unbound_cpumask);
                if (!ctx) {
                        ret = -ENOMEM;
                        break;
@@ -5365,6 +5371,11 @@ static int workqueue_apply_unbound_cpumask(void)
                apply_wqattrs_cleanup(ctx);
        }
 
+       if (!ret) {
+               mutex_lock(&wq_pool_attach_mutex);
+               cpumask_copy(wq_unbound_cpumask, unbound_cpumask);
+               mutex_unlock(&wq_pool_attach_mutex);
+       }
        return ret;
 }
 
@@ -5383,7 +5394,6 @@ static int workqueue_apply_unbound_cpumask(void)
 int workqueue_set_unbound_cpumask(cpumask_var_t cpumask)
 {
        int ret = -EINVAL;
-       cpumask_var_t saved_cpumask;
 
        /*
         * Not excluding isolated cpus on purpose.
@@ -5397,23 +5407,8 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask)
                        goto out_unlock;
                }
 
-               if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL)) {
-                       ret = -ENOMEM;
-                       goto out_unlock;
-               }
-
-               /* save the old wq_unbound_cpumask. */
-               cpumask_copy(saved_cpumask, wq_unbound_cpumask);
-
-               /* update wq_unbound_cpumask at first and apply it to wqs. */
-               cpumask_copy(wq_unbound_cpumask, cpumask);
-               ret = workqueue_apply_unbound_cpumask();
-
-               /* restore the wq_unbound_cpumask when failed. */
-               if (ret < 0)
-                       cpumask_copy(wq_unbound_cpumask, saved_cpumask);
+               ret = workqueue_apply_unbound_cpumask(cpumask);
 
-               free_cpumask_var(saved_cpumask);
 out_unlock:
                apply_wqattrs_unlock();
        }