From: Greg Kroah-Hartman Date: Mon, 8 Oct 2012 17:39:56 +0000 (-0700) Subject: 3.6-stable patches X-Git-Tag: v3.0.46~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bd7abca0e1af66ebd9cf539af8603125bb7130b7;p=thirdparty%2Fkernel%2Fstable-queue.git 3.6-stable patches added patches: 8021q-fix-mac_len-recomputation-in-vlan_untag.patch drxk-allow-loading-firmware-synchrousnously.patch ipv4-add-a-fib_type-to-fib_info.patch ipv6-del-unreachable-route-when-an-addr-is-deleted-on-lo.patch ipv6-release-reference-of-ip6_null_entry-s-dst-entry-in-__ip6_del_rt.patch ixgbe-fix-ptp-ethtool-timestamping-function.patch jbd2-don-t-write-superblock-when-if-its-empty.patch lguest-fix-occasional-crash-in-example-launcher.patch localmodconfig-fix-localyesconfig-to-set-to-y-not-m.patch net-ethernet-davinci_cpdma-decrease-the-desc-count-when-cleaning-up-the-remaining-packets.patch pm-sleep-use-resume-event-when-call-dpm_resume_early.patch powerpc-eeh-fix-crash-on-converting-of-node-to-edev.patch powerpc-fix-vmx-fix-for-memcpy-case.patch rapidio-rionet-fix-multicast-packet-transmit-logic.patch workqueue-add-missing-smp_wmb-in-process_one_work.patch workqueue-fix-possible-stall-on-try_to_grab_pending-of-a-delayed-work-item.patch --- diff --git a/queue-3.6/8021q-fix-mac_len-recomputation-in-vlan_untag.patch b/queue-3.6/8021q-fix-mac_len-recomputation-in-vlan_untag.patch new file mode 100644 index 00000000000..0ed50bbc056 --- /dev/null +++ b/queue-3.6/8021q-fix-mac_len-recomputation-in-vlan_untag.patch @@ -0,0 +1,40 @@ +From 9d6bd5f3d98404a9e6509f2c32d1f047029dae8f Mon Sep 17 00:00:00 2001 +From: Antonio Quartulli +Date: Tue, 2 Oct 2012 06:14:17 +0000 +Subject: 8021q: fix mac_len recomputation in vlan_untag() + + +From: Antonio Quartulli + +[ Upstream commit 5316cf9a5197eb80b2800e1acadde287924ca975 ] + +skb_reset_mac_len() relies on the value of the skb->network_header pointer, +therefore we must wait for such pointer to be recalculated before computing +the new mac_len value. + +Signed-off-by: Antonio Quartulli +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/8021q/vlan_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/8021q/vlan_core.c ++++ b/net/8021q/vlan_core.c +@@ -105,7 +105,6 @@ static struct sk_buff *vlan_reorder_head + return NULL; + memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); + skb->mac_header += VLAN_HLEN; +- skb_reset_mac_len(skb); + return skb; + } + +@@ -139,6 +138,8 @@ struct sk_buff *vlan_untag(struct sk_buf + + skb_reset_network_header(skb); + skb_reset_transport_header(skb); ++ skb_reset_mac_len(skb); ++ + return skb; + + err_free: diff --git a/queue-3.6/drxk-allow-loading-firmware-synchrousnously.patch b/queue-3.6/drxk-allow-loading-firmware-synchrousnously.patch new file mode 100644 index 00000000000..861f076a749 --- /dev/null +++ b/queue-3.6/drxk-allow-loading-firmware-synchrousnously.patch @@ -0,0 +1,80 @@ +From 8e30783b0b3270736b2cff6415c68b894bc411df Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Tue, 2 Oct 2012 16:01:15 -0300 +Subject: drxk: allow loading firmware synchrousnously + +From: Mauro Carvalho Chehab + +commit 8e30783b0b3270736b2cff6415c68b894bc411df upstream. + +Due to udev-182, the firmware load was changed to be async, as +otherwise udev would give up of loading a firmware. + +Add an option to return to the previous behaviour, async firmware +loads cause failures with the tda18271 driver. + +Antti tested it with the following hardware: + Hauppauge WinTV HVR 930C + MaxMedia UB425-TC + PCTV QuatroStick nano (520e) + +Tested-by: Antti Palosaari +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/dvb/frontends/drxk.h | 2 ++ + drivers/media/dvb/frontends/drxk_hard.c | 20 +++++++++++++++----- + 2 files changed, 17 insertions(+), 5 deletions(-) + +--- a/drivers/media/dvb/frontends/drxk.h ++++ b/drivers/media/dvb/frontends/drxk.h +@@ -28,6 +28,7 @@ + * A value of 0 (default) or lower indicates that + * the correct number of parameters will be + * automatically detected. ++ * @load_firmware_sync: Force the firmware load to be synchronous. + * + * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is + * UIO-3. +@@ -39,6 +40,7 @@ struct drxk_config { + bool parallel_ts; + bool dynamic_clk; + bool enable_merr_cfg; ++ bool load_firmware_sync; + + bool antenna_dvbt; + u16 antenna_gpio; +--- a/drivers/media/dvb/frontends/drxk_hard.c ++++ b/drivers/media/dvb/frontends/drxk_hard.c +@@ -6609,15 +6609,25 @@ struct dvb_frontend *drxk_attach(const s + + /* Load firmware and initialize DRX-K */ + if (state->microcode_name) { +- status = request_firmware_nowait(THIS_MODULE, 1, ++ if (config->load_firmware_sync) { ++ const struct firmware *fw = NULL; ++ ++ status = request_firmware(&fw, state->microcode_name, ++ state->i2c->dev.parent); ++ if (status < 0) ++ fw = NULL; ++ load_firmware_cb(fw, state); ++ } else { ++ status = request_firmware_nowait(THIS_MODULE, 1, + state->microcode_name, + state->i2c->dev.parent, + GFP_KERNEL, + state, load_firmware_cb); +- if (status < 0) { +- printk(KERN_ERR +- "drxk: failed to request a firmware\n"); +- return NULL; ++ if (status < 0) { ++ printk(KERN_ERR ++ "drxk: failed to request a firmware\n"); ++ return NULL; ++ } + } + } else if (init_drxk(state) < 0) + goto error; diff --git a/queue-3.6/ipv4-add-a-fib_type-to-fib_info.patch b/queue-3.6/ipv4-add-a-fib_type-to-fib_info.patch new file mode 100644 index 00000000000..7bbb0cda1d5 --- /dev/null +++ b/queue-3.6/ipv4-add-a-fib_type-to-fib_info.patch @@ -0,0 +1,90 @@ +From 0f805a4315b509718ad3000e6cd6012573289409 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 4 Oct 2012 01:25:26 +0000 +Subject: ipv4: add a fib_type to fib_info + + +From: Eric Dumazet + +[ Upstream commit f4ef85bbda96324785097356336bc79cdd37db0a ] + +commit d2d68ba9fe8 (ipv4: Cache input routes in fib_info nexthops.) +introduced a regression for forwarding. + +This was hard to reproduce but the symptom was that packets were +delivered to local host instead of being forwarded. + +David suggested to add fib_type to fib_info so that we dont +inadvertently share same fib_info for different purposes. + +With help from Julian Anastasov who provided very helpful +hints, reproduced here : + + + Can it be a problem related to fib_info reuse +from different routes. For example, when local IP address +is created for subnet we have: + +broadcast 192.168.0.255 dev DEV proto kernel scope link src +192.168.0.1 +192.168.0.0/24 dev DEV proto kernel scope link src 192.168.0.1 +local 192.168.0.1 dev DEV proto kernel scope host src 192.168.0.1 + + The "dev DEV proto kernel scope link src 192.168.0.1" is +a reused fib_info structure where we put cached routes. +The result can be same fib_info for 192.168.0.255 and +192.168.0.0/24. RTN_BROADCAST is cached only for input +routes. Incoming broadcast to 192.168.0.255 can be cached +and can cause problems for traffic forwarded to 192.168.0.0/24. +So, this patch should solve the problem because it +separates the broadcast from unicast traffic. + + And the ip_route_input_slow caching will work for +local and broadcast input routes (above routes 1 and 3) just +because they differ in scope and use different fib_info. + + + +Many thanks to Chris Clayton for his patience and help. + +Reported-by: Chris Clayton +Bisected-by: Chris Clayton +Reported-by: Dave Jones +Signed-off-by: Eric Dumazet +Cc: Julian Anastasov +Tested-by: Chris Clayton +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/ip_fib.h | 1 + + net/ipv4/fib_semantics.c | 2 ++ + 2 files changed, 3 insertions(+) + +--- a/include/net/ip_fib.h ++++ b/include/net/ip_fib.h +@@ -102,6 +102,7 @@ struct fib_info { + unsigned char fib_dead; + unsigned char fib_protocol; + unsigned char fib_scope; ++ unsigned char fib_type; + __be32 fib_prefsrc; + u32 fib_priority; + u32 *fib_metrics; +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -314,6 +314,7 @@ static struct fib_info *fib_find_info(co + nfi->fib_scope == fi->fib_scope && + nfi->fib_prefsrc == fi->fib_prefsrc && + nfi->fib_priority == fi->fib_priority && ++ nfi->fib_type == fi->fib_type && + memcmp(nfi->fib_metrics, fi->fib_metrics, + sizeof(u32) * RTAX_MAX) == 0 && + ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 && +@@ -833,6 +834,7 @@ struct fib_info *fib_create_info(struct + fi->fib_flags = cfg->fc_flags; + fi->fib_priority = cfg->fc_priority; + fi->fib_prefsrc = cfg->fc_prefsrc; ++ fi->fib_type = cfg->fc_type; + + fi->fib_nhs = nhs; + change_nexthops(fi) { diff --git a/queue-3.6/ipv6-del-unreachable-route-when-an-addr-is-deleted-on-lo.patch b/queue-3.6/ipv6-del-unreachable-route-when-an-addr-is-deleted-on-lo.patch new file mode 100644 index 00000000000..43822b69c74 --- /dev/null +++ b/queue-3.6/ipv6-del-unreachable-route-when-an-addr-is-deleted-on-lo.patch @@ -0,0 +1,50 @@ +From be5bbaad23547fa5551691b6185641004d206967 Mon Sep 17 00:00:00 2001 +From: Nicolas Dichtel +Date: Wed, 26 Sep 2012 00:04:55 +0000 +Subject: ipv6: del unreachable route when an addr is deleted on lo + + +From: Nicolas Dichtel + +[ Upstream commit 64c6d08e6490fb18cea09bb03686c149946bd818 ] + +When an address is added on loopback (ip -6 a a 2002::1/128 dev lo), two routes +are added: + - one in the local table: + local 2002::1 via :: dev lo proto none metric 0 + - one the in main table (for the prefix): + unreachable 2002::1 dev lo proto kernel metric 256 error -101 + +When the address is deleted, the route inserted in the main table remains +because we use rt6_lookup(), which returns NULL when dst->error is set, which +is the case here! Thus, it is better to use ip6_route_lookup() to avoid this +kind of filter. + +Signed-off-by: Nicolas Dichtel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/addrconf.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -788,10 +788,16 @@ static void ipv6_del_addr(struct inet6_i + struct in6_addr prefix; + struct rt6_info *rt; + struct net *net = dev_net(ifp->idev->dev); ++ struct flowi6 fl6 = {}; ++ + ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); +- rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); ++ fl6.flowi6_oif = ifp->idev->dev->ifindex; ++ fl6.daddr = prefix; ++ rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, ++ RT6_LOOKUP_F_IFACE); + +- if (rt && addrconf_is_prefix_route(rt)) { ++ if (rt != net->ipv6.ip6_null_entry && ++ addrconf_is_prefix_route(rt)) { + if (onlink == 0) { + ip6_del_rt(rt); + rt = NULL; diff --git a/queue-3.6/ipv6-release-reference-of-ip6_null_entry-s-dst-entry-in-__ip6_del_rt.patch b/queue-3.6/ipv6-release-reference-of-ip6_null_entry-s-dst-entry-in-__ip6_del_rt.patch new file mode 100644 index 00000000000..9b519113c32 --- /dev/null +++ b/queue-3.6/ipv6-release-reference-of-ip6_null_entry-s-dst-entry-in-__ip6_del_rt.patch @@ -0,0 +1,50 @@ +From 78fd2204e8bd37393c19b9cbe937540a6e558c09 Mon Sep 17 00:00:00 2001 +From: Gao feng +Date: Wed, 19 Sep 2012 19:25:34 +0000 +Subject: ipv6: release reference of ip6_null_entry's dst entry in __ip6_del_rt + + +From: Gao feng + +[ Upstream commit 6825a26c2dc21eb4f8df9c06d3786ddec97cf53b ] + +as we hold dst_entry before we call __ip6_del_rt, +so we should alse call dst_release not only return +-ENOENT when the rt6_info is ip6_null_entry. + +and we already hold the dst entry, so I think it's +safe to call dst_release out of the write-read lock. + +Signed-off-by: Gao feng +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/route.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1589,17 +1589,18 @@ static int __ip6_del_rt(struct rt6_info + struct fib6_table *table; + struct net *net = dev_net(rt->dst.dev); + +- if (rt == net->ipv6.ip6_null_entry) +- return -ENOENT; ++ if (rt == net->ipv6.ip6_null_entry) { ++ err = -ENOENT; ++ goto out; ++ } + + table = rt->rt6i_table; + write_lock_bh(&table->tb6_lock); +- + err = fib6_del(rt, info); +- dst_release(&rt->dst); +- + write_unlock_bh(&table->tb6_lock); + ++out: ++ dst_release(&rt->dst); + return err; + } + diff --git a/queue-3.6/ixgbe-fix-ptp-ethtool-timestamping-function.patch b/queue-3.6/ixgbe-fix-ptp-ethtool-timestamping-function.patch new file mode 100644 index 00000000000..b1d4d7c7b36 --- /dev/null +++ b/queue-3.6/ixgbe-fix-ptp-ethtool-timestamping-function.patch @@ -0,0 +1,36 @@ +From 1cc92eb871d6cbb1da038b4bcd89eec3c73b9781 Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Fri, 21 Sep 2012 07:23:20 +0000 +Subject: ixgbe: fix PTP ethtool timestamping function + +From: Jacob Keller + +commit 1cc92eb871d6cbb1da038b4bcd89eec3c73b9781 upstream. + +This patch fixes a development issue that occurred due to invalid modes reported +in the ethtool get_ts_info function. The issue is resolved by removing +unsupported modes from the Rx supported list. + +Signed-off-by: Jacob Keller +Tested-by: Phil Schmitt +Signed-off-by: Jeff Kirsher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +@@ -2690,10 +2690,7 @@ static int ixgbe_get_ts_info(struct net_ + (1 << HWTSTAMP_FILTER_NONE) | + (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | + (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | +- (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | +- (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | +- (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | +- (1 << HWTSTAMP_FILTER_SOME); ++ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); + break; + #endif /* CONFIG_IXGBE_PTP */ + default: diff --git a/queue-3.6/jbd2-don-t-write-superblock-when-if-its-empty.patch b/queue-3.6/jbd2-don-t-write-superblock-when-if-its-empty.patch new file mode 100644 index 00000000000..2ce54cdaebf --- /dev/null +++ b/queue-3.6/jbd2-don-t-write-superblock-when-if-its-empty.patch @@ -0,0 +1,48 @@ +From eeecef0af5ea4efd763c9554cf2bd80fc4a0efd3 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Sat, 18 Aug 2012 22:29:40 -0400 +Subject: jbd2: don't write superblock when if its empty + +From: Eric Sandeen + +commit eeecef0af5ea4efd763c9554cf2bd80fc4a0efd3 upstream. + +This sequence: + +# truncate --size=1g fsfile +# mkfs.ext4 -F fsfile +# mount -o loop,ro fsfile /mnt +# umount /mnt +# dmesg | tail + +results in an IO error when unmounting the RO filesystem: + +[ 318.020828] Buffer I/O error on device loop1, logical block 196608 +[ 318.027024] lost page write due to I/O error on loop1 +[ 318.032088] JBD2: Error -5 detected when updating journal superblock for loop1-8. + +This was a regression introduced by commit 24bcc89c7e7c: "jbd2: split +updating of journal superblock and marking journal empty". + +Signed-off-by: Eric Sandeen +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jbd2/journal.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -1354,6 +1354,11 @@ static void jbd2_mark_journal_empty(jour + + BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); + read_lock(&journal->j_state_lock); ++ /* Is it already empty? */ ++ if (sb->s_start == 0) { ++ read_unlock(&journal->j_state_lock); ++ return; ++ } + jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n", + journal->j_tail_sequence); + diff --git a/queue-3.6/lguest-fix-occasional-crash-in-example-launcher.patch b/queue-3.6/lguest-fix-occasional-crash-in-example-launcher.patch new file mode 100644 index 00000000000..8c6e01d6cfe --- /dev/null +++ b/queue-3.6/lguest-fix-occasional-crash-in-example-launcher.patch @@ -0,0 +1,29 @@ +From ca16f580a5db7e60bfafe59a50bb133bd3347491 Mon Sep 17 00:00:00 2001 +From: Rusty Russell +Date: Thu, 4 Oct 2012 12:03:25 +0930 +Subject: lguest: fix occasional crash in example launcher. + +From: Rusty Russell + +commit ca16f580a5db7e60bfafe59a50bb133bd3347491 upstream. + +We usually got away with ->next on the final entry being NULL, but it +finally bit me. + +Signed-off-by: Rusty Russell +Signed-off-by: Greg Kroah-Hartman + +--- + tools/lguest/lguest.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/tools/lguest/lguest.c ++++ b/tools/lguest/lguest.c +@@ -1299,6 +1299,7 @@ static struct device *new_device(const c + dev->feature_len = 0; + dev->num_vq = 0; + dev->running = false; ++ dev->next = NULL; + + /* + * Append to device list. Prepending to a single-linked list is diff --git a/queue-3.6/localmodconfig-fix-localyesconfig-to-set-to-y-not-m.patch b/queue-3.6/localmodconfig-fix-localyesconfig-to-set-to-y-not-m.patch new file mode 100644 index 00000000000..a1e1bb7c72d --- /dev/null +++ b/queue-3.6/localmodconfig-fix-localyesconfig-to-set-to-y-not-m.patch @@ -0,0 +1,38 @@ +From 4eae518d4b01b0cbf2f0d8edb5a6f3d6245ee8fb Mon Sep 17 00:00:00 2001 +From: Yuta Ando +Date: Mon, 1 Oct 2012 23:24:30 +0900 +Subject: localmodconfig: Fix localyesconfig to set to 'y' not 'm' + +From: Yuta Ando + +commit 4eae518d4b01b0cbf2f0d8edb5a6f3d6245ee8fb upstream. + +The kbuild target 'localyesconfig' has been same as 'localmodconfig' +since the commit 50bce3e "kconfig/streamline_config.pl: merge +local{mod,yes}config". The commit expects this script generates +different configure depending on target, but it was not yet implemented. + +So I added code that sets to 'yes' when target is 'localyesconfig'. + +Link: http://lkml.kernel.org/r/1349101470-12243-1-git-send-email-yuta.and@gmail.com + +Signed-off-by: Yuta Ando +Cc: linux-kbuild@vger.kernel.org +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman + +--- + scripts/kconfig/streamline_config.pl | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/scripts/kconfig/streamline_config.pl ++++ b/scripts/kconfig/streamline_config.pl +@@ -605,6 +605,8 @@ foreach my $line (@config_file) { + if (defined($configs{$1})) { + if ($localyesconfig) { + $setconfigs{$1} = 'y'; ++ print "$1=y\n"; ++ next; + } else { + $setconfigs{$1} = $2; + } diff --git a/queue-3.6/net-ethernet-davinci_cpdma-decrease-the-desc-count-when-cleaning-up-the-remaining-packets.patch b/queue-3.6/net-ethernet-davinci_cpdma-decrease-the-desc-count-when-cleaning-up-the-remaining-packets.patch new file mode 100644 index 00000000000..c680ef1a214 --- /dev/null +++ b/queue-3.6/net-ethernet-davinci_cpdma-decrease-the-desc-count-when-cleaning-up-the-remaining-packets.patch @@ -0,0 +1,31 @@ +From dccdd11a3449d39d0e3fdf376f13cf2eabab41b8 Mon Sep 17 00:00:00 2001 +From: Tao Hou +Date: Mon, 1 Oct 2012 16:42:43 +0000 +Subject: net: ethernet: davinci_cpdma: decrease the desc count when cleaning up the remaining packets + + +From: Tao Hou + +[ Upstream commit ffb5ba90017505a19e238e986e6d33f09e4df765 ] + +chan->count is used by rx channel. If the desc count is not updated by +the clean up loop in cpdma_chan_stop, the value written to the rxfree +register in cpdma_chan_start will be incorrect. + +Signed-off-by: Tao Hou +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/ti/davinci_cpdma.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/ti/davinci_cpdma.c ++++ b/drivers/net/ethernet/ti/davinci_cpdma.c +@@ -863,6 +863,7 @@ int cpdma_chan_stop(struct cpdma_chan *c + + next_dma = desc_read(desc, hw_next); + chan->head = desc_from_phys(pool, next_dma); ++ chan->count--; + chan->stats.teardown_dequeue++; + + /* issue callback without locks held */ diff --git a/queue-3.6/pm-sleep-use-resume-event-when-call-dpm_resume_early.patch b/queue-3.6/pm-sleep-use-resume-event-when-call-dpm_resume_early.patch new file mode 100644 index 00000000000..5c7a0236453 --- /dev/null +++ b/queue-3.6/pm-sleep-use-resume-event-when-call-dpm_resume_early.patch @@ -0,0 +1,33 @@ +From 997a031107ec962967ce36db9bc500f1fad491c1 Mon Sep 17 00:00:00 2001 +From: Feng Hong +Date: Wed, 19 Sep 2012 14:16:00 +0200 +Subject: PM / Sleep: use resume event when call dpm_resume_early + +From: Feng Hong + +commit 997a031107ec962967ce36db9bc500f1fad491c1 upstream. + +When dpm_suspend_noirq fail, state is PMSG_SUSPEND, +should change to PMSG_RESUME when dpm_resume_early is called + +Signed-off-by: Feng Hong +Signed-off-by: Raul Xiong +Signed-off-by: Neil Zhang +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/power/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -996,7 +996,7 @@ int dpm_suspend_end(pm_message_t state) + + error = dpm_suspend_noirq(state); + if (error) { +- dpm_resume_early(state); ++ dpm_resume_early(resume_event(state)); + return error; + } + diff --git a/queue-3.6/powerpc-eeh-fix-crash-on-converting-of-node-to-edev.patch b/queue-3.6/powerpc-eeh-fix-crash-on-converting-of-node-to-edev.patch new file mode 100644 index 00000000000..043bdb62f83 --- /dev/null +++ b/queue-3.6/powerpc-eeh-fix-crash-on-converting-of-node-to-edev.patch @@ -0,0 +1,93 @@ +From 1e38b7140185e384da216aff66a711df09b5afc9 Mon Sep 17 00:00:00 2001 +From: Gavin Shan +Date: Mon, 17 Sep 2012 04:34:28 +0000 +Subject: powerpc/eeh: Fix crash on converting OF node to edev + +From: Gavin Shan + +commit 1e38b7140185e384da216aff66a711df09b5afc9 upstream. + +The kernel crash was reported by Alexy. He was testing some feature +with private kernel, in which Alexy added some code in pci_pm_reset() +to read the CSR after writting it. The bug could be reproduced on +Fiber Channel card (Fibre Channel: Emulex Corporation Saturn-X: +LightPulse Fibre Channel Host Adapter (rev 03)) by the following +commands. + + # echo 1 > /sys/devices/pci0004:01/0004:01:00.0/reset + # rmmod lpfc + # modprobe lpfc + +The history behind the test case is that those additional config +space reading operations in pci_pm_reset() would cause EEH error, +but we didn't detect EEH error until "modprobe lpfc". For the case, +all the PCI devices on PCI bus (0004:01) were removed and added after +PE reset. Then the EEH devices would be figured out again based on +the OF nodes. Unfortunately, there were some child OF nodes under +PCI device (0004:01:00.0), but they didn't have attached PCI_DN since +they're invisible from PCI domain. However, we were still trying to +convert OF node to EEH device without checking on the attached PCI_DN. +Eventually, it caused the kernel crash as follows: + +Unable to handle kernel paging request for data at address 0x00000030 +Faulting instruction address: 0xc00000000004d888 +cpu 0x0: Vector: 300 (Data Access) at [c000000fc797b950] + pc: c00000000004d888: .eeh_add_device_tree_early+0x78/0x140 + lr: c00000000004d880: .eeh_add_device_tree_early+0x70/0x140 + sp: c000000fc797bbd0 + msr: 8000000000009032 + dar: 30 + dsisr: 40000000 + current = 0xc000000fc78d9f70 + paca = 0xc00000000edb0000 softe: 0 irq_happened: 0x00 + pid = 2951, comm = eehd +enter ? for help +[c000000fc797bc50] c00000000004d848 .eeh_add_device_tree_early+0x38/0x140 +[c000000fc797bcd0] c00000000004d848 .eeh_add_device_tree_early+0x38/0x140 +[c000000fc797bd50] c000000000051b54 .pcibios_add_pci_devices+0x34/0x190 +[c000000fc797bde0] c00000000004fb10 .eeh_reset_device+0x100/0x160 +[c000000fc797be70] c0000000000502dc .eeh_handle_event+0x19c/0x300 +[c000000fc797bf00] c000000000050570 .eeh_event_handler+0x130/0x1a0 +[c000000fc797bf90] c000000000020138 .kernel_thread+0x54/0x70 + +The patch changes of_node_to_eeh_dev() and just returns NULL if the +passed OF node doesn't have attached PCI_DN. + +Reported-by: Alexey Kardashevskiy +Signed-off-by: Gavin Shan +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/include/asm/pci-bridge.h | 8 ++++++++ + arch/powerpc/platforms/pseries/eeh.c | 2 +- + 2 files changed, 9 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/include/asm/pci-bridge.h ++++ b/arch/powerpc/include/asm/pci-bridge.h +@@ -182,6 +182,14 @@ static inline int pci_device_from_OF_nod + #if defined(CONFIG_EEH) + static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn) + { ++ /* ++ * For those OF nodes whose parent isn't PCI bridge, they ++ * don't have PCI_DN actually. So we have to skip them for ++ * any EEH operations. ++ */ ++ if (!dn || !PCI_DN(dn)) ++ return NULL; ++ + return PCI_DN(dn)->edev; + } + #endif +--- a/arch/powerpc/platforms/pseries/eeh.c ++++ b/arch/powerpc/platforms/pseries/eeh.c +@@ -1029,7 +1029,7 @@ static void eeh_add_device_early(struct + { + struct pci_controller *phb; + +- if (!dn || !of_node_to_eeh_dev(dn)) ++ if (!of_node_to_eeh_dev(dn)) + return; + phb = of_node_to_eeh_dev(dn)->phb; + diff --git a/queue-3.6/powerpc-fix-vmx-fix-for-memcpy-case.patch b/queue-3.6/powerpc-fix-vmx-fix-for-memcpy-case.patch new file mode 100644 index 00000000000..22cfa8d609b --- /dev/null +++ b/queue-3.6/powerpc-fix-vmx-fix-for-memcpy-case.patch @@ -0,0 +1,89 @@ +From c8adfeccee01ce3de6a7d14fcd4e3be02e27f03c Mon Sep 17 00:00:00 2001 +From: Nishanth Aravamudan +Date: Mon, 1 Oct 2012 14:59:13 +0000 +Subject: powerpc: Fix VMX fix for memcpy case + +From: Nishanth Aravamudan + +commit c8adfeccee01ce3de6a7d14fcd4e3be02e27f03c upstream. + +In 2fae7cdb60240e2e2d9b378afbf6d9fcce8a3890 ("powerpc: Fix VMX in +interrupt check in POWER7 copy loops"), Anton inadvertently +introduced a regression for memcpy on POWER7 machines. copyuser and +memcpy diverge slightly in their use of cr1 (copyuser doesn't use it, +but memcpy does) and you end up clobbering that register with your fix. +That results in (taken from an FC18 kernel): + +[ 18.824604] Unrecoverable VMX/Altivec Unavailable Exception f20 at c000000000052f40 +[ 18.824618] Oops: Unrecoverable VMX/Altivec Unavailable Exception, sig: 6 [#1] +[ 18.824623] SMP NR_CPUS=1024 NUMA pSeries +[ 18.824633] Modules linked in: tg3(+) be2net(+) cxgb4(+) ipr(+) sunrpc xts lrw gf128mul dm_crypt dm_round_robin dm_multipath linear raid10 raid456 async_raid6_recov async_memcpy async_pq raid6_pq async_xor xor async_tx raid1 raid0 scsi_dh_rdac scsi_dh_hp_sw scsi_dh_emc scsi_dh_alua squashfs cramfs +[ 18.824705] NIP: c000000000052f40 LR: c00000000020b874 CTR: 0000000000000512 +[ 18.824709] REGS: c000001f1fef7790 TRAP: 0f20 Not tainted (3.6.0-0.rc6.git0.2.fc18.ppc64) +[ 18.824713] MSR: 8000000000009032 CR: 4802802e XER: 20000010 +[ 18.824726] SOFTE: 0 +[ 18.824728] CFAR: 0000000000000f20 +[ 18.824731] TASK = c000000fa7128400[0] 'swapper/24' THREAD: c000000fa7480000 CPU: 24 +GPR00: 00000000ffffffc0 c000001f1fef7a10 c00000000164edc0 c000000f9b9a8120 +GPR04: c000000f9b9a8124 0000000000001438 0000000000000060 03ffffff064657ee +GPR08: 0000000080000000 0000000000000010 0000000000000020 0000000000000030 +GPR12: 0000000028028022 c00000000ff25400 0000000000000001 0000000000000000 +GPR16: 0000000000000000 7fffffffffffffff c0000000016b2180 c00000000156a500 +GPR20: c000000f968c7a90 c0000000131c31d8 c000001f1fef4000 c000000001561d00 +GPR24: 000000000000000a 0000000000000000 0000000000000001 0000000000000012 +GPR28: c000000fa5c04f80 00000000000008bc c0000000015c0a28 000000000000022e +[ 18.824792] NIP [c000000000052f40] .memcpy_power7+0x5a0/0x7c4 +[ 18.824797] LR [c00000000020b874] .pcpu_free_area+0x174/0x2d0 +[ 18.824800] Call Trace: +[ 18.824803] [c000001f1fef7a10] [c000000000052c14] .memcpy_power7+0x274/0x7c4 (unreliable) +[ 18.824809] [c000001f1fef7b10] [c00000000020b874] .pcpu_free_area+0x174/0x2d0 +[ 18.824813] [c000001f1fef7bb0] [c00000000020ba88] .free_percpu+0xb8/0x1b0 +[ 18.824819] [c000001f1fef7c50] [c00000000043d144] .throtl_pd_exit+0x94/0xd0 +[ 18.824824] [c000001f1fef7cf0] [c00000000043acf8] .blkg_free+0x88/0xe0 +[ 18.824829] [c000001f1fef7d90] [c00000000018c048] .rcu_process_callbacks+0x2e8/0x8a0 +[ 18.824835] [c000001f1fef7e90] [c0000000000a8ce8] .__do_softirq+0x158/0x4d0 +[ 18.824840] [c000001f1fef7f90] [c000000000025ecc] .call_do_softirq+0x14/0x24 +[ 18.824845] [c000000fa7483650] [c000000000010e80] .do_softirq+0x160/0x1a0 +[ 18.824850] [c000000fa74836f0] [c0000000000a94a4] .irq_exit+0xf4/0x120 +[ 18.824854] [c000000fa7483780] [c000000000020c44] .timer_interrupt+0x154/0x4d0 +[ 18.824859] [c000000fa7483830] [c000000000003be0] decrementer_common+0x160/0x180 +[ 18.824866] --- Exception: 901 at .plpar_hcall_norets+0x84/0xd4 +[ 18.824866] LR = .check_and_cede_processor+0x48/0x80 +[ 18.824871] [c000000fa7483b20] [c00000000007f018] .check_and_cede_processor+0x18/0x80 (unreliable) +[ 18.824877] [c000000fa7483b90] [c00000000007f104] .dedicated_cede_loop+0x84/0x150 +[ 18.824883] [c000000fa7483c50] [c0000000006bc030] .cpuidle_enter+0x30/0x50 +[ 18.824887] [c000000fa7483cc0] [c0000000006bc9f4] .cpuidle_idle_call+0x104/0x720 +[ 18.824892] [c000000fa7483d80] [c000000000070af8] .pSeries_idle+0x18/0x40 +[ 18.824897] [c000000fa7483df0] [c000000000019084] .cpu_idle+0x1a4/0x380 +[ 18.824902] [c000000fa7483ec0] [c0000000008a4c18] .start_secondary+0x520/0x528 +[ 18.824907] [c000000fa7483f90] [c0000000000093f0] .start_secondary_prolog+0x10/0x14 +[ 18.824911] Instruction dump: +[ 18.824914] 38840008 90030000 90e30004 38630008 7ca62850 7cc300d0 78c7e102 7cf01120 +[ 18.824923] 78c60660 39200010 39400020 39600030 <7e00200c> 7c0020ce 38840010 409f001c +[ 18.824935] ---[ end trace 0bb95124affaaa45 ]--- +[ 18.825046] Unrecoverable VMX/Altivec Unavailable Exception f20 at c000000000052d08 + +I believe the right fix is to make memcpy match usercopy and not use +cr1. + +Signed-off-by: Nishanth Aravamudan +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/lib/memcpy_power7.S | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/lib/memcpy_power7.S ++++ b/arch/powerpc/lib/memcpy_power7.S +@@ -239,8 +239,8 @@ _GLOBAL(memcpy_power7) + ori r9,r9,1 /* stream=1 */ + + srdi r7,r5,7 /* length in cachelines, capped at 0x3FF */ +- cmpldi cr1,r7,0x3FF +- ble cr1,1f ++ cmpldi r7,0x3FF ++ ble 1f + li r7,0x3FF + 1: lis r0,0x0E00 /* depth=7 */ + sldi r7,r7,7 diff --git a/queue-3.6/rapidio-rionet-fix-multicast-packet-transmit-logic.patch b/queue-3.6/rapidio-rionet-fix-multicast-packet-transmit-logic.patch new file mode 100644 index 00000000000..51b11222421 --- /dev/null +++ b/queue-3.6/rapidio-rionet-fix-multicast-packet-transmit-logic.patch @@ -0,0 +1,103 @@ +From 7c4a6106d6451fc03c491e61df37c044505d843a Mon Sep 17 00:00:00 2001 +From: Alexandre Bounine +Date: Thu, 4 Oct 2012 17:15:48 -0700 +Subject: rapidio/rionet: fix multicast packet transmit logic + +From: Alexandre Bounine + +commit 7c4a6106d6451fc03c491e61df37c044505d843a upstream. + +Fix multicast packet transmit logic to account for repetitive transmission +of single skb: +- correct check for available buffers (this bug may produce NULL pointer + crash dump in case of heavy traffic); +- update skb user count (incorrect user counter causes a warning dump from + net_tx_action routine during multicast transfers in systems with three or + more rionet participants). + +Signed-off-by: Alexandre Bounine +Cc: Matt Porter +Cc: David S. Miller +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/rionet.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +--- a/drivers/net/rionet.c ++++ b/drivers/net/rionet.c +@@ -79,6 +79,7 @@ static int rionet_capable = 1; + * on system trade-offs. + */ + static struct rio_dev **rionet_active; ++static int nact; /* total number of active rionet peers */ + + #define is_rionet_capable(src_ops, dst_ops) \ + ((src_ops & RIO_SRC_OPS_DATA_MSG) && \ +@@ -175,6 +176,7 @@ static int rionet_start_xmit(struct sk_b + struct ethhdr *eth = (struct ethhdr *)skb->data; + u16 destid; + unsigned long flags; ++ int add_num = 1; + + local_irq_save(flags); + if (!spin_trylock(&rnet->tx_lock)) { +@@ -182,7 +184,10 @@ static int rionet_start_xmit(struct sk_b + return NETDEV_TX_LOCKED; + } + +- if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) { ++ if (is_multicast_ether_addr(eth->h_dest)) ++ add_num = nact; ++ ++ if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) { + netif_stop_queue(ndev); + spin_unlock_irqrestore(&rnet->tx_lock, flags); + printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n", +@@ -191,11 +196,16 @@ static int rionet_start_xmit(struct sk_b + } + + if (is_multicast_ether_addr(eth->h_dest)) { ++ int count = 0; + for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); + i++) +- if (rionet_active[i]) ++ if (rionet_active[i]) { + rionet_queue_tx_msg(skb, ndev, + rionet_active[i]); ++ if (count) ++ atomic_inc(&skb->users); ++ count++; ++ } + } else if (RIONET_MAC_MATCH(eth->h_dest)) { + destid = RIONET_GET_DESTID(eth->h_dest); + if (rionet_active[destid]) +@@ -220,14 +230,17 @@ static void rionet_dbell_event(struct ri + if (info == RIONET_DOORBELL_JOIN) { + if (!rionet_active[sid]) { + list_for_each_entry(peer, &rionet_peers, node) { +- if (peer->rdev->destid == sid) ++ if (peer->rdev->destid == sid) { + rionet_active[sid] = peer->rdev; ++ nact++; ++ } + } + rio_mport_send_doorbell(mport, sid, + RIONET_DOORBELL_JOIN); + } + } else if (info == RIONET_DOORBELL_LEAVE) { + rionet_active[sid] = NULL; ++ nact--; + } else { + if (netif_msg_intr(rnet)) + printk(KERN_WARNING "%s: unhandled doorbell\n", +@@ -523,6 +536,7 @@ static int rionet_probe(struct rio_dev * + + rc = rionet_setup_netdev(rdev->net->hport, ndev); + rionet_check = 1; ++ nact = 0; + } + + /* diff --git a/queue-3.6/series b/queue-3.6/series index 091994e2960..c63c73ddf76 100644 --- a/queue-3.6/series +++ b/queue-3.6/series @@ -18,3 +18,19 @@ lib-gcd.c-prevent-possible-div-by-0.patch kernel-sys.c-call-disable_nonboot_cpus-in-kernel_restart.patch drivers-scsi-atp870u.c-fix-bad-use-of-udelay.patch drivers-dma-dmaengine.c-lower-the-priority-of-failed-to-get-dma-channel-message.patch +lguest-fix-occasional-crash-in-example-launcher.patch +powerpc-fix-vmx-fix-for-memcpy-case.patch +powerpc-eeh-fix-crash-on-converting-of-node-to-edev.patch +ixgbe-fix-ptp-ethtool-timestamping-function.patch +drxk-allow-loading-firmware-synchrousnously.patch +rapidio-rionet-fix-multicast-packet-transmit-logic.patch +pm-sleep-use-resume-event-when-call-dpm_resume_early.patch +workqueue-add-missing-smp_wmb-in-process_one_work.patch +workqueue-fix-possible-stall-on-try_to_grab_pending-of-a-delayed-work-item.patch +jbd2-don-t-write-superblock-when-if-its-empty.patch +localmodconfig-fix-localyesconfig-to-set-to-y-not-m.patch +ipv4-add-a-fib_type-to-fib_info.patch +8021q-fix-mac_len-recomputation-in-vlan_untag.patch +ipv6-release-reference-of-ip6_null_entry-s-dst-entry-in-__ip6_del_rt.patch +net-ethernet-davinci_cpdma-decrease-the-desc-count-when-cleaning-up-the-remaining-packets.patch +ipv6-del-unreachable-route-when-an-addr-is-deleted-on-lo.patch diff --git a/queue-3.6/workqueue-add-missing-smp_wmb-in-process_one_work.patch b/queue-3.6/workqueue-add-missing-smp_wmb-in-process_one_work.patch new file mode 100644 index 00000000000..6e9bf358f47 --- /dev/null +++ b/queue-3.6/workqueue-add-missing-smp_wmb-in-process_one_work.patch @@ -0,0 +1,44 @@ +From 959d1af8cffc8fd38ed53e8be1cf4ab8782f9c00 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Fri, 3 Aug 2012 10:30:45 -0700 +Subject: workqueue: add missing smp_wmb() in process_one_work() + +From: Tejun Heo + +commit 959d1af8cffc8fd38ed53e8be1cf4ab8782f9c00 upstream. + +WORK_STRUCT_PENDING is used to claim ownership of a work item and +process_one_work() releases it before starting execution. When +someone else grabs PENDING, all pre-release updates to the work item +should be visible and all updates made by the new owner should happen +afterwards. + +Grabbing PENDING uses test_and_set_bit() and thus has a full barrier; +however, clearing doesn't have a matching wmb. Given the preceding +spin_unlock and use of clear_bit, I don't believe this can be a +problem on an actual machine and there hasn't been any related report +but it still is theretically possible for clear_pending to permeate +upwards and happen before work->entry update. + +Add an explicit smp_wmb() before work_clear_pending(). + +Signed-off-by: Tejun Heo +Cc: Oleg Nesterov +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/workqueue.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -2073,7 +2073,9 @@ __acquires(&gcwq->lock) + + spin_unlock_irq(&gcwq->lock); + ++ smp_wmb(); /* paired with test_and_set_bit(PENDING) */ + work_clear_pending(work); ++ + lock_map_acquire_read(&cwq->wq->lockdep_map); + lock_map_acquire(&lockdep_map); + trace_workqueue_execute_start(work); diff --git a/queue-3.6/workqueue-fix-possible-stall-on-try_to_grab_pending-of-a-delayed-work-item.patch b/queue-3.6/workqueue-fix-possible-stall-on-try_to_grab_pending-of-a-delayed-work-item.patch new file mode 100644 index 00000000000..b9054fea71f --- /dev/null +++ b/queue-3.6/workqueue-fix-possible-stall-on-try_to_grab_pending-of-a-delayed-work-item.patch @@ -0,0 +1,92 @@ +From 3aa62497594430ea522050b75c033f71f2c60ee6 Mon Sep 17 00:00:00 2001 +From: Lai Jiangshan +Date: Tue, 18 Sep 2012 10:40:00 -0700 +Subject: workqueue: fix possible stall on try_to_grab_pending() of a delayed work item + +From: Lai Jiangshan + +commit 3aa62497594430ea522050b75c033f71f2c60ee6 upstream. + +Currently, when try_to_grab_pending() grabs a delayed work item, it +leaves its linked work items alone on the delayed_works. The linked +work items are always NO_COLOR and will cause future +cwq_activate_first_delayed() increase cwq->nr_active incorrectly, and +may cause the whole cwq to stall. For example, + +state: cwq->max_active = 1, cwq->nr_active = 1 + one work in cwq->pool, many in cwq->delayed_works. + +step1: try_to_grab_pending() removes a work item from delayed_works + but leaves its NO_COLOR linked work items on it. + +step2: Later on, cwq_activate_first_delayed() activates the linked + work item increasing ->nr_active. + +step3: cwq->nr_active = 1, but all activated work items of the cwq are + NO_COLOR. When they finish, cwq->nr_active will not be + decreased due to NO_COLOR, and no further work items will be + activated from cwq->delayed_works. the cwq stalls. + +Fix it by ensuring the target work item is activated before stealing +PENDING in try_to_grab_pending(). This ensures that all the linked +work items are activated without incorrectly bumping cwq->nr_active. + +tj: Updated comment and description. + +Signed-off-by: Lai Jiangshan +Signed-off-by: Tejun Heo +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/workqueue.c | 25 ++++++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -1927,10 +1927,9 @@ static void move_linked_works(struct wor + *nextp = n; + } + +-static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) ++static void cwq_activate_delayed_work(struct work_struct *work) + { +- struct work_struct *work = list_first_entry(&cwq->delayed_works, +- struct work_struct, entry); ++ struct cpu_workqueue_struct *cwq = get_work_cwq(work); + + trace_workqueue_activate_work(work); + move_linked_works(work, &cwq->pool->worklist, NULL); +@@ -1938,6 +1937,14 @@ static void cwq_activate_first_delayed(s + cwq->nr_active++; + } + ++static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) ++{ ++ struct work_struct *work = list_first_entry(&cwq->delayed_works, ++ struct work_struct, entry); ++ ++ cwq_activate_delayed_work(work); ++} ++ + /** + * cwq_dec_nr_in_flight - decrement cwq's nr_in_flight + * @cwq: cwq of interest +@@ -2846,6 +2853,18 @@ static int try_to_grab_pending(struct wo + smp_rmb(); + if (gcwq == get_work_gcwq(work)) { + debug_work_deactivate(work); ++ ++ /* ++ * A delayed work item cannot be grabbed directly ++ * because it might have linked NO_COLOR work items ++ * which, if left on the delayed_list, will confuse ++ * cwq->nr_active management later on and cause ++ * stall. Make sure the work item is activated ++ * before grabbing. ++ */ ++ if (*work_data_bits(work) & WORK_STRUCT_DELAYED) ++ cwq_activate_delayed_work(work); ++ + list_del_init(&work->entry); + cwq_dec_nr_in_flight(get_work_cwq(work), + get_work_color(work),