From: Greg Kroah-Hartman Date: Wed, 18 Jul 2018 10:43:26 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.4.142~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d3334df494ee485f721ae5ed70553842ce11f08b;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: bcm63xx_enet-correct-clock-usage.patch bcm63xx_enet-do-not-write-to-random-dma-channel-on-bcm6345.patch btrfs-fix-duplicate-extents-after-fsync-of-file-with-prealloc-extents.patch cpufreq-cppc-set-platform-specific-transition_delay_us.patch crypto-crypto4xx-fix-crypto4xx_build_pdr-crypto4xx_build_sdr-leak.patch crypto-crypto4xx-remove-bad-list_del.patch ocfs2-ip_alloc_sem-should-be-taken-in-ocfs2_get_block.patch ocfs2-subsystem.su_mutex-is-required-while-accessing-the-item-ci_parent.patch pci-exynos-fix-a-potential-init_clk_resources-null-pointer-dereference.patch xprtrdma-fix-corner-cases-when-handling-device-removal.patch --- diff --git a/queue-4.14/bcm63xx_enet-correct-clock-usage.patch b/queue-4.14/bcm63xx_enet-correct-clock-usage.patch new file mode 100644 index 00000000000..4cb98890925 --- /dev/null +++ b/queue-4.14/bcm63xx_enet-correct-clock-usage.patch @@ -0,0 +1,109 @@ +From 9c86b846ce02f7e35d7234cf090b80553eba5389 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Sun, 1 Oct 2017 13:02:15 +0200 +Subject: bcm63xx_enet: correct clock usage + +From: Jonas Gorski + +commit 9c86b846ce02f7e35d7234cf090b80553eba5389 upstream. + +Check the return code of prepare_enable and change one last instance of +enable only to prepare_enable. Also properly disable and release the +clock in error paths and on remove for enetsw. + +Signed-off-by: Jonas Gorski +Signed-off-by: David S. Miller +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/broadcom/bcm63xx_enet.c | 31 ++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c ++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c +@@ -1773,7 +1773,9 @@ static int bcm_enet_probe(struct platfor + ret = PTR_ERR(priv->mac_clk); + goto out; + } +- clk_prepare_enable(priv->mac_clk); ++ ret = clk_prepare_enable(priv->mac_clk); ++ if (ret) ++ goto out_put_clk_mac; + + /* initialize default and fetch platform data */ + priv->rx_ring_size = BCMENET_DEF_RX_DESC; +@@ -1805,9 +1807,11 @@ static int bcm_enet_probe(struct platfor + if (IS_ERR(priv->phy_clk)) { + ret = PTR_ERR(priv->phy_clk); + priv->phy_clk = NULL; +- goto out_put_clk_mac; ++ goto out_disable_clk_mac; + } +- clk_prepare_enable(priv->phy_clk); ++ ret = clk_prepare_enable(priv->phy_clk); ++ if (ret) ++ goto out_put_clk_phy; + } + + /* do minimal hardware init to be able to probe mii bus */ +@@ -1901,13 +1905,16 @@ out_free_mdio: + out_uninit_hw: + /* turn off mdc clock */ + enet_writel(priv, 0, ENET_MIISC_REG); +- if (priv->phy_clk) { ++ if (priv->phy_clk) + clk_disable_unprepare(priv->phy_clk); ++ ++out_put_clk_phy: ++ if (priv->phy_clk) + clk_put(priv->phy_clk); +- } + +-out_put_clk_mac: ++out_disable_clk_mac: + clk_disable_unprepare(priv->mac_clk); ++out_put_clk_mac: + clk_put(priv->mac_clk); + out: + free_netdev(dev); +@@ -2752,7 +2759,9 @@ static int bcm_enetsw_probe(struct platf + ret = PTR_ERR(priv->mac_clk); + goto out_unmap; + } +- clk_enable(priv->mac_clk); ++ ret = clk_prepare_enable(priv->mac_clk); ++ if (ret) ++ goto out_put_clk; + + priv->rx_chan = 0; + priv->tx_chan = 1; +@@ -2773,7 +2782,7 @@ static int bcm_enetsw_probe(struct platf + + ret = register_netdev(dev); + if (ret) +- goto out_put_clk; ++ goto out_disable_clk; + + netif_carrier_off(dev); + platform_set_drvdata(pdev, dev); +@@ -2782,6 +2791,9 @@ static int bcm_enetsw_probe(struct platf + + return 0; + ++out_disable_clk: ++ clk_disable_unprepare(priv->mac_clk); ++ + out_put_clk: + clk_put(priv->mac_clk); + +@@ -2813,6 +2825,9 @@ static int bcm_enetsw_remove(struct plat + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + ++ clk_disable_unprepare(priv->mac_clk); ++ clk_put(priv->mac_clk); ++ + free_netdev(dev); + return 0; + } diff --git a/queue-4.14/bcm63xx_enet-do-not-write-to-random-dma-channel-on-bcm6345.patch b/queue-4.14/bcm63xx_enet-do-not-write-to-random-dma-channel-on-bcm6345.patch new file mode 100644 index 00000000000..792dd7b587e --- /dev/null +++ b/queue-4.14/bcm63xx_enet-do-not-write-to-random-dma-channel-on-bcm6345.patch @@ -0,0 +1,36 @@ +From d6213c1f2ad54a964b77471690264ed685718928 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Sun, 1 Oct 2017 13:02:16 +0200 +Subject: bcm63xx_enet: do not write to random DMA channel on BCM6345 + +From: Jonas Gorski + +commit d6213c1f2ad54a964b77471690264ed685718928 upstream. + +The DMA controller regs actually point to DMA channel 0, so the write to +ENETDMA_CFG_REG will actually modify a random DMA channel. + +Since DMA controller registers do not exist on BCM6345, guard the write +with the usual check for dma_has_sram. + +Signed-off-by: Jonas Gorski +Signed-off-by: David S. Miller +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/broadcom/bcm63xx_enet.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c ++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c +@@ -1062,7 +1062,8 @@ static int bcm_enet_open(struct net_devi + val = enet_readl(priv, ENET_CTL_REG); + val |= ENET_CTL_ENABLE_MASK; + enet_writel(priv, val, ENET_CTL_REG); +- enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); ++ if (priv->dma_has_sram) ++ enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); + enet_dmac_writel(priv, priv->dma_chan_en_mask, + ENETDMAC_CHANCFG, priv->rx_chan); + diff --git a/queue-4.14/btrfs-fix-duplicate-extents-after-fsync-of-file-with-prealloc-extents.patch b/queue-4.14/btrfs-fix-duplicate-extents-after-fsync-of-file-with-prealloc-extents.patch new file mode 100644 index 00000000000..7afacaa8d4e --- /dev/null +++ b/queue-4.14/btrfs-fix-duplicate-extents-after-fsync-of-file-with-prealloc-extents.patch @@ -0,0 +1,390 @@ +From 31d11b83b96faaee4bb514d375a09489117c3e8d Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Wed, 9 May 2018 16:01:46 +0100 +Subject: Btrfs: fix duplicate extents after fsync of file with prealloc extents + +From: Filipe Manana + +commit 31d11b83b96faaee4bb514d375a09489117c3e8d upstream. + +In commit 471d557afed1 ("Btrfs: fix loss of prealloc extents past i_size +after fsync log replay"), on fsync, we started to always log all prealloc +extents beyond an inode's i_size in order to avoid losing them after a +power failure. However under some cases this can lead to the log replay +code to create duplicate extent items, with different lengths, in the +extent tree. That happens because, as of that commit, we can now log +extent items based on extent maps that are not on the "modified" list +of extent maps of the inode's extent map tree. Logging extent items based +on extent maps is used during the fast fsync path to save time and for +this to work reliably it requires that the extent maps are not merged +with other adjacent extent maps - having the extent maps in the list +of modified extents gives such guarantee. + +Consider the following example, captured during a long run of fsstress, +which illustrates this problem. + +We have inode 271, in the filesystem tree (root 5), for which all of the +following operations and discussion apply to. + +A buffered write starts at offset 312391 with a length of 933471 bytes +(end offset at 1245862). At this point we have, for this inode, the +following extent maps with the their field values: + +em A, start 0, orig_start 0, len 40960, block_start 18446744073709551613, + block_len 0, orig_block_len 0 +em B, start 40960, orig_start 40960, len 376832, block_start 1106399232, + block_len 376832, orig_block_len 376832 +em C, start 417792, orig_start 417792, len 782336, block_start + 18446744073709551613, block_len 0, orig_block_len 0 +em D, start 1200128, orig_start 1200128, len 835584, block_start + 1106776064, block_len 835584, orig_block_len 835584 +em E, start 2035712, orig_start 2035712, len 245760, block_start + 1107611648, block_len 245760, orig_block_len 245760 + +Extent map A corresponds to a hole and extent maps D and E correspond to +preallocated extents. + +Extent map D ends where extent map E begins (1106776064 + 835584 = +1107611648), but these extent maps were not merged because they are in +the inode's list of modified extent maps. + +An fsync against this inode is made, which triggers the fast path +(BTRFS_INODE_NEEDS_FULL_SYNC is not set). This fsync triggers writeback +of the data previously written using buffered IO, and when the respective +ordered extent finishes, btrfs_drop_extents() is called against the +(aligned) range 311296..1249279. This causes a split of extent map D at +btrfs_drop_extent_cache(), replacing extent map D with a new extent map +D', also added to the list of modified extents, with the following +values: + +em D', start 1249280, orig_start of 1200128, + block_start 1106825216 (= 1106776064 + 1249280 - 1200128), + orig_block_len 835584, + block_len 786432 (835584 - (1249280 - 1200128)) + +Then, during the fast fsync, btrfs_log_changed_extents() is called and +extent maps D' and E are removed from the list of modified extents. The +flag EXTENT_FLAG_LOGGING is also set on them. After the extents are logged +clear_em_logging() is called on each of them, and that makes extent map E +to be merged with extent map D' (try_merge_map()), resulting in D' being +deleted and E adjusted to: + +em E, start 1249280, orig_start 1200128, len 1032192, + block_start 1106825216, block_len 1032192, + orig_block_len 245760 + +A direct IO write at offset 1847296 and length of 360448 bytes (end offset +at 2207744) starts, and at that moment the following extent maps exist for +our inode: + +em A, start 0, orig_start 0, len 40960, block_start 18446744073709551613, + block_len 0, orig_block_len 0 +em B, start 40960, orig_start 40960, len 270336, block_start 1106399232, + block_len 270336, orig_block_len 376832 +em C, start 311296, orig_start 311296, len 937984, block_start 1112842240, + block_len 937984, orig_block_len 937984 +em E (prealloc), start 1249280, orig_start 1200128, len 1032192, + block_start 1106825216, block_len 1032192, orig_block_len 245760 + +The dio write results in drop_extent_cache() being called twice. The first +time for a range that starts at offset 1847296 and ends at offset 2035711 +(length of 188416), which results in a double split of extent map E, +replacing it with two new extent maps: + +em F, start 1249280, orig_start 1200128, block_start 1106825216, + block_len 598016, orig_block_len 598016 +em G, start 2035712, orig_start 1200128, block_start 1107611648, + block_len 245760, orig_block_len 1032192 + +It also creates a new extent map that represents a part of the requested +IO (through create_io_em()): + +em H, start 1847296, len 188416, block_start 1107423232, block_len 188416 + +The second call to drop_extent_cache() has a range with a start offset of +2035712 and end offset of 2207743 (length of 172032). This leads to +replacing extent map G with a new extent map I with the following values: + +em I, start 2207744, orig_start 1200128, block_start 1107783680, + block_len 73728, orig_block_len 1032192 + +It also creates a new extent map that represents the second part of the +requested IO (through create_io_em()): + +em J, start 2035712, len 172032, block_start 1107611648, block_len 172032 + +The dio write set the inode's i_size to 2207744 bytes. + +After the dio write the inode has the following extent maps: + +em A, start 0, orig_start 0, len 40960, block_start 18446744073709551613, + block_len 0, orig_block_len 0 +em B, start 40960, orig_start 40960, len 270336, block_start 1106399232, + block_len 270336, orig_block_len 376832 +em C, start 311296, orig_start 311296, len 937984, block_start 1112842240, + block_len 937984, orig_block_len 937984 +em F, start 1249280, orig_start 1200128, len 598016, + block_start 1106825216, block_len 598016, orig_block_len 598016 +em H, start 1847296, orig_start 1200128, len 188416, + block_start 1107423232, block_len 188416, orig_block_len 835584 +em J, start 2035712, orig_start 2035712, len 172032, + block_start 1107611648, block_len 172032, orig_block_len 245760 +em I, start 2207744, orig_start 1200128, len 73728, + block_start 1107783680, block_len 73728, orig_block_len 1032192 + +Now do some change to the file, like adding a xattr for example and then +fsync it again. This triggers a fast fsync path, and as of commit +471d557afed1 ("Btrfs: fix loss of prealloc extents past i_size after fsync +log replay"), we use the extent map I to log a file extent item because +it's a prealloc extent and it starts at an offset matching the inode's +i_size. However when we log it, we create a file extent item with a value +for the disk byte location that is wrong, as can be seen from the +following output of "btrfs inspect-internal dump-tree": + + item 1 key (271 EXTENT_DATA 2207744) itemoff 3782 itemsize 53 + generation 22 type 2 (prealloc) + prealloc data disk byte 1106776064 nr 1032192 + prealloc data offset 1007616 nr 73728 + +Here the disk byte value corresponds to calculation based on some fields +from the extent map I: + + 1106776064 = block_start (1107783680) - 1007616 (extent_offset) + extent_offset = 2207744 (start) - 1200128 (orig_start) = 1007616 + +The disk byte value of 1106776064 clashes with disk byte values of the +file extent items at offsets 1249280 and 1847296 in the fs tree: + + item 6 key (271 EXTENT_DATA 1249280) itemoff 3568 itemsize 53 + generation 20 type 2 (prealloc) + prealloc data disk byte 1106776064 nr 835584 + prealloc data offset 49152 nr 598016 + item 7 key (271 EXTENT_DATA 1847296) itemoff 3515 itemsize 53 + generation 20 type 1 (regular) + extent data disk byte 1106776064 nr 835584 + extent data offset 647168 nr 188416 ram 835584 + extent compression 0 (none) + item 8 key (271 EXTENT_DATA 2035712) itemoff 3462 itemsize 53 + generation 20 type 1 (regular) + extent data disk byte 1107611648 nr 245760 + extent data offset 0 nr 172032 ram 245760 + extent compression 0 (none) + item 9 key (271 EXTENT_DATA 2207744) itemoff 3409 itemsize 53 + generation 20 type 2 (prealloc) + prealloc data disk byte 1107611648 nr 245760 + prealloc data offset 172032 nr 73728 + +Instead of the disk byte value of 1106776064, the value of 1107611648 +should have been logged. Also the data offset value should have been +172032 and not 1007616. +After a log replay we end up getting two extent items in the extent tree +with different lengths, one of 835584, which is correct and existed +before the log replay, and another one of 1032192 which is wrong and is +based on the logged file extent item: + + item 12 key (1106776064 EXTENT_ITEM 835584) itemoff 3406 itemsize 53 + refs 2 gen 15 flags DATA + extent data backref root 5 objectid 271 offset 1200128 count 2 + item 13 key (1106776064 EXTENT_ITEM 1032192) itemoff 3353 itemsize 53 + refs 1 gen 22 flags DATA + extent data backref root 5 objectid 271 offset 1200128 count 1 + +Obviously this leads to many problems and a filesystem check reports many +errors: + + (...) + checking extents + Extent back ref already exists for 1106776064 parent 0 root 5 owner 271 offset 1200128 num_refs 1 + extent item 1106776064 has multiple extent items + ref mismatch on [1106776064 835584] extent item 2, found 3 + Incorrect local backref count on 1106776064 root 5 owner 271 offset 1200128 found 2 wanted 1 back 0x55b1d0ad7680 + Backref 1106776064 root 5 owner 271 offset 1200128 num_refs 0 not found in extent tree + Incorrect local backref count on 1106776064 root 5 owner 271 offset 1200128 found 1 wanted 0 back 0x55b1d0ad4e70 + Backref bytes do not match extent backref, bytenr=1106776064, ref bytes=835584, backref bytes=1032192 + backpointer mismatch on [1106776064 835584] + checking free space cache + block group 1103101952 has wrong amount of free space + failed to load free space cache for block group 1103101952 + checking fs roots + (...) + +So fix this by logging the prealloc extents beyond the inode's i_size +based on searches in the subvolume tree instead of the extent maps. + +Fixes: 471d557afed1 ("Btrfs: fix loss of prealloc extents past i_size after fsync log replay") +CC: stable@vger.kernel.org # 4.14+ +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/tree-log.c | 137 ++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 112 insertions(+), 25 deletions(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -4214,6 +4214,110 @@ static int log_one_extent(struct btrfs_t + return ret; + } + ++/* ++ * Log all prealloc extents beyond the inode's i_size to make sure we do not ++ * lose them after doing a fast fsync and replaying the log. We scan the ++ * subvolume's root instead of iterating the inode's extent map tree because ++ * otherwise we can log incorrect extent items based on extent map conversion. ++ * That can happen due to the fact that extent maps are merged when they ++ * are not in the extent map tree's list of modified extents. ++ */ ++static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, ++ struct btrfs_inode *inode, ++ struct btrfs_path *path) ++{ ++ struct btrfs_root *root = inode->root; ++ struct btrfs_key key; ++ const u64 i_size = i_size_read(&inode->vfs_inode); ++ const u64 ino = btrfs_ino(inode); ++ struct btrfs_path *dst_path = NULL; ++ u64 last_extent = (u64)-1; ++ int ins_nr = 0; ++ int start_slot; ++ int ret; ++ ++ if (!(inode->flags & BTRFS_INODE_PREALLOC)) ++ return 0; ++ ++ key.objectid = ino; ++ key.type = BTRFS_EXTENT_DATA_KEY; ++ key.offset = i_size; ++ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); ++ if (ret < 0) ++ goto out; ++ ++ while (true) { ++ struct extent_buffer *leaf = path->nodes[0]; ++ int slot = path->slots[0]; ++ ++ if (slot >= btrfs_header_nritems(leaf)) { ++ if (ins_nr > 0) { ++ ret = copy_items(trans, inode, dst_path, path, ++ &last_extent, start_slot, ++ ins_nr, 1, 0); ++ if (ret < 0) ++ goto out; ++ ins_nr = 0; ++ } ++ ret = btrfs_next_leaf(root, path); ++ if (ret < 0) ++ goto out; ++ if (ret > 0) { ++ ret = 0; ++ break; ++ } ++ continue; ++ } ++ ++ btrfs_item_key_to_cpu(leaf, &key, slot); ++ if (key.objectid > ino) ++ break; ++ if (WARN_ON_ONCE(key.objectid < ino) || ++ key.type < BTRFS_EXTENT_DATA_KEY || ++ key.offset < i_size) { ++ path->slots[0]++; ++ continue; ++ } ++ if (last_extent == (u64)-1) { ++ last_extent = key.offset; ++ /* ++ * Avoid logging extent items logged in past fsync calls ++ * and leading to duplicate keys in the log tree. ++ */ ++ do { ++ ret = btrfs_truncate_inode_items(trans, ++ root->log_root, ++ &inode->vfs_inode, ++ i_size, ++ BTRFS_EXTENT_DATA_KEY); ++ } while (ret == -EAGAIN); ++ if (ret) ++ goto out; ++ } ++ if (ins_nr == 0) ++ start_slot = slot; ++ ins_nr++; ++ path->slots[0]++; ++ if (!dst_path) { ++ dst_path = btrfs_alloc_path(); ++ if (!dst_path) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ } ++ } ++ if (ins_nr > 0) { ++ ret = copy_items(trans, inode, dst_path, path, &last_extent, ++ start_slot, ins_nr, 1, 0); ++ if (ret > 0) ++ ret = 0; ++ } ++out: ++ btrfs_release_path(path); ++ btrfs_free_path(dst_path); ++ return ret; ++} ++ + static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_inode *inode, +@@ -4256,6 +4360,11 @@ static int btrfs_log_changed_extents(str + if (em->generation <= test_gen) + continue; + ++ /* We log prealloc extents beyond eof later. */ ++ if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) && ++ em->start >= i_size_read(&inode->vfs_inode)) ++ continue; ++ + if (em->start < logged_start) + logged_start = em->start; + if ((em->start + em->len - 1) > logged_end) +@@ -4268,31 +4377,6 @@ static int btrfs_log_changed_extents(str + num++; + } + +- /* +- * Add all prealloc extents beyond the inode's i_size to make sure we +- * don't lose them after doing a fast fsync and replaying the log. +- */ +- if (inode->flags & BTRFS_INODE_PREALLOC) { +- struct rb_node *node; +- +- for (node = rb_last(&tree->map); node; node = rb_prev(node)) { +- em = rb_entry(node, struct extent_map, rb_node); +- if (em->start < i_size_read(&inode->vfs_inode)) +- break; +- if (!list_empty(&em->list)) +- continue; +- /* Same as above loop. */ +- if (++num > 32768) { +- list_del_init(&tree->modified_extents); +- ret = -EFBIG; +- goto process; +- } +- refcount_inc(&em->refs); +- set_bit(EXTENT_FLAG_LOGGING, &em->flags); +- list_add_tail(&em->list, &extents); +- } +- } +- + list_sort(NULL, &extents, extent_cmp); + btrfs_get_logged_extents(inode, logged_list, logged_start, logged_end); + /* +@@ -4337,6 +4421,9 @@ process: + up_write(&inode->dio_sem); + + btrfs_release_path(path); ++ if (!ret) ++ ret = btrfs_log_prealloc_extents(trans, inode, path); ++ + return ret; + } + diff --git a/queue-4.14/cpufreq-cppc-set-platform-specific-transition_delay_us.patch b/queue-4.14/cpufreq-cppc-set-platform-specific-transition_delay_us.patch new file mode 100644 index 00000000000..06009f3c7ee --- /dev/null +++ b/queue-4.14/cpufreq-cppc-set-platform-specific-transition_delay_us.patch @@ -0,0 +1,108 @@ +From d4f3388afd488ed15368fa7413b8bd6d1f98bb1d Mon Sep 17 00:00:00 2001 +From: Prashanth Prakash +Date: Fri, 27 Apr 2018 11:35:27 -0600 +Subject: cpufreq / CPPC: Set platform specific transition_delay_us + +From: Prashanth Prakash + +commit d4f3388afd488ed15368fa7413b8bd6d1f98bb1d upstream. + +Add support to specify platform specific transition_delay_us instead +of using the transition delay derived from PCC. + +With commit 3d41386d556d (cpufreq: CPPC: Use transition_delay_us +depending transition_latency) we are setting transition_delay_us +directly and not applying the LATENCY_MULTIPLIER. Because of that, +on Qualcomm Centriq we can end up with a very high rate of frequency +change requests when using the schedutil governor (default +rate_limit_us=10 compared to an earlier value of 10000). + +The PCC subspace describes the rate at which the platform can accept +commands on the CPPC's PCC channel. This includes read and write +command on the PCC channel that can be used for reasons other than +frequency transitions. Moreover the same PCC subspace can be used by +multiple freq domains and deriving transition_delay_us from it as we +do now can be sub-optimal. + +Moreover if a platform does not use PCC for desired_perf register then +there is no way to compute the transition latency or the delay_us. + +CPPC does not have a standard defined mechanism to get the transition +rate or the latency at the moment. + +Given the above limitations, it is simpler to have a platform specific +transition_delay_us and rely on PCC derived value only if a platform +specific value is not available. + +Signed-off-by: Prashanth Prakash +Cc: 4.14+ # 4.14+ +Fixes: 3d41386d556d (cpufreq: CPPC: Use transition_delay_us depending transition_latency) +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + drivers/cpufreq/cppc_cpufreq.c | 46 +++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 44 insertions(+), 2 deletions(-) + +--- a/drivers/cpufreq/cppc_cpufreq.c ++++ b/drivers/cpufreq/cppc_cpufreq.c +@@ -126,6 +126,49 @@ static void cppc_cpufreq_stop_cpu(struct + cpu->perf_caps.lowest_perf, cpu_num, ret); + } + ++/* ++ * The PCC subspace describes the rate at which platform can accept commands ++ * on the shared PCC channel (including READs which do not count towards freq ++ * trasition requests), so ideally we need to use the PCC values as a fallback ++ * if we don't have a platform specific transition_delay_us ++ */ ++#ifdef CONFIG_ARM64 ++#include ++ ++static unsigned int cppc_cpufreq_get_transition_delay_us(int cpu) ++{ ++ unsigned long implementor = read_cpuid_implementor(); ++ unsigned long part_num = read_cpuid_part_number(); ++ unsigned int delay_us = 0; ++ ++ switch (implementor) { ++ case ARM_CPU_IMP_QCOM: ++ switch (part_num) { ++ case QCOM_CPU_PART_FALKOR_V1: ++ case QCOM_CPU_PART_FALKOR: ++ delay_us = 10000; ++ break; ++ default: ++ delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC; ++ break; ++ } ++ break; ++ default: ++ delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC; ++ break; ++ } ++ ++ return delay_us; ++} ++ ++#else ++ ++static unsigned int cppc_cpufreq_get_transition_delay_us(int cpu) ++{ ++ return cppc_get_transition_latency(cpu) / NSEC_PER_USEC; ++} ++#endif ++ + static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) + { + struct cppc_cpudata *cpu; +@@ -163,8 +206,7 @@ static int cppc_cpufreq_cpu_init(struct + policy->cpuinfo.max_freq = cppc_dmi_max_khz; + + policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num); +- policy->transition_delay_us = cppc_get_transition_latency(cpu_num) / +- NSEC_PER_USEC; ++ policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu_num); + policy->shared_type = cpu->shared_type; + + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { diff --git a/queue-4.14/crypto-crypto4xx-fix-crypto4xx_build_pdr-crypto4xx_build_sdr-leak.patch b/queue-4.14/crypto-crypto4xx-fix-crypto4xx_build_pdr-crypto4xx_build_sdr-leak.patch new file mode 100644 index 00000000000..f9ec80e7fd1 --- /dev/null +++ b/queue-4.14/crypto-crypto4xx-fix-crypto4xx_build_pdr-crypto4xx_build_sdr-leak.patch @@ -0,0 +1,90 @@ +From 5d59ad6eea82ef8df92b4109615a0dde9d8093e9 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Fri, 25 Aug 2017 15:47:24 +0200 +Subject: crypto: crypto4xx - fix crypto4xx_build_pdr, crypto4xx_build_sdr leak + +From: Christian Lamparter + +commit 5d59ad6eea82ef8df92b4109615a0dde9d8093e9 upstream. + +If one of the later memory allocations in rypto4xx_build_pdr() +fails: dev->pdr (and/or) dev->pdr_uinfo wouldn't be freed. + +crypto4xx_build_sdr() has the same issue with dev->sdr. + +Signed-off-by: Christian Lamparter +Signed-off-by: Herbert Xu +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/crypto/amcc/crypto4xx_core.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/drivers/crypto/amcc/crypto4xx_core.c ++++ b/drivers/crypto/amcc/crypto4xx_core.c +@@ -207,7 +207,7 @@ static u32 crypto4xx_build_pdr(struct cr + dev->pdr_pa); + return -ENOMEM; + } +- memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD); ++ memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD); + dev->shadow_sa_pool = dma_alloc_coherent(dev->core_dev->device, + 256 * PPC4XX_NUM_PD, + &dev->shadow_sa_pool_pa, +@@ -240,13 +240,15 @@ static u32 crypto4xx_build_pdr(struct cr + + static void crypto4xx_destroy_pdr(struct crypto4xx_device *dev) + { +- if (dev->pdr != NULL) ++ if (dev->pdr) + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_pd) * PPC4XX_NUM_PD, + dev->pdr, dev->pdr_pa); ++ + if (dev->shadow_sa_pool) + dma_free_coherent(dev->core_dev->device, 256 * PPC4XX_NUM_PD, + dev->shadow_sa_pool, dev->shadow_sa_pool_pa); ++ + if (dev->shadow_sr_pool) + dma_free_coherent(dev->core_dev->device, + sizeof(struct sa_state_record) * PPC4XX_NUM_PD, +@@ -416,12 +418,12 @@ static u32 crypto4xx_build_sdr(struct cr + + static void crypto4xx_destroy_sdr(struct crypto4xx_device *dev) + { +- if (dev->sdr != NULL) ++ if (dev->sdr) + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_sd) * PPC4XX_NUM_SD, + dev->sdr, dev->sdr_pa); + +- if (dev->scatter_buffer_va != NULL) ++ if (dev->scatter_buffer_va) + dma_free_coherent(dev->core_dev->device, + dev->scatter_buffer_size * PPC4XX_NUM_SD, + dev->scatter_buffer_va, +@@ -1191,7 +1193,7 @@ static int crypto4xx_probe(struct platfo + + rc = crypto4xx_build_gdr(core_dev->dev); + if (rc) +- goto err_build_gdr; ++ goto err_build_pdr; + + rc = crypto4xx_build_sdr(core_dev->dev); + if (rc) +@@ -1234,12 +1236,11 @@ err_iomap: + err_request_irq: + irq_dispose_mapping(core_dev->irq); + tasklet_kill(&core_dev->tasklet); +- crypto4xx_destroy_sdr(core_dev->dev); + err_build_sdr: ++ crypto4xx_destroy_sdr(core_dev->dev); + crypto4xx_destroy_gdr(core_dev->dev); +-err_build_gdr: +- crypto4xx_destroy_pdr(core_dev->dev); + err_build_pdr: ++ crypto4xx_destroy_pdr(core_dev->dev); + kfree(core_dev->dev); + err_alloc_dev: + kfree(core_dev); diff --git a/queue-4.14/crypto-crypto4xx-remove-bad-list_del.patch b/queue-4.14/crypto-crypto4xx-remove-bad-list_del.patch new file mode 100644 index 00000000000..92b21e7e59b --- /dev/null +++ b/queue-4.14/crypto-crypto4xx-remove-bad-list_del.patch @@ -0,0 +1,39 @@ +From a728a196d253530f17da5c86dc7dfbe58c5f7094 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Fri, 25 Aug 2017 15:47:14 +0200 +Subject: crypto: crypto4xx - remove bad list_del + +From: Christian Lamparter + +commit a728a196d253530f17da5c86dc7dfbe58c5f7094 upstream. + +alg entries are only added to the list, after the registration +was successful. If the registration failed, it was never added +to the list in the first place. + +Signed-off-by: Christian Lamparter +Signed-off-by: Herbert Xu +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/crypto/amcc/crypto4xx_core.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/crypto/amcc/crypto4xx_core.c ++++ b/drivers/crypto/amcc/crypto4xx_core.c +@@ -1033,12 +1033,10 @@ int crypto4xx_register_alg(struct crypto + break; + } + +- if (rc) { +- list_del(&alg->entry); ++ if (rc) + kfree(alg); +- } else { ++ else + list_add_tail(&alg->entry, &sec_dev->alg_list); +- } + } + + return 0; diff --git a/queue-4.14/ocfs2-ip_alloc_sem-should-be-taken-in-ocfs2_get_block.patch b/queue-4.14/ocfs2-ip_alloc_sem-should-be-taken-in-ocfs2_get_block.patch new file mode 100644 index 00000000000..ee718f4e9d4 --- /dev/null +++ b/queue-4.14/ocfs2-ip_alloc_sem-should-be-taken-in-ocfs2_get_block.patch @@ -0,0 +1,122 @@ +From 3e4c56d41eef5595035872a2ec5a483f42e8917f Mon Sep 17 00:00:00 2001 +From: alex chen +Date: Wed, 15 Nov 2017 17:31:44 -0800 +Subject: ocfs2: ip_alloc_sem should be taken in ocfs2_get_block() + +From: alex chen + +commit 3e4c56d41eef5595035872a2ec5a483f42e8917f upstream. + +ip_alloc_sem should be taken in ocfs2_get_block() when reading file in +DIRECT mode to prevent concurrent access to extent tree with +ocfs2_dio_end_io_write(), which may cause BUGON in the following +situation: + +read file 'A' end_io of writing file 'A' +vfs_read + __vfs_read + ocfs2_file_read_iter + generic_file_read_iter + ocfs2_direct_IO + __blockdev_direct_IO + do_blockdev_direct_IO + do_direct_IO + get_more_blocks + ocfs2_get_block + ocfs2_extent_map_get_blocks + ocfs2_get_clusters + ocfs2_get_clusters_nocache() + ocfs2_search_extent_list + return the index of record which + contains the v_cluster, that is + v_cluster > rec[i]->e_cpos. + ocfs2_dio_end_io + ocfs2_dio_end_io_write + down_write(&oi->ip_alloc_sem); + ocfs2_mark_extent_written + ocfs2_change_extent_flag + ocfs2_split_extent + ... + --> modify the rec[i]->e_cpos, resulting + in v_cluster < rec[i]->e_cpos. + BUG_ON(v_cluster < le32_to_cpu(rec->e_cpos)) + +[alex.chen@huawei.com: v3] + Link: http://lkml.kernel.org/r/59EF3614.6050008@huawei.com +Link: http://lkml.kernel.org/r/59EF3614.6050008@huawei.com +Fixes: c15471f79506 ("ocfs2: fix sparse file & data ordering issue in direct io") +Signed-off-by: Alex Chen +Reviewed-by: Jun Piao +Reviewed-by: Joseph Qi +Reviewed-by: Gang He +Acked-by: Changwei Ge +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Salvatore Bonaccorso +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ocfs2/aops.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +--- a/fs/ocfs2/aops.c ++++ b/fs/ocfs2/aops.c +@@ -134,6 +134,19 @@ bail: + return err; + } + ++static int ocfs2_lock_get_block(struct inode *inode, sector_t iblock, ++ struct buffer_head *bh_result, int create) ++{ ++ int ret = 0; ++ struct ocfs2_inode_info *oi = OCFS2_I(inode); ++ ++ down_read(&oi->ip_alloc_sem); ++ ret = ocfs2_get_block(inode, iblock, bh_result, create); ++ up_read(&oi->ip_alloc_sem); ++ ++ return ret; ++} ++ + int ocfs2_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) + { +@@ -2128,7 +2141,7 @@ static void ocfs2_dio_free_write_ctx(str + * called like this: dio->get_blocks(dio->inode, fs_startblk, + * fs_count, map_bh, dio->rw == WRITE); + */ +-static int ocfs2_dio_get_block(struct inode *inode, sector_t iblock, ++static int ocfs2_dio_wr_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) + { + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); +@@ -2154,12 +2167,9 @@ static int ocfs2_dio_get_block(struct in + * while file size will be changed. + */ + if (pos + total_len <= i_size_read(inode)) { +- down_read(&oi->ip_alloc_sem); +- /* This is the fast path for re-write. */ +- ret = ocfs2_get_block(inode, iblock, bh_result, create); +- +- up_read(&oi->ip_alloc_sem); + ++ /* This is the fast path for re-write. */ ++ ret = ocfs2_lock_get_block(inode, iblock, bh_result, create); + if (buffer_mapped(bh_result) && + !buffer_new(bh_result) && + ret == 0) +@@ -2424,9 +2434,9 @@ static ssize_t ocfs2_direct_IO(struct ki + return 0; + + if (iov_iter_rw(iter) == READ) +- get_block = ocfs2_get_block; ++ get_block = ocfs2_lock_get_block; + else +- get_block = ocfs2_dio_get_block; ++ get_block = ocfs2_dio_wr_get_block; + + return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, + iter, get_block, diff --git a/queue-4.14/ocfs2-subsystem.su_mutex-is-required-while-accessing-the-item-ci_parent.patch b/queue-4.14/ocfs2-subsystem.su_mutex-is-required-while-accessing-the-item-ci_parent.patch new file mode 100644 index 00000000000..dcf54dbe6ae --- /dev/null +++ b/queue-4.14/ocfs2-subsystem.su_mutex-is-required-while-accessing-the-item-ci_parent.patch @@ -0,0 +1,208 @@ +From 853bc26a7ea39e354b9f8889ae7ad1492ffa28d2 Mon Sep 17 00:00:00 2001 +From: alex chen +Date: Wed, 15 Nov 2017 17:31:48 -0800 +Subject: ocfs2: subsystem.su_mutex is required while accessing the item->ci_parent + +From: alex chen + +commit 853bc26a7ea39e354b9f8889ae7ad1492ffa28d2 upstream. + +The subsystem.su_mutex is required while accessing the item->ci_parent, +otherwise, NULL pointer dereference to the item->ci_parent will be +triggered in the following situation: + +add node delete node +sys_write + vfs_write + configfs_write_file + o2nm_node_store + o2nm_node_local_write + do_rmdir + vfs_rmdir + configfs_rmdir + mutex_lock(&subsys->su_mutex); + unlink_obj + item->ci_group = NULL; + item->ci_parent = NULL; + to_o2nm_cluster_from_node + node->nd_item.ci_parent->ci_parent + BUG since of NULL pointer dereference to nd_item.ci_parent + +Moreover, the o2nm_cluster also should be protected by the +subsystem.su_mutex. + +[alex.chen@huawei.com: v2] + Link: http://lkml.kernel.org/r/59EEAA69.9080703@huawei.com +Link: http://lkml.kernel.org/r/59E9B36A.10700@huawei.com +Signed-off-by: Alex Chen +Reviewed-by: Jun Piao +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Salvatore Bonaccorso +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ocfs2/cluster/nodemanager.c | 63 +++++++++++++++++++++++++++++++++++------ + 1 file changed, 55 insertions(+), 8 deletions(-) + +--- a/fs/ocfs2/cluster/nodemanager.c ++++ b/fs/ocfs2/cluster/nodemanager.c +@@ -40,6 +40,9 @@ char *o2nm_fence_method_desc[O2NM_FENCE_ + "panic", /* O2NM_FENCE_PANIC */ + }; + ++static inline void o2nm_lock_subsystem(void); ++static inline void o2nm_unlock_subsystem(void); ++ + struct o2nm_node *o2nm_get_node_by_num(u8 node_num) + { + struct o2nm_node *node = NULL; +@@ -181,7 +184,10 @@ static struct o2nm_cluster *to_o2nm_clus + { + /* through the first node_set .parent + * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */ +- return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); ++ if (node->nd_item.ci_parent) ++ return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); ++ else ++ return NULL; + } + + enum { +@@ -194,7 +200,7 @@ static ssize_t o2nm_node_num_store(struc + size_t count) + { + struct o2nm_node *node = to_o2nm_node(item); +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + unsigned long tmp; + char *p = (char *)page; + int ret = 0; +@@ -214,6 +220,13 @@ static ssize_t o2nm_node_num_store(struc + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ o2nm_unlock_subsystem(); ++ return -EINVAL; ++ } ++ + write_lock(&cluster->cl_nodes_lock); + if (cluster->cl_nodes[tmp]) + ret = -EEXIST; +@@ -226,6 +239,8 @@ static ssize_t o2nm_node_num_store(struc + set_bit(tmp, cluster->cl_nodes_bitmap); + } + write_unlock(&cluster->cl_nodes_lock); ++ o2nm_unlock_subsystem(); ++ + if (ret) + return ret; + +@@ -269,7 +284,7 @@ static ssize_t o2nm_node_ipv4_address_st + size_t count) + { + struct o2nm_node *node = to_o2nm_node(item); +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + int ret, i; + struct rb_node **p, *parent; + unsigned int octets[4]; +@@ -286,6 +301,13 @@ static ssize_t o2nm_node_ipv4_address_st + be32_add_cpu(&ipv4_addr, octets[i] << (i * 8)); + } + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ o2nm_unlock_subsystem(); ++ return -EINVAL; ++ } ++ + ret = 0; + write_lock(&cluster->cl_nodes_lock); + if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) +@@ -298,6 +320,8 @@ static ssize_t o2nm_node_ipv4_address_st + rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); + } + write_unlock(&cluster->cl_nodes_lock); ++ o2nm_unlock_subsystem(); ++ + if (ret) + return ret; + +@@ -315,7 +339,7 @@ static ssize_t o2nm_node_local_store(str + size_t count) + { + struct o2nm_node *node = to_o2nm_node(item); +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + unsigned long tmp; + char *p = (char *)page; + ssize_t ret; +@@ -333,17 +357,26 @@ static ssize_t o2nm_node_local_store(str + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + /* the only failure case is trying to set a new local node + * when a different one is already set */ + if (tmp && tmp == cluster->cl_has_local && +- cluster->cl_local_node != node->nd_num) +- return -EBUSY; ++ cluster->cl_local_node != node->nd_num) { ++ ret = -EBUSY; ++ goto out; ++ } + + /* bring up the rx thread if we're setting the new local node. */ + if (tmp && !cluster->cl_has_local) { + ret = o2net_start_listening(node); + if (ret) +- return ret; ++ goto out; + } + + if (!tmp && cluster->cl_has_local && +@@ -358,7 +391,11 @@ static ssize_t o2nm_node_local_store(str + cluster->cl_local_node = node->nd_num; + } + +- return count; ++ ret = count; ++ ++out: ++ o2nm_unlock_subsystem(); ++ return ret; + } + + CONFIGFS_ATTR(o2nm_node_, num); +@@ -738,6 +775,16 @@ static struct o2nm_cluster_group o2nm_cl + }, + }; + ++static inline void o2nm_lock_subsystem(void) ++{ ++ mutex_lock(&o2nm_cluster_group.cs_subsys.su_mutex); ++} ++ ++static inline void o2nm_unlock_subsystem(void) ++{ ++ mutex_unlock(&o2nm_cluster_group.cs_subsys.su_mutex); ++} ++ + int o2nm_depend_item(struct config_item *item) + { + return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item); diff --git a/queue-4.14/pci-exynos-fix-a-potential-init_clk_resources-null-pointer-dereference.patch b/queue-4.14/pci-exynos-fix-a-potential-init_clk_resources-null-pointer-dereference.patch new file mode 100644 index 00000000000..c71ddd9ff58 --- /dev/null +++ b/queue-4.14/pci-exynos-fix-a-potential-init_clk_resources-null-pointer-dereference.patch @@ -0,0 +1,37 @@ +From b5d6bc90c9129279d363ccbc02ad11e7b657c0b4 Mon Sep 17 00:00:00 2001 +From: Jaehoon Chung +Date: Mon, 22 Jan 2018 11:28:54 +0900 +Subject: PCI: exynos: Fix a potential init_clk_resources NULL pointer dereference + +From: Jaehoon Chung + +commit b5d6bc90c9129279d363ccbc02ad11e7b657c0b4 upstream. + +In order to avoid triggering a NULL pointer dereference in +exynos_pcie_probe() a check must be put in place to detect if +the init_clk_resources hook is initialized before calling it. + +Add the respective function pointer check in exynos_pcie_probe(). + +Signed-off-by: Jaehoon Chung +[lorenzo.pieralisi@arm.com: rewrote the commit log] +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/dwc/pci-exynos.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/pci/dwc/pci-exynos.c ++++ b/drivers/pci/dwc/pci-exynos.c +@@ -695,7 +695,8 @@ static int __init exynos_pcie_probe(stru + return ret; + } + +- if (ep->ops && ep->ops->get_clk_resources) { ++ if (ep->ops && ep->ops->get_clk_resources && ++ ep->ops->init_clk_resources) { + ret = ep->ops->get_clk_resources(ep); + if (ret) + return ret; diff --git a/queue-4.14/series b/queue-4.14/series index 8c904802856..3cb6125bd47 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -1,3 +1,13 @@ compiler-gcc.h-add-__attribute__-gnu_inline-to-all-inline-declarations.patch x86-asm-add-_asm_arg-constants-for-argument-registers-to-asm-asm.h.patch x86-paravirt-make-native_save_fl-extern-inline.patch +btrfs-fix-duplicate-extents-after-fsync-of-file-with-prealloc-extents.patch +cpufreq-cppc-set-platform-specific-transition_delay_us.patch +xprtrdma-fix-corner-cases-when-handling-device-removal.patch +ocfs2-subsystem.su_mutex-is-required-while-accessing-the-item-ci_parent.patch +ocfs2-ip_alloc_sem-should-be-taken-in-ocfs2_get_block.patch +bcm63xx_enet-correct-clock-usage.patch +bcm63xx_enet-do-not-write-to-random-dma-channel-on-bcm6345.patch +pci-exynos-fix-a-potential-init_clk_resources-null-pointer-dereference.patch +crypto-crypto4xx-remove-bad-list_del.patch +crypto-crypto4xx-fix-crypto4xx_build_pdr-crypto4xx_build_sdr-leak.patch diff --git a/queue-4.14/xprtrdma-fix-corner-cases-when-handling-device-removal.patch b/queue-4.14/xprtrdma-fix-corner-cases-when-handling-device-removal.patch new file mode 100644 index 00000000000..88224e2a39e --- /dev/null +++ b/queue-4.14/xprtrdma-fix-corner-cases-when-handling-device-removal.patch @@ -0,0 +1,83 @@ +From 25524288631fc5b7d33259fca1e0dc38146be5d6 Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Mon, 19 Mar 2018 14:23:16 -0400 +Subject: xprtrdma: Fix corner cases when handling device removal + +From: Chuck Lever + +commit 25524288631fc5b7d33259fca1e0dc38146be5d6 upstream. + +Michal Kalderon has found some corner cases around device unload +with active NFS mounts that I didn't have the imagination to test +when xprtrdma device removal was added last year. + +- The ULP device removal handler is responsible for deallocating + the PD. That wasn't clear to me initially, and my own testing + suggested it was not necessary, but that is incorrect. + +- The transport destruction path can no longer assume that there + is a valid ID. + +- When destroying a transport, ensure that ib_free_cq() is not + invoked on a CQ that was already released. + +Reported-by: Michal Kalderon +Fixes: bebd031866ca ("xprtrdma: Support unplugging an HCA from ...") +Signed-off-by: Chuck Lever +Cc: stable@vger.kernel.org # v4.12+ +Signed-off-by: Anna Schumaker +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + net/sunrpc/xprtrdma/verbs.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -270,7 +270,6 @@ rpcrdma_conn_upcall(struct rdma_cm_id *i + wait_for_completion(&ia->ri_remove_done); + + ia->ri_id = NULL; +- ia->ri_pd = NULL; + ia->ri_device = NULL; + /* Return 1 to ensure the core destroys the id. */ + return 1; +@@ -464,7 +463,9 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia) + ia->ri_id->qp = NULL; + } + ib_free_cq(ep->rep_attr.recv_cq); ++ ep->rep_attr.recv_cq = NULL; + ib_free_cq(ep->rep_attr.send_cq); ++ ep->rep_attr.send_cq = NULL; + + /* The ULP is responsible for ensuring all DMA + * mappings and MRs are gone. +@@ -477,6 +478,8 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia) + rpcrdma_dma_unmap_regbuf(req->rl_recvbuf); + } + rpcrdma_destroy_mrs(buf); ++ ib_dealloc_pd(ia->ri_pd); ++ ia->ri_pd = NULL; + + /* Allow waiters to continue */ + complete(&ia->ri_remove_done); +@@ -650,14 +653,16 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep + + cancel_delayed_work_sync(&ep->rep_connect_worker); + +- if (ia->ri_id->qp) { ++ if (ia->ri_id && ia->ri_id->qp) { + rpcrdma_ep_disconnect(ep, ia); + rdma_destroy_qp(ia->ri_id); + ia->ri_id->qp = NULL; + } + +- ib_free_cq(ep->rep_attr.recv_cq); +- ib_free_cq(ep->rep_attr.send_cq); ++ if (ep->rep_attr.recv_cq) ++ ib_free_cq(ep->rep_attr.recv_cq); ++ if (ep->rep_attr.send_cq) ++ ib_free_cq(ep->rep_attr.send_cq); + } + + /* Re-establish a connection after a device removal event.