commit: b4ce9ca77ea63e1f533b5ecfe8a938534f86f934 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Sat Feb 7 01:17:01 2015 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Sat Feb 7 01:17:01 2015 +0000 URL: http://sources.gentoo.org/gitweb/?p=proj/linux-patches.git;a=commit;h=b4ce9ca7
Linux patch 3.14.32 --- 0000_README | 4 + 1031_linux-3.14.32.patch | 1098 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1102 insertions(+) diff --git a/0000_README b/0000_README index 18e35f0..04f7bef 100644 --- a/0000_README +++ b/0000_README @@ -166,6 +166,10 @@ Patch: 1030_linux-3.14.31.patch From: http://www.kernel.org Desc: Linux 3.14.31 +Patch: 1031_linux-3.14.32.patch +From: http://www.kernel.org +Desc: Linux 3.14.32 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1031_linux-3.14.32.patch b/1031_linux-3.14.32.patch new file mode 100644 index 0000000..cca57f3 --- /dev/null +++ b/1031_linux-3.14.32.patch @@ -0,0 +1,1098 @@ +diff --git a/Makefile b/Makefile +index 5abf670c6651..00fffa3f2310 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 31 ++SUBLEVEL = 32 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index 11b3914660d2..42f2fb8c5a00 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -464,12 +464,21 @@ void __init dma_contiguous_remap(void) + map.type = MT_MEMORY_DMA_READY; + + /* +- * Clear previous low-memory mapping ++ * Clear previous low-memory mapping to ensure that the ++ * TLB does not see any conflicting entries, then flush ++ * the TLB of the old entries before creating new mappings. ++ * ++ * This ensures that any speculatively loaded TLB entries ++ * (even though they may be rare) can not cause any problems, ++ * and ensures that this code is architecturally compliant. + */ + for (addr = __phys_to_virt(start); addr < __phys_to_virt(end); + addr += PMD_SIZE) + pmd_clear(pmd_off_k(addr)); + ++ flush_tlb_kernel_range(__phys_to_virt(start), ++ __phys_to_virt(end)); ++ + iotable_init(&map, 1); + } + } +diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c +index bc5fbc201bcb..f89389f634d7 100644 +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -288,6 +288,7 @@ static inline void disable_surveillance(void) + args.token = rtas_token("set-indicator"); + if (args.token == RTAS_UNKNOWN_SERVICE) + return; ++ args.token = cpu_to_be32(args.token); + args.nargs = cpu_to_be32(3); + args.nret = cpu_to_be32(1); + args.rets = &args.args[3]; +diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile +index b5bb49866bcc..67e9f5cc91ed 100644 +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -76,7 +76,7 @@ suffix-$(CONFIG_KERNEL_LZO) := lzo + suffix-$(CONFIG_KERNEL_LZ4) := lz4 + + RUN_SIZE = $(shell $(OBJDUMP) -h vmlinux | \ +- perl $(srctree)/arch/x86/tools/calc_run_size.pl) ++ $(CONFIG_SHELL) $(srctree)/arch/x86/tools/calc_run_size.sh) + quiet_cmd_mkpiggy = MKPIGGY $@ + cmd_mkpiggy = $(obj)/mkpiggy $< $(RUN_SIZE) > $@ || ( rm -f $@ ; false ) + +diff --git a/arch/x86/tools/calc_run_size.pl b/arch/x86/tools/calc_run_size.pl +deleted file mode 100644 +index 23210baade2d..000000000000 +--- a/arch/x86/tools/calc_run_size.pl ++++ /dev/null +@@ -1,39 +0,0 @@ +-#!/usr/bin/perl +-# +-# Calculate the amount of space needed to run the kernel, including room for +-# the .bss and .brk sections. +-# +-# Usage: +-# objdump -h a.out | perl calc_run_size.pl +-use strict; +- +-my $mem_size = 0; +-my $file_offset = 0; +- +-my $sections=" *[0-9]+ \.(?:bss|brk) +"; +-while (<>) { +- if (/^$sections([0-9a-f]+) +(?:[0-9a-f]+ +){2}([0-9a-f]+)/) { +- my $size = hex($1); +- my $offset = hex($2); +- $mem_size += $size; +- if ($file_offset == 0) { +- $file_offset = $offset; +- } elsif ($file_offset != $offset) { +- # BFD linker shows the same file offset in ELF. +- # Gold linker shows them as consecutive. +- next if ($file_offset + $mem_size == $offset + $size); +- +- printf STDERR "file_offset: 0x%lx\n", $file_offset; +- printf STDERR "mem_size: 0x%lx\n", $mem_size; +- printf STDERR "offset: 0x%lx\n", $offset; +- printf STDERR "size: 0x%lx\n", $size; +- +- die ".bss and .brk are non-contiguous\n"; +- } +- } +-} +- +-if ($file_offset == 0) { +- die "Never found .bss or .brk file offset\n"; +-} +-printf("%d\n", $mem_size + $file_offset); +diff --git a/arch/x86/tools/calc_run_size.sh b/arch/x86/tools/calc_run_size.sh +new file mode 100644 +index 000000000000..1a4c17bb3910 +--- /dev/null ++++ b/arch/x86/tools/calc_run_size.sh +@@ -0,0 +1,42 @@ ++#!/bin/sh ++# ++# Calculate the amount of space needed to run the kernel, including room for ++# the .bss and .brk sections. ++# ++# Usage: ++# objdump -h a.out | sh calc_run_size.sh ++ ++NUM='\([0-9a-fA-F]*[ \t]*\)' ++OUT=$(sed -n 's/^[ \t0-9]*.b[sr][sk][ \t]*'"$NUM$NUM$NUM$NUM"'.*/\1\4/p') ++if [ -z "$OUT" ] ; then ++ echo "Never found .bss or .brk file offset" >&2 ++ exit 1 ++fi ++ ++OUT=$(echo ${OUT# }) ++sizeA=$(printf "%d" 0x${OUT%% *}) ++OUT=${OUT#* } ++offsetA=$(printf "%d" 0x${OUT%% *}) ++OUT=${OUT#* } ++sizeB=$(printf "%d" 0x${OUT%% *}) ++OUT=${OUT#* } ++offsetB=$(printf "%d" 0x${OUT%% *}) ++ ++run_size=$(( $offsetA + $sizeA + $sizeB )) ++ ++# BFD linker shows the same file offset in ELF. ++if [ "$offsetA" -ne "$offsetB" ] ; then ++ # Gold linker shows them as consecutive. ++ endB=$(( $offsetB + $sizeB )) ++ if [ "$endB" != "$run_size" ] ; then ++ printf "sizeA: 0x%x\n" $sizeA >&2 ++ printf "offsetA: 0x%x\n" $offsetA >&2 ++ printf "sizeB: 0x%x\n" $sizeB >&2 ++ printf "offsetB: 0x%x\n" $offsetB >&2 ++ echo ".bss and .brk are non-contiguous" >&2 ++ exit 1 ++ fi ++fi ++ ++printf "%d\n" $run_size ++exit 0 +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 255ca232ecc7..275a7dc2b06c 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -1926,32 +1926,26 @@ static void rbd_dev_parent_put(struct rbd_device *rbd_dev) + * If an image has a non-zero parent overlap, get a reference to its + * parent. + * +- * We must get the reference before checking for the overlap to +- * coordinate properly with zeroing the parent overlap in +- * rbd_dev_v2_parent_info() when an image gets flattened. We +- * drop it again if there is no overlap. +- * + * Returns true if the rbd device has a parent with a non-zero + * overlap and a reference for it was successfully taken, or + * false otherwise. + */ + static bool rbd_dev_parent_get(struct rbd_device *rbd_dev) + { +- int counter; ++ int counter = 0; + + if (!rbd_dev->parent_spec) + return false; + +- counter = atomic_inc_return_safe(&rbd_dev->parent_ref); +- if (counter > 0 && rbd_dev->parent_overlap) +- return true; +- +- /* Image was flattened, but parent is not yet torn down */ ++ down_read(&rbd_dev->header_rwsem); ++ if (rbd_dev->parent_overlap) ++ counter = atomic_inc_return_safe(&rbd_dev->parent_ref); ++ up_read(&rbd_dev->header_rwsem); + + if (counter < 0) + rbd_warn(rbd_dev, "parent reference overflow\n"); + +- return false; ++ return counter > 0; + } + + /* +@@ -3904,7 +3898,6 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) + */ + if (rbd_dev->parent_overlap) { + rbd_dev->parent_overlap = 0; +- smp_mb(); + rbd_dev_parent_put(rbd_dev); + pr_info("%s: clone image has been flattened\n", + rbd_dev->disk->disk_name); +@@ -3948,7 +3941,6 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) + * treat it specially. + */ + rbd_dev->parent_overlap = overlap; +- smp_mb(); + if (!overlap) { + + /* A null parent_spec indicates it's the initial probe */ +@@ -4764,10 +4756,7 @@ static void rbd_dev_unprobe(struct rbd_device *rbd_dev) + { + struct rbd_image_header *header; + +- /* Drop parent reference unless it's already been done (or none) */ +- +- if (rbd_dev->parent_overlap) +- rbd_dev_parent_put(rbd_dev); ++ rbd_dev_parent_put(rbd_dev); + + /* Free dynamic fields from the header, then zero it out */ + +diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c +index 3153eabde39b..de5ab4876a89 100644 +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -2893,6 +2893,13 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, + u32 size = i915_gem_obj_ggtt_size(obj); + uint64_t val; + ++ /* Adjust fence size to match tiled area */ ++ if (obj->tiling_mode != I915_TILING_NONE) { ++ uint32_t row_size = obj->stride * ++ (obj->tiling_mode == I915_TILING_Y ? 32 : 8); ++ size = (size / row_size) * row_size; ++ } ++ + val = (uint64_t)((i915_gem_obj_ggtt_offset(obj) + size - 4096) & + 0xfffff000) << 32; + val |= i915_gem_obj_ggtt_offset(obj) & 0xfffff000; +diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c +index 93ec37649346..79a211782766 100644 +--- a/drivers/i2c/busses/i2c-s3c2410.c ++++ b/drivers/i2c/busses/i2c-s3c2410.c +@@ -753,14 +753,16 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, + int ret; + + pm_runtime_get_sync(&adap->dev); +- clk_prepare_enable(i2c->clk); ++ ret = clk_enable(i2c->clk); ++ if (ret) ++ return ret; + + for (retry = 0; retry < adap->retries; retry++) { + + ret = s3c24xx_i2c_doxfer(i2c, msgs, num); + + if (ret != -EAGAIN) { +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + pm_runtime_put(&adap->dev); + return ret; + } +@@ -770,7 +772,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, + udelay(100); + } + +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + pm_runtime_put(&adap->dev); + return -EREMOTEIO; + } +@@ -1153,7 +1155,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + + clk_prepare_enable(i2c->clk); + ret = s3c24xx_i2c_init(i2c); +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + if (ret != 0) { + dev_err(&pdev->dev, "I2C controller init failed\n"); + return ret; +@@ -1166,6 +1168,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + i2c->irq = ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_err(&pdev->dev, "cannot find IRQ\n"); ++ clk_unprepare(i2c->clk); + return ret; + } + +@@ -1174,6 +1177,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + + if (ret != 0) { + dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); ++ clk_unprepare(i2c->clk); + return ret; + } + } +@@ -1181,6 +1185,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + ret = s3c24xx_i2c_register_cpufreq(i2c); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); ++ clk_unprepare(i2c->clk); + return ret; + } + +@@ -1197,6 +1202,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + if (ret < 0) { + dev_err(&pdev->dev, "failed to add bus to i2c core\n"); + s3c24xx_i2c_deregister_cpufreq(i2c); ++ clk_unprepare(i2c->clk); + return ret; + } + +@@ -1218,6 +1224,8 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) + { + struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); + ++ clk_unprepare(i2c->clk); ++ + pm_runtime_disable(&i2c->adap.dev); + pm_runtime_disable(&pdev->dev); + +@@ -1246,10 +1254,13 @@ static int s3c24xx_i2c_resume(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); + struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); ++ int ret; + +- clk_prepare_enable(i2c->clk); ++ ret = clk_enable(i2c->clk); ++ if (ret) ++ return ret; + s3c24xx_i2c_init(i2c); +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + i2c->suspended = 0; + + return 0; +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index a3769cf84381..b00e282ef166 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -132,8 +132,9 @@ static const struct min_max_quirk min_max_pnpid_table[] = { + 1232, 5710, 1156, 4696 + }, + { +- (const char * const []){"LEN0034", "LEN0036", "LEN0039", +- "LEN2002", "LEN2004", NULL}, ++ (const char * const []){"LEN0034", "LEN0036", "LEN0037", ++ "LEN0039", "LEN2002", "LEN2004", ++ NULL}, + 1024, 5112, 2024, 4832 + }, + { +@@ -162,7 +163,7 @@ static const char * const topbuttonpad_pnp_ids[] = { + "LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */ + "LEN0035", /* X240 */ + "LEN0036", /* T440 */ +- "LEN0037", ++ "LEN0037", /* X1 Carbon 2nd */ + "LEN0038", + "LEN0039", /* T440s */ + "LEN0041", +diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h +index c43c46f7dcd0..dd6d14d2337f 100644 +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -152,6 +152,14 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { + }, + }, + { ++ /* Medion Akoya E7225 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Medion"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), ++ }, ++ }, ++ { + /* Blue FB5601 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "blue"), +diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c +index d290e8396116..b950a803bae8 100644 +--- a/drivers/md/dm-cache-metadata.c ++++ b/drivers/md/dm-cache-metadata.c +@@ -683,7 +683,7 @@ static struct dm_cache_metadata *metadata_open(struct block_device *bdev, + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + DMERR("could not allocate metadata struct"); +- return NULL; ++ return ERR_PTR(-ENOMEM); + } + + atomic_set(&cmd->ref_count, 1); +@@ -745,7 +745,7 @@ static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev, + return cmd; + + cmd = metadata_open(bdev, data_block_size, may_format_device, policy_hint_size); +- if (cmd) { ++ if (!IS_ERR(cmd)) { + mutex_lock(&table_lock); + cmd2 = lookup(bdev); + if (cmd2) { +@@ -780,9 +780,10 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, + { + struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size, + may_format_device, policy_hint_size); +- if (cmd && !same_params(cmd, data_block_size)) { ++ ++ if (!IS_ERR(cmd) && !same_params(cmd, data_block_size)) { + dm_cache_metadata_close(cmd); +- return NULL; ++ return ERR_PTR(-EINVAL); + } + + return cmd; +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index f7e052c7ab5f..c1120eb96d86 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -2744,6 +2744,12 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv) + struct pool_c *pt = ti->private; + struct pool *pool = pt->pool; + ++ if (get_pool_mode(pool) >= PM_READ_ONLY) { ++ DMERR("%s: unable to service pool target messages in READ_ONLY or FAIL mode", ++ dm_device_name(pool->pool_md)); ++ return -EINVAL; ++ } ++ + if (!strcasecmp(argv[0], "create_thin")) + r = process_create_thin_mesg(argc, argv, pool); + +diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c +index 4e65b35bebc0..3d198679510b 100644 +--- a/drivers/net/can/usb/kvaser_usb.c ++++ b/drivers/net/can/usb/kvaser_usb.c +@@ -578,7 +578,7 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv, + usb_sndbulkpipe(dev->udev, + dev->bulk_out->bEndpointAddress), + buf, msg->len, +- kvaser_usb_simple_msg_callback, priv); ++ kvaser_usb_simple_msg_callback, netdev); + usb_anchor_urb(urb, &priv->tx_submitted); + + err = usb_submit_urb(urb, GFP_ATOMIC); +@@ -653,11 +653,6 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + priv = dev->nets[channel]; + stats = &priv->netdev->stats; + +- if (status & M16C_STATE_BUS_RESET) { +- kvaser_usb_unlink_tx_urbs(priv); +- return; +- } +- + skb = alloc_can_err_skb(priv->netdev, &cf); + if (!skb) { + stats->rx_dropped++; +@@ -668,7 +663,7 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + + netdev_dbg(priv->netdev, "Error status: 0x%02x\n", status); + +- if (status & M16C_STATE_BUS_OFF) { ++ if (status & (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) { + cf->can_id |= CAN_ERR_BUSOFF; + + priv->can.can_stats.bus_off++; +@@ -694,9 +689,7 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + } + + new_state = CAN_STATE_ERROR_PASSIVE; +- } +- +- if (status == M16C_STATE_BUS_ERROR) { ++ } else if (status & M16C_STATE_BUS_ERROR) { + if ((priv->can.state < CAN_STATE_ERROR_WARNING) && + ((txerr >= 96) || (rxerr >= 96))) { + cf->can_id |= CAN_ERR_CRTL; +@@ -706,7 +699,8 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + + priv->can.can_stats.error_warning++; + new_state = CAN_STATE_ERROR_WARNING; +- } else if (priv->can.state > CAN_STATE_ERROR_ACTIVE) { ++ } else if ((priv->can.state > CAN_STATE_ERROR_ACTIVE) && ++ ((txerr < 96) && (rxerr < 96))) { + cf->can_id |= CAN_ERR_PROT; + cf->data[2] = CAN_ERR_PROT_ACTIVE; + +@@ -1582,7 +1576,7 @@ static int kvaser_usb_probe(struct usb_interface *intf, + { + struct kvaser_usb *dev; + int err = -ENOMEM; +- int i; ++ int i, retry = 3; + + dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) +@@ -1600,7 +1594,15 @@ static int kvaser_usb_probe(struct usb_interface *intf, + + usb_set_intfdata(intf, dev); + +- err = kvaser_usb_get_software_info(dev); ++ /* On some x86 laptops, plugging a Kvaser device again after ++ * an unplug makes the firmware always ignore the very first ++ * command. For such a case, provide some room for retries ++ * instead of completely exiting the driver. ++ */ ++ do { ++ err = kvaser_usb_get_software_info(dev); ++ } while (--retry && err == -ETIMEDOUT); ++ + if (err) { + dev_err(&intf->dev, + "Cannot get software infos, error %d\n", err); +diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +index 316650c3b5d7..4eb091da7fb6 100644 +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -1610,6 +1610,19 @@ static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev, + if (vid == priv->data.default_vlan) + return 0; + ++ if (priv->data.dual_emac) { ++ /* In dual EMAC, reserved VLAN id should not be used for ++ * creating VLAN interfaces as this can break the dual ++ * EMAC port separation ++ */ ++ int i; ++ ++ for (i = 0; i < priv->data.slaves; i++) { ++ if (vid == priv->slaves[i].port_vlan) ++ return -EINVAL; ++ } ++ } ++ + dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid); + return cpsw_add_vlan_ale_entry(priv, vid); + } +@@ -1623,6 +1636,15 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, + if (vid == priv->data.default_vlan) + return 0; + ++ if (priv->data.dual_emac) { ++ int i; ++ ++ for (i = 0; i < priv->data.slaves; i++) { ++ if (vid == priv->slaves[i].port_vlan) ++ return -EINVAL; ++ } ++ } ++ + dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid); + ret = cpsw_ale_del_vlan(priv->ale, vid, 0); + if (ret != 0) +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index afca1bc24f26..b7984044232d 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1479,7 +1479,7 @@ struct regulator *regulator_get_optional(struct device *dev, const char *id) + } + EXPORT_SYMBOL_GPL(regulator_get_optional); + +-/* Locks held by regulator_put() */ ++/* regulator_list_mutex lock held by regulator_put() */ + static void _regulator_put(struct regulator *regulator) + { + struct regulator_dev *rdev; +@@ -1494,12 +1494,14 @@ static void _regulator_put(struct regulator *regulator) + /* remove any sysfs entries */ + if (regulator->dev) + sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); ++ mutex_lock(&rdev->mutex); + kfree(regulator->supply_name); + list_del(®ulator->list); + kfree(regulator); + + rdev->open_count--; + rdev->exclusive = 0; ++ mutex_unlock(&rdev->mutex); + + module_put(rdev->owner); + } +diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c +index a4c45ea8f688..996e16d12cd4 100644 +--- a/drivers/spi/spi-dw-mid.c ++++ b/drivers/spi/spi-dw-mid.c +@@ -222,7 +222,6 @@ int dw_spi_mid_init(struct dw_spi *dws) + iounmap(clk_reg); + + dws->num_cs = 16; +- dws->fifo_len = 40; /* FIFO has 40 words buffer */ + + #ifdef CONFIG_SPI_DW_MID_DMA + dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL); +diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c +index 7ab3ccb592eb..458a1480dc07 100644 +--- a/drivers/spi/spi-pxa2xx.c ++++ b/drivers/spi/spi-pxa2xx.c +@@ -400,8 +400,8 @@ static void giveback(struct driver_data *drv_data) + cs_deassert(drv_data); + } + +- spi_finalize_current_message(drv_data->master); + drv_data->cur_chip = NULL; ++ spi_finalize_current_message(drv_data->master); + } + + static void reset_sccr1(struct driver_data *drv_data) +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index 38b4be24d13f..26ae6886ac59 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -1153,10 +1153,10 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) + " changed for TCM/pSCSI\n", dev); + return -EINVAL; + } +- if (optimal_sectors > dev->dev_attrib.fabric_max_sectors) { ++ if (optimal_sectors > dev->dev_attrib.hw_max_sectors) { + pr_err("dev[%p]: Passed optimal_sectors %u cannot be" +- " greater than fabric_max_sectors: %u\n", dev, +- optimal_sectors, dev->dev_attrib.fabric_max_sectors); ++ " greater than hw_max_sectors: %u\n", dev, ++ optimal_sectors, dev->dev_attrib.hw_max_sectors); + return -EINVAL; + } + +@@ -1565,7 +1565,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) + DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; + dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; + dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; +- dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; + + xcopy_lun = &dev->xcopy_lun; + xcopy_lun->lun_se_dev = dev; +@@ -1606,6 +1605,7 @@ int target_configure_device(struct se_device *dev) + dev->dev_attrib.hw_max_sectors = + se_dev_align_max_sectors(dev->dev_attrib.hw_max_sectors, + dev->dev_attrib.hw_block_size); ++ dev->dev_attrib.optimal_sectors = dev->dev_attrib.hw_max_sectors; + + dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); + dev->creation_time = get_jiffies_64(); +diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c +index cf991a91a8a9..41eff7d64cb8 100644 +--- a/drivers/target/target_core_file.c ++++ b/drivers/target/target_core_file.c +@@ -620,7 +620,16 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + struct fd_prot fd_prot; + sense_reason_t rc; + int ret = 0; +- ++ /* ++ * We are currently limited by the number of iovecs (2048) per ++ * single vfs_[writev,readv] call. ++ */ ++ if (cmd->data_length > FD_MAX_BYTES) { ++ pr_err("FILEIO: Not able to process I/O of %u bytes due to" ++ "FD_MAX_BYTES: %u iovec count limitiation\n", ++ cmd->data_length, FD_MAX_BYTES); ++ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ++ } + /* + * Call vectorized fileio functions to map struct scatterlist + * physical memory addresses to struct iovec virtual memory. +diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c +index 9e0232cca92e..feefe24a88f7 100644 +--- a/drivers/target/target_core_iblock.c ++++ b/drivers/target/target_core_iblock.c +@@ -123,7 +123,7 @@ static int iblock_configure_device(struct se_device *dev) + q = bdev_get_queue(bd); + + dev->dev_attrib.hw_block_size = bdev_logical_block_size(bd); +- dev->dev_attrib.hw_max_sectors = UINT_MAX; ++ dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); + dev->dev_attrib.hw_queue_depth = q->nr_requests; + + /* +diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c +index 379033f5903b..5216acd68b4b 100644 +--- a/drivers/target/target_core_sbc.c ++++ b/drivers/target/target_core_sbc.c +@@ -910,21 +910,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) + if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { + unsigned long long end_lba; + +- if (sectors > dev->dev_attrib.fabric_max_sectors) { +- printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" +- " big sectors %u exceeds fabric_max_sectors:" +- " %u\n", cdb[0], sectors, +- dev->dev_attrib.fabric_max_sectors); +- return TCM_INVALID_CDB_FIELD; +- } +- if (sectors > dev->dev_attrib.hw_max_sectors) { +- printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" +- " big sectors %u exceeds backend hw_max_sectors:" +- " %u\n", cdb[0], sectors, +- dev->dev_attrib.hw_max_sectors); +- return TCM_INVALID_CDB_FIELD; +- } +- + end_lba = dev->transport->get_blocks(dev) + 1; + if (cmd->t_task_lba + sectors > end_lba) { + pr_err("cmd exceeds last lba %llu " +diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c +index fcdf98fc947c..12a74f646d38 100644 +--- a/drivers/target/target_core_spc.c ++++ b/drivers/target/target_core_spc.c +@@ -503,7 +503,6 @@ static sense_reason_t + spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) + { + struct se_device *dev = cmd->se_dev; +- u32 max_sectors; + int have_tp = 0; + int opt, min; + +@@ -537,9 +536,7 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) + /* + * Set MAXIMUM TRANSFER LENGTH + */ +- max_sectors = min(dev->dev_attrib.fabric_max_sectors, +- dev->dev_attrib.hw_max_sectors); +- put_unaligned_be32(max_sectors, &buf[8]); ++ put_unaligned_be32(dev->dev_attrib.hw_max_sectors, &buf[8]); + + /* + * Set OPTIMAL TRANSFER LENGTH +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index de2543d3c283..7ececa1c6c4f 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -123,6 +123,12 @@ static inline int put_dreq(struct nfs_direct_req *dreq) + */ + ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) + { ++ struct inode *inode = iocb->ki_filp->f_mapping->host; ++ ++ /* we only support swap file calling nfs_direct_IO */ ++ if (!IS_SWAPFILE(inode)) ++ return 0; ++ + #ifndef CONFIG_NFS_SWAP + dprintk("NFS: nfs_direct_IO (%pD) off/no(%Ld/%lu) EINVAL\n", + iocb->ki_filp, (long long) pos, nr_segs); +diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c +index 037f9572b94c..d3f606255b99 100644 +--- a/fs/nfs/nfs4client.c ++++ b/fs/nfs/nfs4client.c +@@ -633,7 +633,7 @@ int nfs41_walk_client_list(struct nfs_client *new, + prev = pos; + + status = nfs_wait_client_init_complete(pos); +- if (status == 0) { ++ if (pos->cl_cons_state == NFS_CS_SESSION_INITING) { + nfs4_schedule_lease_recovery(pos); + status = nfs4_wait_clnt_recover(pos); + } +diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c +index e7d95f959333..fe68d8ac4d3d 100644 +--- a/fs/pstore/ram.c ++++ b/fs/pstore/ram.c +@@ -92,6 +92,7 @@ struct ramoops_context { + struct persistent_ram_ecc_info ecc_info; + unsigned int max_dump_cnt; + unsigned int dump_write_cnt; ++ /* _read_cnt need clear on ramoops_pstore_open */ + unsigned int dump_read_cnt; + unsigned int console_read_cnt; + unsigned int ftrace_read_cnt; +@@ -107,6 +108,7 @@ static int ramoops_pstore_open(struct pstore_info *psi) + + cxt->dump_read_cnt = 0; + cxt->console_read_cnt = 0; ++ cxt->ftrace_read_cnt = 0; + return 0; + } + +@@ -123,13 +125,15 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max, + return NULL; + + prz = przs[i]; ++ if (!prz) ++ return NULL; + +- if (update) { +- /* Update old/shadowed buffer. */ ++ /* Update old/shadowed buffer. */ ++ if (update) + persistent_ram_save_old(prz); +- if (!persistent_ram_old_size(prz)) +- return NULL; +- } ++ ++ if (!persistent_ram_old_size(prz)) ++ return NULL; + + *typep = type; + *id = i; +@@ -435,7 +439,6 @@ static int ramoops_probe(struct platform_device *pdev) + if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size)) + pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); + +- cxt->dump_read_cnt = 0; + cxt->size = pdata->mem_size; + cxt->phys_addr = pdata->mem_address; + cxt->memtype = pdata->mem_type; +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index b4defdecec8a..f6f31d823e8e 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -1962,17 +1962,13 @@ static void pool_mayday_timeout(unsigned long __pool) + * spin_lock_irq(pool->lock) which may be released and regrabbed + * multiple times. Does GFP_KERNEL allocations. Called only from + * manager. +- * +- * Return: +- * %false if no action was taken and pool->lock stayed locked, %true +- * otherwise. + */ +-static bool maybe_create_worker(struct worker_pool *pool) ++static void maybe_create_worker(struct worker_pool *pool) + __releases(&pool->lock) + __acquires(&pool->lock) + { + if (!need_to_create_worker(pool)) +- return false; ++ return; + restart: + spin_unlock_irq(&pool->lock); + +@@ -1989,7 +1985,7 @@ restart: + start_worker(worker); + if (WARN_ON_ONCE(need_to_create_worker(pool))) + goto restart; +- return true; ++ return; + } + + if (!need_to_create_worker(pool)) +@@ -2006,7 +2002,7 @@ restart: + spin_lock_irq(&pool->lock); + if (need_to_create_worker(pool)) + goto restart; +- return true; ++ return; + } + + /** +@@ -2019,15 +2015,9 @@ restart: + * LOCKING: + * spin_lock_irq(pool->lock) which may be released and regrabbed + * multiple times. Called only from manager. +- * +- * Return: +- * %false if no action was taken and pool->lock stayed locked, %true +- * otherwise. + */ +-static bool maybe_destroy_workers(struct worker_pool *pool) ++static void maybe_destroy_workers(struct worker_pool *pool) + { +- bool ret = false; +- + while (too_many_workers(pool)) { + struct worker *worker; + unsigned long expires; +@@ -2041,10 +2031,7 @@ static bool maybe_destroy_workers(struct worker_pool *pool) + } + + destroy_worker(worker); +- ret = true; + } +- +- return ret; + } + + /** +@@ -2064,16 +2051,14 @@ static bool maybe_destroy_workers(struct worker_pool *pool) + * multiple times. Does GFP_KERNEL allocations. + * + * Return: +- * %false if the pool don't need management and the caller can safely start +- * processing works, %true indicates that the function released pool->lock +- * and reacquired it to perform some management function and that the +- * conditions that the caller verified while holding the lock before +- * calling the function might no longer be true. ++ * %false if the pool doesn't need management and the caller can safely ++ * start processing works, %true if management function was performed and ++ * the conditions that the caller verified before calling the function may ++ * no longer be true. + */ + static bool manage_workers(struct worker *worker) + { + struct worker_pool *pool = worker->pool; +- bool ret = false; + + /* + * Managership is governed by two mutexes - manager_arb and +@@ -2097,7 +2082,7 @@ static bool manage_workers(struct worker *worker) + * manager_mutex. + */ + if (!mutex_trylock(&pool->manager_arb)) +- return ret; ++ return false; + + /* + * With manager arbitration won, manager_mutex would be free in +@@ -2107,7 +2092,6 @@ static bool manage_workers(struct worker *worker) + spin_unlock_irq(&pool->lock); + mutex_lock(&pool->manager_mutex); + spin_lock_irq(&pool->lock); +- ret = true; + } + + pool->flags &= ~POOL_MANAGE_WORKERS; +@@ -2116,12 +2100,12 @@ static bool manage_workers(struct worker *worker) + * Destroy and then create so that may_start_working() is true + * on return. + */ +- ret |= maybe_destroy_workers(pool); +- ret |= maybe_create_worker(pool); ++ maybe_destroy_workers(pool); ++ maybe_create_worker(pool); + + mutex_unlock(&pool->manager_mutex); + mutex_unlock(&pool->manager_arb); +- return ret; ++ return true; + } + + /** +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 1e4dc4ed5e0d..815ca56b39e7 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -261,7 +261,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, + else if (rate && rate->flags & IEEE80211_RATE_ERP_G) + channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; + else if (rate) +- channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; ++ channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ; + else + channel_flags |= IEEE80211_CHAN_2GHZ; + put_unaligned_le16(channel_flags, pos); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index df33156ecd2d..18d73df72531 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -2697,6 +2697,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) + if (!rdev->ops->get_key) + return -EOPNOTSUPP; + ++ if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) ++ return -ENOENT; ++ + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; +@@ -2716,10 +2719,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) + goto nla_put_failure; + +- if (pairwise && mac_addr && +- !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) +- return -ENOENT; +- + err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, + get_key_callback); + +@@ -2890,7 +2889,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) + wdev_lock(dev->ieee80211_ptr); + err = nl80211_key_allowed(dev->ieee80211_ptr); + +- if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr && ++ if (key.type == NL80211_KEYTYPE_GROUP && mac_addr && + !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) + err = -ENOENT; + +diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c +index dbc550716790..f60d81497f28 100644 +--- a/sound/core/seq/seq_dummy.c ++++ b/sound/core/seq/seq_dummy.c +@@ -82,36 +82,6 @@ struct snd_seq_dummy_port { + static int my_client = -1; + + /* +- * unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events +- * to subscribers. +- * Note: this callback is called only after all subscribers are removed. +- */ +-static int +-dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info) +-{ +- struct snd_seq_dummy_port *p; +- int i; +- struct snd_seq_event ev; +- +- p = private_data; +- memset(&ev, 0, sizeof(ev)); +- if (p->duplex) +- ev.source.port = p->connect; +- else +- ev.source.port = p->port; +- ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; +- ev.type = SNDRV_SEQ_EVENT_CONTROLLER; +- for (i = 0; i < 16; i++) { +- ev.data.control.channel = i; +- ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF; +- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); +- ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS; +- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); +- } +- return 0; +-} +- +-/* + * event input callback - just redirect events to subscribers + */ + static int +@@ -175,7 +145,6 @@ create_port(int idx, int type) + | SNDRV_SEQ_PORT_TYPE_PORT; + memset(&pcb, 0, sizeof(pcb)); + pcb.owner = THIS_MODULE; +- pcb.unuse = dummy_unuse; + pcb.event_input = dummy_input; + pcb.private_free = dummy_free; + pcb.private_data = rec; +diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c +index f156010e52bc..942ef8427347 100644 +--- a/sound/soc/codecs/wm8960.c ++++ b/sound/soc/codecs/wm8960.c +@@ -555,7 +555,7 @@ static struct { + { 22050, 2 }, + { 24000, 2 }, + { 16000, 3 }, +- { 11250, 4 }, ++ { 11025, 4 }, + { 12000, 4 }, + { 8000, 5 }, + }; +diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h +index 75e14033e8d8..dfdbaa014561 100644 +--- a/sound/soc/fsl/fsl_esai.h ++++ b/sound/soc/fsl/fsl_esai.h +@@ -302,7 +302,7 @@ + #define ESAI_xCCR_xFP_MASK (((1 << ESAI_xCCR_xFP_WIDTH) - 1) << ESAI_xCCR_xFP_SHIFT) + #define ESAI_xCCR_xFP(v) ((((v) - 1) << ESAI_xCCR_xFP_SHIFT) & ESAI_xCCR_xFP_MASK) + #define ESAI_xCCR_xDC_SHIFT 9 +-#define ESAI_xCCR_xDC_WIDTH 4 ++#define ESAI_xCCR_xDC_WIDTH 5 + #define ESAI_xCCR_xDC_MASK (((1 << ESAI_xCCR_xDC_WIDTH) - 1) << ESAI_xCCR_xDC_SHIFT) + #define ESAI_xCCR_xDC(v) ((((v) - 1) << ESAI_xCCR_xDC_SHIFT) & ESAI_xCCR_xDC_MASK) + #define ESAI_xCCR_xPSR_SHIFT 8 +diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c +index 6c19bba23570..6a339fb55479 100644 +--- a/sound/soc/omap/omap-mcbsp.c ++++ b/sound/soc/omap/omap-mcbsp.c +@@ -436,7 +436,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, + case SND_SOC_DAIFMT_CBM_CFS: + /* McBSP slave. FS clock as output */ + regs->srgr2 |= FSGM; +- regs->pcr0 |= FSXM; ++ regs->pcr0 |= FSXM | FSRM; + break; + case SND_SOC_DAIFMT_CBM_CFM: + /* McBSP slave */ +diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c +index 5e9690c85d8f..4f98ff14cf12 100644 +--- a/sound/soc/soc-compress.c ++++ b/sound/soc/soc-compress.c +@@ -696,7 +696,8 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) + rtd->dai_link->stream_name); + + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, +- 1, 0, &be_pcm); ++ rtd->dai_link->dpcm_playback, ++ rtd->dai_link->dpcm_capture, &be_pcm); + if (ret < 0) { + dev_err(rtd->card->dev, "ASoC: can't create compressed for %s\n", + rtd->dai_link->name); +@@ -705,8 +706,10 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) + + rtd->pcm = be_pcm; + rtd->fe_compr = 1; +- be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; +- be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; ++ if (rtd->dai_link->dpcm_playback) ++ be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; ++ else if (rtd->dai_link->dpcm_capture) ++ be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; + memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); + } else + memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));