]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Mar 2020 11:01:07 +0000 (12:01 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Mar 2020 11:01:07 +0000 (12:01 +0100)
added patches:
cgroup-cgroup_procs_next-should-increase-position-index.patch
cgroup-iterate-tasks-that-did-not-finish-do_exit.patch
drm-amd-display-remove-duplicated-assignment-to-grph_obj_type.patch
iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint.patch
iwlwifi-mvm-do-not-require-phy_sku-nvm-section-for-3168-devices.patch
virtio-blk-fix-hw_queue-stopped-on-arbitrary-error.patch
workqueue-don-t-use-wq_select_unbound_cpu-for-bound-works.patch

queue-4.14/cgroup-cgroup_procs_next-should-increase-position-index.patch [new file with mode: 0644]
queue-4.14/cgroup-iterate-tasks-that-did-not-finish-do_exit.patch [new file with mode: 0644]
queue-4.14/drm-amd-display-remove-duplicated-assignment-to-grph_obj_type.patch [new file with mode: 0644]
queue-4.14/iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint.patch [new file with mode: 0644]
queue-4.14/iwlwifi-mvm-do-not-require-phy_sku-nvm-section-for-3168-devices.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/virtio-blk-fix-hw_queue-stopped-on-arbitrary-error.patch [new file with mode: 0644]
queue-4.14/workqueue-don-t-use-wq_select_unbound_cpu-for-bound-works.patch [new file with mode: 0644]

diff --git a/queue-4.14/cgroup-cgroup_procs_next-should-increase-position-index.patch b/queue-4.14/cgroup-cgroup_procs_next-should-increase-position-index.patch
new file mode 100644 (file)
index 0000000..9c9e640
--- /dev/null
@@ -0,0 +1,85 @@
+From 2d4ecb030dcc90fb725ecbfc82ce5d6c37906e0e Mon Sep 17 00:00:00 2001
+From: Vasily Averin <vvs@virtuozzo.com>
+Date: Thu, 30 Jan 2020 13:34:59 +0300
+Subject: cgroup: cgroup_procs_next should increase position index
+
+From: Vasily Averin <vvs@virtuozzo.com>
+
+commit 2d4ecb030dcc90fb725ecbfc82ce5d6c37906e0e upstream.
+
+If seq_file .next fuction does not change position index,
+read after some lseek can generate unexpected output:
+
+1) dd bs=1 skip output of each 2nd elements
+$ dd if=/sys/fs/cgroup/cgroup.procs bs=8 count=1
+2
+3
+4
+5
+1+0 records in
+1+0 records out
+8 bytes copied, 0,000267297 s, 29,9 kB/s
+[test@localhost ~]$ dd if=/sys/fs/cgroup/cgroup.procs bs=1 count=8
+2
+4 <<< NB! 3 was skipped
+6 <<<    ... and 5 too
+8 <<<    ... and 7
+8+0 records in
+8+0 records out
+8 bytes copied, 5,2123e-05 s, 153 kB/s
+
+ This happen because __cgroup_procs_start() makes an extra
+ extra cgroup_procs_next() call
+
+2) read after lseek beyond end of file generates whole last line.
+3) read after lseek into middle of last line generates
+expected rest of last line and unexpected whole line once again.
+
+Additionally patch removes an extra position index changes in
+__cgroup_procs_start()
+
+Cc: stable@vger.kernel.org
+https://bugzilla.kernel.org/show_bug.cgi?id=206283
+Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/cgroup/cgroup.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/kernel/cgroup/cgroup.c
++++ b/kernel/cgroup/cgroup.c
+@@ -4249,6 +4249,9 @@ static void *cgroup_procs_next(struct se
+       struct kernfs_open_file *of = s->private;
+       struct css_task_iter *it = of->priv;
++      if (pos)
++              (*pos)++;
++
+       return css_task_iter_next(it);
+ }
+@@ -4264,7 +4267,7 @@ static void *__cgroup_procs_start(struct
+        * from position 0, so we can simply keep iterating on !0 *pos.
+        */
+       if (!it) {
+-              if (WARN_ON_ONCE((*pos)++))
++              if (WARN_ON_ONCE((*pos)))
+                       return ERR_PTR(-EINVAL);
+               it = kzalloc(sizeof(*it), GFP_KERNEL);
+@@ -4272,10 +4275,11 @@ static void *__cgroup_procs_start(struct
+                       return ERR_PTR(-ENOMEM);
+               of->priv = it;
+               css_task_iter_start(&cgrp->self, iter_flags, it);
+-      } else if (!(*pos)++) {
++      } else if (!(*pos)) {
+               css_task_iter_end(it);
+               css_task_iter_start(&cgrp->self, iter_flags, it);
+-      }
++      } else
++              return it->cur_task;
+       return cgroup_procs_next(s, NULL, NULL);
+ }
diff --git a/queue-4.14/cgroup-iterate-tasks-that-did-not-finish-do_exit.patch b/queue-4.14/cgroup-iterate-tasks-that-did-not-finish-do_exit.patch
new file mode 100644 (file)
index 0000000..7385276
--- /dev/null
@@ -0,0 +1,100 @@
+From 9c974c77246460fa6a92c18554c3311c8c83c160 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michal=20Koutn=C3=BD?= <mkoutny@suse.com>
+Date: Fri, 24 Jan 2020 12:40:15 +0100
+Subject: cgroup: Iterate tasks that did not finish do_exit()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michal Koutný <mkoutny@suse.com>
+
+commit 9c974c77246460fa6a92c18554c3311c8c83c160 upstream.
+
+PF_EXITING is set earlier than actual removal from css_set when a task
+is exitting. This can confuse cgroup.procs readers who see no PF_EXITING
+tasks, however, rmdir is checking against css_set membership so it can
+transitionally fail with EBUSY.
+
+Fix this by listing tasks that weren't unlinked from css_set active
+lists.
+It may happen that other users of the task iterator (without
+CSS_TASK_ITER_PROCS) spot a PF_EXITING task before cgroup_exit(). This
+is equal to the state before commit c03cd7738a83 ("cgroup: Include dying
+leaders with live threads in PROCS iterations") but it may be reviewed
+later.
+
+Reported-by: Suren Baghdasaryan <surenb@google.com>
+Fixes: c03cd7738a83 ("cgroup: Include dying leaders with live threads in PROCS iterations")
+Signed-off-by: Michal Koutný <mkoutny@suse.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/cgroup.h |    1 +
+ kernel/cgroup/cgroup.c |   23 ++++++++++++++++-------
+ 2 files changed, 17 insertions(+), 7 deletions(-)
+
+--- a/include/linux/cgroup.h
++++ b/include/linux/cgroup.h
+@@ -61,6 +61,7 @@ struct css_task_iter {
+       struct list_head                *mg_tasks_head;
+       struct list_head                *dying_tasks_head;
++      struct list_head                *cur_tasks_head;
+       struct css_set                  *cur_cset;
+       struct css_set                  *cur_dcset;
+       struct task_struct              *cur_task;
+--- a/kernel/cgroup/cgroup.c
++++ b/kernel/cgroup/cgroup.c
+@@ -4051,12 +4051,16 @@ static void css_task_iter_advance_css_se
+               }
+       } while (!css_set_populated(cset) && list_empty(&cset->dying_tasks));
+-      if (!list_empty(&cset->tasks))
++      if (!list_empty(&cset->tasks)) {
+               it->task_pos = cset->tasks.next;
+-      else if (!list_empty(&cset->mg_tasks))
++              it->cur_tasks_head = &cset->tasks;
++      } else if (!list_empty(&cset->mg_tasks)) {
+               it->task_pos = cset->mg_tasks.next;
+-      else
++              it->cur_tasks_head = &cset->mg_tasks;
++      } else {
+               it->task_pos = cset->dying_tasks.next;
++              it->cur_tasks_head = &cset->dying_tasks;
++      }
+       it->tasks_head = &cset->tasks;
+       it->mg_tasks_head = &cset->mg_tasks;
+@@ -4114,10 +4118,14 @@ repeat:
+               else
+                       it->task_pos = it->task_pos->next;
+-              if (it->task_pos == it->tasks_head)
++              if (it->task_pos == it->tasks_head) {
+                       it->task_pos = it->mg_tasks_head->next;
+-              if (it->task_pos == it->mg_tasks_head)
++                      it->cur_tasks_head = it->mg_tasks_head;
++              }
++              if (it->task_pos == it->mg_tasks_head) {
+                       it->task_pos = it->dying_tasks_head->next;
++                      it->cur_tasks_head = it->dying_tasks_head;
++              }
+               if (it->task_pos == it->dying_tasks_head)
+                       css_task_iter_advance_css_set(it);
+       } else {
+@@ -4136,11 +4144,12 @@ repeat:
+                       goto repeat;
+               /* and dying leaders w/o live member threads */
+-              if (!atomic_read(&task->signal->live))
++              if (it->cur_tasks_head == it->dying_tasks_head &&
++                  !atomic_read(&task->signal->live))
+                       goto repeat;
+       } else {
+               /* skip all dying ones */
+-              if (task->flags & PF_EXITING)
++              if (it->cur_tasks_head == it->dying_tasks_head)
+                       goto repeat;
+       }
+ }
diff --git a/queue-4.14/drm-amd-display-remove-duplicated-assignment-to-grph_obj_type.patch b/queue-4.14/drm-amd-display-remove-duplicated-assignment-to-grph_obj_type.patch
new file mode 100644 (file)
index 0000000..4ecbb5f
--- /dev/null
@@ -0,0 +1,34 @@
+From d785476c608c621b345dd9396e8b21e90375cb0e Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Fri, 8 Nov 2019 14:45:27 +0000
+Subject: drm/amd/display: remove duplicated assignment to grph_obj_type
+
+From: Colin Ian King <colin.king@canonical.com>
+
+commit d785476c608c621b345dd9396e8b21e90375cb0e upstream.
+
+Variable grph_obj_type is being assigned twice, one of these is
+redundant so remove it.
+
+Addresses-Coverity: ("Evaluation order violation")
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: <nobuhiro1.iwamatsu@toshiba.co.jp>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+@@ -363,8 +363,7 @@ bool amdgpu_atombios_get_connector_info_
+                       router.ddc_valid = false;
+                       router.cd_valid = false;
+                       for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
+-                              uint8_t grph_obj_type=
+-                              grph_obj_type =
++                              uint8_t grph_obj_type =
+                                   (le16_to_cpu(path->usGraphicObjIds[j]) &
+                                    OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
diff --git a/queue-4.14/iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint.patch b/queue-4.14/iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint.patch
new file mode 100644 (file)
index 0000000..d2dac85
--- /dev/null
@@ -0,0 +1,53 @@
+From 81ee85d0462410de8eeeec1b9761941fd6ed8c7b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 9 Mar 2020 19:25:10 +0100
+Subject: iommu/vt-d: quirk_ioat_snb_local_iommu: replace WARN_TAINT with pr_warn + add_taint
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 81ee85d0462410de8eeeec1b9761941fd6ed8c7b upstream.
+
+Quoting from the comment describing the WARN functions in
+include/asm-generic/bug.h:
+
+ * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report
+ * significant kernel issues that need prompt attention if they should ever
+ * appear at runtime.
+ *
+ * Do not use these macros when checking for invalid external inputs
+
+The (buggy) firmware tables which the dmar code was calling WARN_TAINT
+for really are invalid external inputs. They are not under the kernel's
+control and the issues in them cannot be fixed by a kernel update.
+So logging a backtrace, which invites bug reports to be filed about this,
+is not helpful.
+
+Fixes: 556ab45f9a77 ("ioat2: catch and recover from broken vtd configurations v6")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Lu Baolu <baolu.lu@linux.intel.com>
+Link: https://lore.kernel.org/r/20200309182510.373875-1-hdegoede@redhat.com
+BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=701847
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/intel-iommu.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -3984,10 +3984,11 @@ static void quirk_ioat_snb_local_iommu(s
+       /* we know that the this iommu should be at offset 0xa000 from vtbar */
+       drhd = dmar_find_matched_drhd_unit(pdev);
+-      if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
+-                          TAINT_FIRMWARE_WORKAROUND,
+-                          "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
++      if (!drhd || drhd->reg_base_addr - vtbar != 0xa000) {
++              pr_warn_once(FW_BUG "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n");
++              add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
+               pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
++      }
+ }
+ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
diff --git a/queue-4.14/iwlwifi-mvm-do-not-require-phy_sku-nvm-section-for-3168-devices.patch b/queue-4.14/iwlwifi-mvm-do-not-require-phy_sku-nvm-section-for-3168-devices.patch
new file mode 100644 (file)
index 0000000..f1d8c8e
--- /dev/null
@@ -0,0 +1,41 @@
+From a9149d243f259ad8f02b1e23dfe8ba06128f15e1 Mon Sep 17 00:00:00 2001
+From: Dan Moulding <dmoulding@me.com>
+Date: Tue, 28 Jan 2020 02:31:07 -0700
+Subject: iwlwifi: mvm: Do not require PHY_SKU NVM section for 3168 devices
+
+From: Dan Moulding <dmoulding@me.com>
+
+commit a9149d243f259ad8f02b1e23dfe8ba06128f15e1 upstream.
+
+The logic for checking required NVM sections was recently fixed in
+commit b3f20e098293 ("iwlwifi: mvm: fix NVM check for 3168
+devices"). However, with that fixed the else is now taken for 3168
+devices and within the else clause there is a mandatory check for the
+PHY_SKU section. This causes the parsing to fail for 3168 devices.
+
+The PHY_SKU section is really only mandatory for the IWL_NVM_EXT
+layout (the phy_sku parameter of iwl_parse_nvm_data is only used when
+the NVM type is IWL_NVM_EXT). So this changes the PHY_SKU section
+check so that it's only mandatory for IWL_NVM_EXT.
+
+Fixes: b3f20e098293 ("iwlwifi: mvm: fix NVM check for 3168 devices")
+Signed-off-by: Dan Moulding <dmoulding@me.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/nvm.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+@@ -326,7 +326,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *m
+               }
+               /* PHY_SKU section is mandatory in B0 */
+-              if (!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
++              if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT &&
++                  !mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
+                       IWL_ERR(mvm,
+                               "Can't parse phy_sku in B0, empty sections\n");
+                       return NULL;
index cd161c22a5485487006986d5fb887da21ecfee71..d88e81b7cca9bb04df789f7665a43ee5d5f9c22b 100644 (file)
@@ -34,3 +34,10 @@ inet_diag-return-classid-for-all-socket-types.patch
 ipvlan-do-not-add-hardware-address-of-master-to-its-unicast-filter-list.patch
 ipvlan-egress-mcast-packets-are-not-exceptional.patch
 ipvlan-don-t-deref-eth-hdr-before-checking-it-s-set.patch
+cgroup-cgroup_procs_next-should-increase-position-index.patch
+cgroup-iterate-tasks-that-did-not-finish-do_exit.patch
+iwlwifi-mvm-do-not-require-phy_sku-nvm-section-for-3168-devices.patch
+virtio-blk-fix-hw_queue-stopped-on-arbitrary-error.patch
+iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint.patch
+workqueue-don-t-use-wq_select_unbound_cpu-for-bound-works.patch
+drm-amd-display-remove-duplicated-assignment-to-grph_obj_type.patch
diff --git a/queue-4.14/virtio-blk-fix-hw_queue-stopped-on-arbitrary-error.patch b/queue-4.14/virtio-blk-fix-hw_queue-stopped-on-arbitrary-error.patch
new file mode 100644 (file)
index 0000000..0ae2cbf
--- /dev/null
@@ -0,0 +1,51 @@
+From f5f6b95c72f7f8bb46eace8c5306c752d0133daa Mon Sep 17 00:00:00 2001
+From: Halil Pasic <pasic@linux.ibm.com>
+Date: Thu, 13 Feb 2020 13:37:27 +0100
+Subject: virtio-blk: fix hw_queue stopped on arbitrary error
+
+From: Halil Pasic <pasic@linux.ibm.com>
+
+commit f5f6b95c72f7f8bb46eace8c5306c752d0133daa upstream.
+
+Since nobody else is going to restart our hw_queue for us, the
+blk_mq_start_stopped_hw_queues() is in virtblk_done() is not sufficient
+necessarily sufficient to ensure that the queue will get started again.
+In case of global resource outage (-ENOMEM because mapping failure,
+because of swiotlb full) our virtqueue may be empty and we can get
+stuck with a stopped hw_queue.
+
+Let us not stop the queue on arbitrary errors, but only on -EONSPC which
+indicates a full virtqueue, where the hw_queue is guaranteed to get
+started by virtblk_done() before when it makes sense to carry on
+submitting requests. Let us also remove a stale comment.
+
+Signed-off-by: Halil Pasic <pasic@linux.ibm.com>
+Cc: Jens Axboe <axboe@kernel.dk>
+Fixes: f7728002c1c7 ("virtio_ring: fix return code on DMA mapping fails")
+Link: https://lore.kernel.org/r/20200213123728.61216-2-pasic@linux.ibm.com
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/virtio_blk.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -271,10 +271,12 @@ static blk_status_t virtio_queue_rq(stru
+               err = virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num);
+       if (err) {
+               virtqueue_kick(vblk->vqs[qid].vq);
+-              blk_mq_stop_hw_queue(hctx);
++              /* Don't stop the queue if -ENOMEM: we may have failed to
++               * bounce the buffer due to global resource outage.
++               */
++              if (err == -ENOSPC)
++                      blk_mq_stop_hw_queue(hctx);
+               spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
+-              /* Out of mem doesn't actually happen, since we fall back
+-               * to direct descriptors */
+               if (err == -ENOMEM || err == -ENOSPC)
+                       return BLK_STS_RESOURCE;
+               return BLK_STS_IOERR;
diff --git a/queue-4.14/workqueue-don-t-use-wq_select_unbound_cpu-for-bound-works.patch b/queue-4.14/workqueue-don-t-use-wq_select_unbound_cpu-for-bound-works.patch
new file mode 100644 (file)
index 0000000..38a8c83
--- /dev/null
@@ -0,0 +1,61 @@
+From aa202f1f56960c60e7befaa0f49c72b8fa11b0a8 Mon Sep 17 00:00:00 2001
+From: Hillf Danton <hdanton@sina.com>
+Date: Fri, 24 Jan 2020 20:14:45 -0500
+Subject: workqueue: don't use wq_select_unbound_cpu() for bound works
+
+From: Hillf Danton <hdanton@sina.com>
+
+commit aa202f1f56960c60e7befaa0f49c72b8fa11b0a8 upstream.
+
+wq_select_unbound_cpu() is designed for unbound workqueues only, but
+it's wrongly called when using a bound workqueue too.
+
+Fixing this ensures work queued to a bound workqueue with
+cpu=WORK_CPU_UNBOUND always runs on the local CPU.
+
+Before, that would happen only if wq_unbound_cpumask happened to include
+it (likely almost always the case), or was empty, or we got lucky with
+forced round-robin placement.  So restricting
+/sys/devices/virtual/workqueue/cpumask to a small subset of a machine's
+CPUs would cause some bound work items to run unexpectedly there.
+
+Fixes: ef557180447f ("workqueue: schedule WORK_CPU_UNBOUND work on wq_unbound_cpumask CPUs")
+Cc: stable@vger.kernel.org # v4.5+
+Signed-off-by: Hillf Danton <hdanton@sina.com>
+[dj: massage changelog]
+Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Lai Jiangshan <jiangshanlai@gmail.com>
+Cc: linux-kernel@vger.kernel.org
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/workqueue.c |   14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -1386,14 +1386,16 @@ static void __queue_work(int cpu, struct
+           WARN_ON_ONCE(!is_chained_work(wq)))
+               return;
+ retry:
+-      if (req_cpu == WORK_CPU_UNBOUND)
+-              cpu = wq_select_unbound_cpu(raw_smp_processor_id());
+-
+       /* pwq which will be used unless @work is executing elsewhere */
+-      if (!(wq->flags & WQ_UNBOUND))
+-              pwq = per_cpu_ptr(wq->cpu_pwqs, cpu);
+-      else
++      if (wq->flags & WQ_UNBOUND) {
++              if (req_cpu == WORK_CPU_UNBOUND)
++                      cpu = wq_select_unbound_cpu(raw_smp_processor_id());
+               pwq = unbound_pwq_by_node(wq, cpu_to_node(cpu));
++      } else {
++              if (req_cpu == WORK_CPU_UNBOUND)
++                      cpu = raw_smp_processor_id();
++              pwq = per_cpu_ptr(wq->cpu_pwqs, cpu);
++      }
+       /*
+        * If @work was previously on a different pool, it might still be