--- /dev/null
+From 016d5baad04269e8559332df05f89bd95b52d6ad Mon Sep 17 00:00:00 2001
+From: Lan Tianyu <tianyu.lan@intel.com>
+Date: Tue, 30 Jul 2013 14:00:42 +0200
+Subject: ACPI / battery: Fix parsing _BIX return value
+
+From: Lan Tianyu <tianyu.lan@intel.com>
+
+commit 016d5baad04269e8559332df05f89bd95b52d6ad upstream.
+
+The _BIX method returns extended battery info as a package.
+According the ACPI spec (ACPI 5, Section 10.2.2.2), the first member
+of that package should be "Revision". However, the current ACPI
+battery driver treats the first member as "Power Unit" which should
+be the second member. This causes the result of _BIX return data
+parsing to be incorrect.
+
+Fix this by adding a new member called 'revision' to struct
+acpi_battery and adding the offsetof() information on it to
+extended_info_offsets[] as the first row.
+
+[rjw: Changelog]
+Reported-and-tested-by: Jan Hoffmann <jan.christian.hoffmann@gmail.com>
+References: http://bugzilla.kernel.org/show_bug.cgi?id=60519
+Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/battery.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/acpi/battery.c
++++ b/drivers/acpi/battery.c
+@@ -117,6 +117,7 @@ struct acpi_battery {
+ struct acpi_device *device;
+ struct notifier_block pm_nb;
+ unsigned long update_time;
++ int revision;
+ int rate_now;
+ int capacity_now;
+ int voltage_now;
+@@ -359,6 +360,7 @@ static struct acpi_offsets info_offsets[
+ };
+
+ static struct acpi_offsets extended_info_offsets[] = {
++ {offsetof(struct acpi_battery, revision), 0},
+ {offsetof(struct acpi_battery, power_unit), 0},
+ {offsetof(struct acpi_battery, design_capacity), 0},
+ {offsetof(struct acpi_battery, full_charge_capacity), 0},
--- /dev/null
+From 83e612f632c3897be29ef02e0472f6d63e258378 Mon Sep 17 00:00:00 2001
+From: Tomasz Moń <desowin@gmail.com>
+Date: Tue, 23 Jul 2013 07:42:49 +0200
+Subject: mwifiex: Add missing endian conversion.
+
+From: Tomasz Moń <desowin@gmail.com>
+
+commit 83e612f632c3897be29ef02e0472f6d63e258378 upstream.
+
+Both type and pkt_len variables are in host endian and these should be in
+Little Endian in the payload.
+
+Signed-off-by: Tomasz Moń <desowin@gmail.com>
+Acked-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/sdio.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/mwifiex/sdio.c
++++ b/drivers/net/wireless/mwifiex/sdio.c
+@@ -1441,8 +1441,8 @@ static int mwifiex_sdio_host_to_card(str
+ /* Allocate buffer and copy payload */
+ blk_size = MWIFIEX_SDIO_BLOCK_SIZE;
+ buf_block_len = (pkt_len + blk_size - 1) / blk_size;
+- *(u16 *) &payload[0] = (u16) pkt_len;
+- *(u16 *) &payload[2] = type;
++ *(__le16 *)&payload[0] = cpu_to_le16((u16)pkt_len);
++ *(__le16 *)&payload[2] = cpu_to_le16(type);
+
+ /*
+ * This is SDIO specific header
--- /dev/null
+From 953b3539ef9301b8ef73f4b6e2fd824b86aae65a Mon Sep 17 00:00:00 2001
+From: Avinash Patil <patila@marvell.com>
+Date: Mon, 29 Jul 2013 16:32:37 -0700
+Subject: mwifiex: check for bss_role instead of bss_mode for STA operations
+
+From: Avinash Patil <patila@marvell.com>
+
+commit 953b3539ef9301b8ef73f4b6e2fd824b86aae65a upstream.
+
+This patch fixes an issue wherein association would fail on P2P
+interfaces. This happened because we are checking priv->mode
+against NL80211_IFTYPE_STATION. While this check is correct for
+infrastructure stations, it would fail P2P clients for which mode
+is NL80211_IFTYPE_P2P_CLIENT.
+
+Better check would be bss_role which has only 2 values: STA/AP.
+
+Signed-off-by: Avinash Patil <patila@marvell.com>
+Signed-off-by: Stone Piao <piaoyun@marvell.com>
+Signed-off-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/cfg80211.c | 4 ++--
+ drivers/net/wireless/mwifiex/join.c | 6 ++++--
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/mwifiex/cfg80211.c
++++ b/drivers/net/wireless/mwifiex/cfg80211.c
+@@ -1668,9 +1668,9 @@ mwifiex_cfg80211_connect(struct wiphy *w
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ int ret;
+
+- if (priv->bss_mode != NL80211_IFTYPE_STATION) {
++ if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
+ wiphy_err(wiphy,
+- "%s: reject infra assoc request in non-STA mode\n",
++ "%s: reject infra assoc request in non-STA role\n",
+ dev->name);
+ return -EINVAL;
+ }
+--- a/drivers/net/wireless/mwifiex/join.c
++++ b/drivers/net/wireless/mwifiex/join.c
+@@ -1290,8 +1290,10 @@ int mwifiex_associate(struct mwifiex_pri
+ {
+ u8 current_bssid[ETH_ALEN];
+
+- /* Return error if the adapter or table entry is not marked as infra */
+- if ((priv->bss_mode != NL80211_IFTYPE_STATION) ||
++ /* Return error if the adapter is not STA role or table entry
++ * is not marked as infra.
++ */
++ if ((GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) ||
+ (bss_desc->bss_mode != NL80211_IFTYPE_STATION))
+ return -1;
+
--- /dev/null
+From 237b2ac8ac89a6b0120decdd05c7bf4637deb98a Mon Sep 17 00:00:00 2001
+From: Avinash Patil <patila@marvell.com>
+Date: Mon, 29 Jul 2013 16:32:38 -0700
+Subject: mwifiex: fix wrong data rates in P2P client
+
+From: Avinash Patil <patila@marvell.com>
+
+commit 237b2ac8ac89a6b0120decdd05c7bf4637deb98a upstream.
+
+This patch fixes an issue wherein adhoc rates were being copied
+into association request from P2P client.
+
+Signed-off-by: Avinash Patil <patila@marvell.com>
+Signed-off-by: Stone Piao <piaoyun@marvell.com>
+Signed-off-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/cfp.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/mwifiex/cfp.c
++++ b/drivers/net/wireless/mwifiex/cfp.c
+@@ -415,7 +415,8 @@ u32 mwifiex_get_supported_rates(struct m
+ u32 k = 0;
+ struct mwifiex_adapter *adapter = priv->adapter;
+
+- if (priv->bss_mode == NL80211_IFTYPE_STATION) {
++ if (priv->bss_mode == NL80211_IFTYPE_STATION ||
++ priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
+ switch (adapter->config_bands) {
+ case BAND_B:
+ dev_dbg(adapter->dev, "info: infra band=%d "
--- /dev/null
+From e2288b66fe7ff0288382b2af671b4da558b44472 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <stf_xl@wp.pl>
+Date: Sun, 28 Jul 2013 13:17:22 +0200
+Subject: rt2x00: fix stop queue
+
+From: Stanislaw Gruszka <stf_xl@wp.pl>
+
+commit e2288b66fe7ff0288382b2af671b4da558b44472 upstream.
+
+Since we clear QUEUE_STARTED in rt2x00queue_stop_queue(), following
+call to rt2x00queue_pause_queue() reduce to noop, i.e we do not
+stop queue in mac80211.
+
+To fix that introduce rt2x00queue_pause_queue_nocheck() function,
+which will stop queue in mac80211 directly.
+
+Note that rt2x00_start_queue() explicitly set QUEUE_PAUSED bit.
+
+Note also that reordering operations i.e. first call to
+rt2x00queue_pause_queue() and then clear QUEUE_STARTED bit, will race
+with rt2x00queue_unpause_queue(), so calling ieee80211_stop_queue()
+directly is the only available solution to fix the problem without
+major rework.
+
+Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rt2x00/rt2x00queue.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -936,13 +936,8 @@ void rt2x00queue_index_inc(struct queue_
+ spin_unlock_irqrestore(&queue->index_lock, irqflags);
+ }
+
+-void rt2x00queue_pause_queue(struct data_queue *queue)
++void rt2x00queue_pause_queue_nocheck(struct data_queue *queue)
+ {
+- if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
+- !test_bit(QUEUE_STARTED, &queue->flags) ||
+- test_and_set_bit(QUEUE_PAUSED, &queue->flags))
+- return;
+-
+ switch (queue->qid) {
+ case QID_AC_VO:
+ case QID_AC_VI:
+@@ -958,6 +953,15 @@ void rt2x00queue_pause_queue(struct data
+ break;
+ }
+ }
++void rt2x00queue_pause_queue(struct data_queue *queue)
++{
++ if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
++ !test_bit(QUEUE_STARTED, &queue->flags) ||
++ test_and_set_bit(QUEUE_PAUSED, &queue->flags))
++ return;
++
++ rt2x00queue_pause_queue_nocheck(queue);
++}
+ EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue);
+
+ void rt2x00queue_unpause_queue(struct data_queue *queue)
+@@ -1019,7 +1023,7 @@ void rt2x00queue_stop_queue(struct data_
+ return;
+ }
+
+- rt2x00queue_pause_queue(queue);
++ rt2x00queue_pause_queue_nocheck(queue);
+
+ queue->rt2x00dev->ops->lib->stop_queue(queue);
+
bluetooth-add-support-for-atheros_2.patch
bluetooth-add-support-for-mediatek-bluetooth-device.patch
bluetooth-fix-wrong-use-of-ptr_err-in-btusb.patch
+svcrpc-fix-gss-proxy-xdr-decoding-oops.patch
+svcrpc-fix-gss_rpc_upcall-create-error.patch
+svcrpc-fix-kfree-oops-in-gss-proxy-code.patch
+rt2x00-fix-stop-queue.patch
+mwifiex-add-missing-endian-conversion.patch
+mwifiex-check-for-bss_role-instead-of-bss_mode-for-sta-operations.patch
+mwifiex-fix-wrong-data-rates-in-p2p-client.patch
+zram-avoid-invalid-memory-access-in-zram_exit.patch
+zram-use-zram-lock-to-protect-zram_free_page-in-swap-free-notify-path.patch
+zram-destroy-all-devices-on-error-recovery-path-in-zram_init.patch
+zram-avoid-double-free-in-function-zram_bvec_write.patch
+zram-avoid-access-beyond-the-zram-device.patch
+zram-protect-sysfs-handler-from-invalid-memory-access.patch
+acpi-battery-fix-parsing-_bix-return-value.patch
--- /dev/null
+From dc43376c26cef74226174a2394f37f2a3f8a8639 Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Fri, 7 Jun 2013 10:11:19 -0400
+Subject: svcrpc: fix gss-proxy xdr decoding oops
+
+From: "J. Bruce Fields" <bfields@redhat.com>
+
+commit dc43376c26cef74226174a2394f37f2a3f8a8639 upstream.
+
+Uninitialized stack data was being used as the destination for memcpy's.
+
+Longer term we'll just delete some of this code; all we're doing is
+skipping over xdr that we don't care about.
+
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/auth_gss/gss_rpc_xdr.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
+@@ -430,7 +430,7 @@ static int dummy_enc_nameattr_array(stru
+ static int dummy_dec_nameattr_array(struct xdr_stream *xdr,
+ struct gssx_name_attr_array *naa)
+ {
+- struct gssx_name_attr dummy;
++ struct gssx_name_attr dummy = { .attr = {.len = 0} };
+ u32 count, i;
+ __be32 *p;
+
+@@ -493,12 +493,13 @@ static int gssx_enc_name(struct xdr_stre
+ return err;
+ }
+
++
+ static int gssx_dec_name(struct xdr_stream *xdr,
+ struct gssx_name *name)
+ {
+- struct xdr_netobj dummy_netobj;
+- struct gssx_name_attr_array dummy_name_attr_array;
+- struct gssx_option_array dummy_option_array;
++ struct xdr_netobj dummy_netobj = { .len = 0 };
++ struct gssx_name_attr_array dummy_name_attr_array = { .count = 0 };
++ struct gssx_option_array dummy_option_array = { .count = 0 };
+ int err;
+
+ /* name->display_name */
--- /dev/null
+From 9f96392b0ae6aefc02a9b900c3f4889dfafc8402 Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Mon, 10 Jun 2013 16:06:44 -0400
+Subject: svcrpc: fix gss_rpc_upcall create error
+
+From: "J. Bruce Fields" <bfields@redhat.com>
+
+commit 9f96392b0ae6aefc02a9b900c3f4889dfafc8402 upstream.
+
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/auth_gss/gss_rpc_upcall.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
++++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
+@@ -120,7 +120,7 @@ static int gssp_rpc_create(struct net *n
+ if (IS_ERR(clnt)) {
+ dprintk("RPC: failed to create AF_LOCAL gssproxy "
+ "client (errno %ld).\n", PTR_ERR(clnt));
+- result = -PTR_ERR(clnt);
++ result = PTR_ERR(clnt);
+ *_clnt = NULL;
+ goto out;
+ }
--- /dev/null
+From 743e217129f69aab074abe520a464fd0c6b1cca1 Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Wed, 31 Jul 2013 14:11:14 -0400
+Subject: svcrpc: fix kfree oops in gss-proxy code
+
+From: "J. Bruce Fields" <bfields@redhat.com>
+
+commit 743e217129f69aab074abe520a464fd0c6b1cca1 upstream.
+
+mech_oid.data is an array, not kmalloc()'d memory.
+
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/auth_gss/gss_rpc_upcall.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
++++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
+@@ -328,7 +328,6 @@ void gssp_free_upcall_data(struct gssp_u
+ kfree(data->in_handle.data);
+ kfree(data->out_handle.data);
+ kfree(data->out_token.data);
+- kfree(data->mech_oid.data);
+ free_svc_cred(&data->creds);
+ }
+
--- /dev/null
+From 12a7ad3b810e77137d0caf97a6dd97591e075b30 Mon Sep 17 00:00:00 2001
+From: Jiang Liu <liuj97@gmail.com>
+Date: Fri, 7 Jun 2013 00:07:26 +0800
+Subject: zram: avoid access beyond the zram device
+
+From: Jiang Liu <liuj97@gmail.com>
+
+commit 12a7ad3b810e77137d0caf97a6dd97591e075b30 upstream.
+
+Function valid_io_request() should verify the entire request are within
+the zram device address range. Otherwise it may cause invalid memory
+access when accessing/modifying zram->meta->table[index] because the
+'index' is out of range. Then it may access non-exist memory, randomly
+modify memory belong to other subsystems, which is hard to track down.
+
+Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/zram/zram_drv.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/zram/zram_drv.c
++++ b/drivers/staging/zram/zram_drv.c
+@@ -420,13 +420,20 @@ out:
+ */
+ static inline int valid_io_request(struct zram *zram, struct bio *bio)
+ {
+- if (unlikely(
+- (bio->bi_sector >= (zram->disksize >> SECTOR_SHIFT)) ||
+- (bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)) ||
+- (bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))) {
++ u64 start, end, bound;
++
++ /* unaligned request */
++ if (unlikely(bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
++ return 0;
++ if (unlikely(bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
++ return 0;
+
++ start = bio->bi_sector;
++ end = start + (bio->bi_size >> SECTOR_SHIFT);
++ bound = zram->disksize >> SECTOR_SHIFT;
++ /* out of range range */
++ if (unlikely(start >= bound || end >= bound || start > end))
+ return 0;
+- }
+
+ /* I/O request is valid */
+ return 1;
--- /dev/null
+From 65c484609a3b25c35e4edcd5f2c38f98f5226093 Mon Sep 17 00:00:00 2001
+From: Jiang Liu <liuj97@gmail.com>
+Date: Fri, 7 Jun 2013 00:07:25 +0800
+Subject: zram: avoid double free in function zram_bvec_write()
+
+From: Jiang Liu <liuj97@gmail.com>
+
+commit 65c484609a3b25c35e4edcd5f2c38f98f5226093 upstream.
+
+When doing a patial write and the whole page is filled with zero,
+zram_bvec_write() will free uncmem twice.
+
+Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
+Acked-by: Minchan Kim <minchan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/zram/zram_drv.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/staging/zram/zram_drv.c
++++ b/drivers/staging/zram/zram_drv.c
+@@ -272,8 +272,6 @@ static int zram_bvec_write(struct zram *
+
+ if (page_zero_filled(uncmem)) {
+ kunmap_atomic(user_mem);
+- if (is_partial_io(bvec))
+- kfree(uncmem);
+ zram->stats.pages_zero++;
+ zram_set_flag(meta, index, ZRAM_ZERO);
+ ret = 0;
--- /dev/null
+From 6030ea9b35971a4200062f010341ab832e878ac9 Mon Sep 17 00:00:00 2001
+From: Jiang Liu <liuj97@gmail.com>
+Date: Fri, 7 Jun 2013 00:07:22 +0800
+Subject: zram: avoid invalid memory access in zram_exit()
+
+From: Jiang Liu <liuj97@gmail.com>
+
+commit 6030ea9b35971a4200062f010341ab832e878ac9 upstream.
+
+Memory for zram->disk object may have already been freed after returning
+from destroy_device(zram), then it's unsafe for zram_reset_device(zram)
+to access zram->disk again.
+
+We can't solve this bug by flipping the order of destroy_device(zram)
+and zram_reset_device(zram), that will cause deadlock issues to the
+zram sysfs handler.
+
+So fix it by holding an extra reference to zram->disk before calling
+destroy_device(zram).
+
+Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/zram/zram_drv.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/staging/zram/zram_drv.c
++++ b/drivers/staging/zram/zram_drv.c
+@@ -727,8 +727,10 @@ static void __exit zram_exit(void)
+ for (i = 0; i < num_devices; i++) {
+ zram = &zram_devices[i];
+
++ get_disk(zram->disk);
+ destroy_device(zram);
+ zram_reset_device(zram);
++ put_disk(zram->disk);
+ }
+
+ unregister_blkdev(zram_major, "zram");
--- /dev/null
+From 39a9b8ac9333e4268ecff7da6c9d1ab3823ff243 Mon Sep 17 00:00:00 2001
+From: Jiang Liu <liuj97@gmail.com>
+Date: Fri, 7 Jun 2013 00:07:24 +0800
+Subject: zram: destroy all devices on error recovery path in zram_init()
+
+From: Jiang Liu <liuj97@gmail.com>
+
+commit 39a9b8ac9333e4268ecff7da6c9d1ab3823ff243 upstream.
+
+On error recovery path of zram_init(), it leaks the zram device object
+causing the failure. So change create_device() to free allocated
+resources on error path.
+
+Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
+Acked-by: Minchan Kim <minchan@kernel.org>
+Acked-by: Jerome Marchand <jmarchan@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/zram/zram_drv.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/zram/zram_drv.c
++++ b/drivers/staging/zram/zram_drv.c
+@@ -595,7 +595,7 @@ static const struct block_device_operati
+
+ static int create_device(struct zram *zram, int device_id)
+ {
+- int ret = 0;
++ int ret = -ENOMEM;
+
+ init_rwsem(&zram->lock);
+ init_rwsem(&zram->init_lock);
+@@ -605,7 +605,6 @@ static int create_device(struct zram *zr
+ if (!zram->queue) {
+ pr_err("Error allocating disk queue for device %d\n",
+ device_id);
+- ret = -ENOMEM;
+ goto out;
+ }
+
+@@ -615,11 +614,9 @@ static int create_device(struct zram *zr
+ /* gendisk structure */
+ zram->disk = alloc_disk(1);
+ if (!zram->disk) {
+- blk_cleanup_queue(zram->queue);
+ pr_warn("Error allocating disk structure for device %d\n",
+ device_id);
+- ret = -ENOMEM;
+- goto out;
++ goto out_free_queue;
+ }
+
+ zram->disk->major = zram_major;
+@@ -648,11 +645,17 @@ static int create_device(struct zram *zr
+ &zram_disk_attr_group);
+ if (ret < 0) {
+ pr_warn("Error creating sysfs group");
+- goto out;
++ goto out_free_disk;
+ }
+
+ zram->init_done = 0;
++ return 0;
+
++out_free_disk:
++ del_gendisk(zram->disk);
++ put_disk(zram->disk);
++out_free_queue:
++ blk_cleanup_queue(zram->queue);
+ out:
+ return ret;
+ }
--- /dev/null
+From 5863e10b441e7ea4b492f930f1be180a97d026f3 Mon Sep 17 00:00:00 2001
+From: Jiang Liu <liuj97@gmail.com>
+Date: Fri, 7 Jun 2013 00:07:27 +0800
+Subject: zram: protect sysfs handler from invalid memory access
+
+From: Jiang Liu <liuj97@gmail.com>
+
+commit 5863e10b441e7ea4b492f930f1be180a97d026f3 upstream.
+
+Use zram->init_lock to protect access to zram->meta, otherwise it
+may cause invalid memory access if zram->meta has been freed by
+zram_reset_device().
+
+This issue may be triggered by:
+Thread 1:
+while true; do cat mem_used_total; done
+Thread 2:
+while true; do echo 8M > disksize; echo 1 > reset; done
+
+Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
+Acked-by: Minchan Kim <minchan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/zram/zram_sysfs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/staging/zram/zram_sysfs.c
++++ b/drivers/staging/zram/zram_sysfs.c
+@@ -188,8 +188,10 @@ static ssize_t mem_used_total_show(struc
+ struct zram *zram = dev_to_zram(dev);
+ struct zram_meta *meta = zram->meta;
+
++ down_read(&zram->init_lock);
+ if (zram->init_done)
+ val = zs_get_total_size_bytes(meta->mem_pool);
++ up_read(&zram->init_lock);
+
+ return sprintf(buf, "%llu\n", val);
+ }
--- /dev/null
+From 57ab048532c0d975538cebd4456491b5c34248f4 Mon Sep 17 00:00:00 2001
+From: Jiang Liu <liuj97@gmail.com>
+Date: Fri, 7 Jun 2013 00:07:23 +0800
+Subject: zram: use zram->lock to protect zram_free_page() in swap free notify path
+
+From: Jiang Liu <liuj97@gmail.com>
+
+commit 57ab048532c0d975538cebd4456491b5c34248f4 upstream.
+
+zram_slot_free_notify() is free-running without any protection from
+concurrent operations. So there are race conditions between
+zram_bvec_read()/zram_bvec_write() and zram_slot_free_notify(),
+and possible consequences include:
+1) Trigger BUG_ON(!handle) on zram_bvec_write() side.
+2) Access to freed pages on zram_bvec_read() side.
+3) Break some fields (bad_compress, good_compress, pages_stored)
+ in zram->stats if the swap layer makes concurrently call to
+ zram_slot_free_notify().
+
+So enhance zram_slot_free_notify() to acquire writer lock on zram->lock
+before calling zram_free_page().
+
+Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/zram/zram_drv.c | 2 ++
+ drivers/staging/zram/zram_drv.h | 5 +++--
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/zram/zram_drv.c
++++ b/drivers/staging/zram/zram_drv.c
+@@ -582,7 +582,9 @@ static void zram_slot_free_notify(struct
+ struct zram *zram;
+
+ zram = bdev->bd_disk->private_data;
++ down_write(&zram->lock);
+ zram_free_page(zram, index);
++ up_write(&zram->lock);
+ zram_stat64_inc(zram, &zram->stats.notify_free);
+ }
+
+--- a/drivers/staging/zram/zram_drv.h
++++ b/drivers/staging/zram/zram_drv.h
+@@ -93,8 +93,9 @@ struct zram_meta {
+ struct zram {
+ struct zram_meta *meta;
+ spinlock_t stat64_lock; /* protect 64-bit stats */
+- struct rw_semaphore lock; /* protect compression buffers and table
+- * against concurrent read and writes */
++ struct rw_semaphore lock; /* protect compression buffers, table,
++ * 32bit stat counters against concurrent
++ * notifications, reads and writes */
+ struct request_queue *queue;
+ struct gendisk *disk;
+ int init_done;