]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Nov 2018 10:13:18 +0000 (11:13 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Nov 2018 10:13:18 +0000 (11:13 +0100)
added patches:
cw1200-don-t-leak-memory-if-krealloc-failes.patch
mwifiex-fix-null-pointer-dereference-in-skb_dequeue.patch
mwifiex-fix-p2p-device-doesn-t-find-in-scan-problem.patch
mwifiex-prevent-register-accesses-after-host-is-sleeping.patch
mwifiex-report-error-to-pcie-for-suspend-failure.patch
scsi-ufs-fix-bugs-related-to-null-pointer-access-and-array-size.patch
scsi-ufs-fix-race-between-clock-gating-and-devfreq-scaling-work.patch
scsi-ufshcd-fix-race-between-clk-scaling-and-ungate-work.patch
scsi-ufshcd-release-resources-if-probe-fails.patch

queue-4.9/cw1200-don-t-leak-memory-if-krealloc-failes.patch [new file with mode: 0644]
queue-4.9/input-xpad-add-support-for-xbox1-pdp-camo-series-gam.patch
queue-4.9/mwifiex-fix-null-pointer-dereference-in-skb_dequeue.patch [new file with mode: 0644]
queue-4.9/mwifiex-fix-p2p-device-doesn-t-find-in-scan-problem.patch [new file with mode: 0644]
queue-4.9/mwifiex-prevent-register-accesses-after-host-is-sleeping.patch [new file with mode: 0644]
queue-4.9/mwifiex-report-error-to-pcie-for-suspend-failure.patch [new file with mode: 0644]
queue-4.9/scsi-ufs-fix-bugs-related-to-null-pointer-access-and-array-size.patch [new file with mode: 0644]
queue-4.9/scsi-ufs-fix-race-between-clock-gating-and-devfreq-scaling-work.patch [new file with mode: 0644]
queue-4.9/scsi-ufshcd-fix-race-between-clk-scaling-and-ungate-work.patch [new file with mode: 0644]
queue-4.9/scsi-ufshcd-release-resources-if-probe-fails.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/cw1200-don-t-leak-memory-if-krealloc-failes.patch b/queue-4.9/cw1200-don-t-leak-memory-if-krealloc-failes.patch
new file mode 100644 (file)
index 0000000..16faa75
--- /dev/null
@@ -0,0 +1,53 @@
+From 9afdd6128c39f42398041bb2e017d8df0dcebcd1 Mon Sep 17 00:00:00 2001
+From: Johannes Thumshirn <jthumshirn@suse.de>
+Date: Fri, 30 Sep 2016 14:39:17 +0200
+Subject: cw1200: Don't leak memory if krealloc failes
+
+From: Johannes Thumshirn <jthumshirn@suse.de>
+
+commit 9afdd6128c39f42398041bb2e017d8df0dcebcd1 upstream.
+
+The call to krealloc() in wsm_buf_reserve() directly assigns the newly
+returned memory to buf->begin. This is all fine except when krealloc()
+failes we loose the ability to free the old memory pointed to by
+buf->begin. If we just create a temporary variable to assign memory to
+and assign the memory to it we can mitigate the memory leak.
+
+Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
+Cc: Johannes Berg <johannes@sipsolutions.net>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/st/cw1200/wsm.c |   16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/st/cw1200/wsm.c
++++ b/drivers/net/wireless/st/cw1200/wsm.c
+@@ -1805,16 +1805,18 @@ static int wsm_buf_reserve(struct wsm_bu
+ {
+       size_t pos = buf->data - buf->begin;
+       size_t size = pos + extra_size;
++      u8 *tmp;
+       size = round_up(size, FWLOAD_BLOCK_SIZE);
+-      buf->begin = krealloc(buf->begin, size, GFP_KERNEL | GFP_DMA);
+-      if (buf->begin) {
+-              buf->data = &buf->begin[pos];
+-              buf->end = &buf->begin[size];
+-              return 0;
+-      } else {
+-              buf->end = buf->data = buf->begin;
++      tmp = krealloc(buf->begin, size, GFP_KERNEL | GFP_DMA);
++      if (!tmp) {
++              wsm_buf_deinit(buf);
+               return -ENOMEM;
+       }
++
++      buf->begin = tmp;
++      buf->data = &buf->begin[pos];
++      buf->end = &buf->begin[size];
++      return 0;
+ }
index 3408988f05d10c35225ac33d4819ead6fbb19849..a7d87b5ef0562039addbb972a84c8ed9416052c9 100644 (file)
@@ -19,11 +19,9 @@ Cc: stable@vger.kernel.org
 Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
 Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- drivers/input/joystick/xpad.c | 3 +++
+ drivers/input/joystick/xpad.c |    3 +++
  1 file changed, 3 insertions(+)
 
-diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
-index 69b44aebaf01..2e52015634f9 100644
 --- a/drivers/input/joystick/xpad.c
 +++ b/drivers/input/joystick/xpad.c
 @@ -234,6 +234,7 @@ static const struct xpad_device {
@@ -34,7 +32,7 @@ index 69b44aebaf01..2e52015634f9 100644
        { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 },
        { 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE },
        { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 },
-@@ -533,6 +534,8 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {
+@@ -533,6 +534,8 @@ static const struct xboxone_init_packet
        XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init2),
        XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init1),
        XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init2),
@@ -43,6 +41,3 @@ index 69b44aebaf01..2e52015634f9 100644
        XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),
        XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init),
        XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init),
--- 
-2.17.1
-
diff --git a/queue-4.9/mwifiex-fix-null-pointer-dereference-in-skb_dequeue.patch b/queue-4.9/mwifiex-fix-null-pointer-dereference-in-skb_dequeue.patch
new file mode 100644 (file)
index 0000000..cbbc4b0
--- /dev/null
@@ -0,0 +1,71 @@
+From c44c040300d7afd79294710313a4989683e2afb1 Mon Sep 17 00:00:00 2001
+From: Amitkumar Karwar <akarwar@marvell.com>
+Date: Wed, 28 Sep 2016 18:18:23 +0530
+Subject: mwifiex: Fix NULL pointer dereference in skb_dequeue()
+
+From: Amitkumar Karwar <akarwar@marvell.com>
+
+commit c44c040300d7afd79294710313a4989683e2afb1 upstream.
+
+At couple of places in cleanup path, we are just going through the
+skb queue and freeing them without unlinking. This leads to a crash
+when other thread tries to do skb_dequeue() and use already freed node.
+
+The problem is freed by unlinking skb before freeing it.
+
+Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/marvell/mwifiex/cfg80211.c |    4 +++-
+ drivers/net/wireless/marvell/mwifiex/wmm.c      |   12 +++++++++---
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
++++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+@@ -3079,8 +3079,10 @@ int mwifiex_del_virtual_intf(struct wiph
+       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+-      skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
++      skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) {
++              skb_unlink(skb, &priv->bypass_txq);
+               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
++      }
+       if (netif_carrier_ok(priv->netdev))
+               netif_carrier_off(priv->netdev);
+--- a/drivers/net/wireless/marvell/mwifiex/wmm.c
++++ b/drivers/net/wireless/marvell/mwifiex/wmm.c
+@@ -503,8 +503,10 @@ mwifiex_wmm_del_pkts_in_ralist_node(stru
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct sk_buff *skb, *tmp;
+-      skb_queue_walk_safe(&ra_list->skb_head, skb, tmp)
++      skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) {
++              skb_unlink(skb, &ra_list->skb_head);
+               mwifiex_write_data_complete(adapter, skb, 0, -1);
++      }
+ }
+ /*
+@@ -600,11 +602,15 @@ mwifiex_clean_txrx(struct mwifiex_privat
+               priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+-      skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
++      skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
++              skb_unlink(skb, &priv->tdls_txq);
+               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
++      }
+-      skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
++      skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) {
++              skb_unlink(skb, &priv->bypass_txq);
+               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
++      }
+       atomic_set(&priv->adapter->bypass_tx_pending, 0);
+       idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
diff --git a/queue-4.9/mwifiex-fix-p2p-device-doesn-t-find-in-scan-problem.patch b/queue-4.9/mwifiex-fix-p2p-device-doesn-t-find-in-scan-problem.patch
new file mode 100644 (file)
index 0000000..66f852f
--- /dev/null
@@ -0,0 +1,41 @@
+From 3d8bd85c2c9e47ed2c82348aa5b6029ed48376ae Mon Sep 17 00:00:00 2001
+From: Karthik D A <karthida@marvell.com>
+Date: Wed, 28 Sep 2016 18:18:28 +0530
+Subject: mwifiex: fix p2p device doesn't find in scan problem
+
+From: Karthik D A <karthida@marvell.com>
+
+commit 3d8bd85c2c9e47ed2c82348aa5b6029ed48376ae upstream.
+
+Marvell p2p device disappears from the list of p2p peers on the other
+p2p device after disconnection.
+
+It happens due to a bug in driver. When interface is changed from p2p
+to station, certain variables(bss_type, bss_role etc.) aren't correctly
+updated. This patch corrects them to fix the issue.
+
+Signed-off-by: Karthik D A <karthida@marvell.com>
+Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/marvell/mwifiex/cfg80211.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
++++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+@@ -1209,6 +1209,12 @@ mwifiex_cfg80211_change_virtual_intf(str
+                       priv->adapter->curr_iface_comb.p2p_intf--;
+                       priv->adapter->curr_iface_comb.sta_intf++;
+                       dev->ieee80211_ptr->iftype = type;
++                      if (mwifiex_deinit_priv_params(priv))
++                              return -1;
++                      if (mwifiex_init_new_priv_params(priv, dev, type))
++                              return -1;
++                      if (mwifiex_sta_init_cmd(priv, false, false))
++                              return -1;
+                       break;
+               case NL80211_IFTYPE_ADHOC:
+                       if (mwifiex_cfg80211_deinit_p2p(priv))
diff --git a/queue-4.9/mwifiex-prevent-register-accesses-after-host-is-sleeping.patch b/queue-4.9/mwifiex-prevent-register-accesses-after-host-is-sleeping.patch
new file mode 100644 (file)
index 0000000..95eb5ff
--- /dev/null
@@ -0,0 +1,91 @@
+From ec815dd2a5f110f627d7955e0027a3a008f68166 Mon Sep 17 00:00:00 2001
+From: Amitkumar Karwar <akarwar@marvell.com>
+Date: Wed, 28 Sep 2016 18:18:21 +0530
+Subject: mwifiex: prevent register accesses after host is sleeping
+
+From: Amitkumar Karwar <akarwar@marvell.com>
+
+commit ec815dd2a5f110f627d7955e0027a3a008f68166 upstream.
+
+Following is mwifiex driver-firmware host sleep handshake.
+It involves three threads. suspend handler, interrupt handler, interrupt
+processing in main work queue.
+
+1) Enter suspend handler
+2) Download HS_CFG command
+3) Response from firmware for HS_CFG
+4) Suspend thread waits until handshake completes(i.e hs_activate becomes
+   true)
+5) SLEEP from firmware
+6) SLEEP confirm downloaded to firmware.
+7) SLEEP confirm response from firmware
+8) Driver processes SLEEP confirm response and set hs_activate to wake up
+suspend thread
+9) Exit suspend handler
+10) Read sleep cookie in loop and wait until it indicates firmware is
+sleep.
+11) After processing SLEEP confirm response, we are at the end of interrupt
+processing routine. Recheck if there are interrupts received while we were
+processing them.
+
+During suspend-resume stress test, it's been observed that we may end up
+acessing PCIe hardware(in 10 and 11) when PCIe bus is closed which leads
+to a kernel crash.
+
+This patch solves the problem with below changes.
+a) action 10 above can be done before 8
+b) Skip 11 if hs_activated is true. SLEEP confirm response
+is the last interrupt from firmware. No need to recheck for
+pending interrupts.
+c) Add flush_workqueue() in suspend handler.
+
+Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
+Reviewed-by: Brian Norris <briannorris@chromium.org>
+Tested-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/marvell/mwifiex/pcie.c |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
++++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
+@@ -118,6 +118,7 @@ static int mwifiex_pcie_suspend(struct d
+       adapter = card->adapter;
+       hs_actived = mwifiex_enable_hs(adapter);
++      flush_workqueue(adapter->workqueue);
+       /* Indicate device suspended */
+       adapter->is_suspended = true;
+@@ -1676,9 +1677,6 @@ static int mwifiex_pcie_process_cmd_comp
+       if (!adapter->curr_cmd) {
+               if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
+-                      mwifiex_process_sleep_confirm_resp(adapter, skb->data,
+-                                                         skb->len);
+-                      mwifiex_pcie_enable_host_int(adapter);
+                       if (mwifiex_write_reg(adapter,
+                                             PCIE_CPU_INT_EVENT,
+                                             CPU_INTR_SLEEP_CFM_DONE)) {
+@@ -1691,6 +1689,9 @@ static int mwifiex_pcie_process_cmd_comp
+                       while (reg->sleep_cookie && (count++ < 10) &&
+                              mwifiex_pcie_ok_to_access_hw(adapter))
+                               usleep_range(50, 60);
++                      mwifiex_pcie_enable_host_int(adapter);
++                      mwifiex_process_sleep_confirm_resp(adapter, skb->data,
++                                                         skb->len);
+               } else {
+                       mwifiex_dbg(adapter, ERROR,
+                                   "There is no command but got cmdrsp\n");
+@@ -2329,6 +2330,8 @@ static int mwifiex_process_pcie_int(stru
+                       ret = mwifiex_pcie_process_cmd_complete(adapter);
+                       if (ret)
+                               return ret;
++                      if (adapter->hs_activated)
++                              return ret;
+               }
+               if (card->msi_enable) {
diff --git a/queue-4.9/mwifiex-report-error-to-pcie-for-suspend-failure.patch b/queue-4.9/mwifiex-report-error-to-pcie-for-suspend-failure.patch
new file mode 100644 (file)
index 0000000..6874330
--- /dev/null
@@ -0,0 +1,51 @@
+From 5190f2e405919cd30ba2f12c58129fb2d71cd6b6 Mon Sep 17 00:00:00 2001
+From: Amitkumar Karwar <akarwar@marvell.com>
+Date: Wed, 28 Sep 2016 18:18:22 +0530
+Subject: mwifiex: report error to PCIe for suspend failure
+
+From: Amitkumar Karwar <akarwar@marvell.com>
+
+commit 5190f2e405919cd30ba2f12c58129fb2d71cd6b6 upstream.
+
+When host_sleep_config command fails, we should return an error to
+PCIe, instead of continuing (and possibly panicking, when we try to keep
+processing a timed-out ioctl after we return "successfully" from
+suspend).
+
+Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
+Reviewed-by: Brian Norris <briannorris@chromium.org>
+Tested-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/marvell/mwifiex/pcie.c |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
++++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
+@@ -101,7 +101,6 @@ static int mwifiex_pcie_suspend(struct d
+ {
+       struct mwifiex_adapter *adapter;
+       struct pcie_service_card *card;
+-      int hs_actived;
+       struct pci_dev *pdev = to_pci_dev(dev);
+       if (pdev) {
+@@ -117,7 +116,14 @@ static int mwifiex_pcie_suspend(struct d
+       adapter = card->adapter;
+-      hs_actived = mwifiex_enable_hs(adapter);
++      /* Enable the Host Sleep */
++      if (!mwifiex_enable_hs(adapter)) {
++              mwifiex_dbg(adapter, ERROR,
++                          "cmd: failed to suspend\n");
++              adapter->hs_enabling = false;
++              return -EFAULT;
++      }
++
+       flush_workqueue(adapter->workqueue);
+       /* Indicate device suspended */
diff --git a/queue-4.9/scsi-ufs-fix-bugs-related-to-null-pointer-access-and-array-size.patch b/queue-4.9/scsi-ufs-fix-bugs-related-to-null-pointer-access-and-array-size.patch
new file mode 100644 (file)
index 0000000..b8e0b11
--- /dev/null
@@ -0,0 +1,101 @@
+From e3ce73d69aff44421d7899b235fec5ac2c306ff4 Mon Sep 17 00:00:00 2001
+From: Yaniv Gardi <ygardi@codeaurora.org>
+Date: Mon, 17 Oct 2016 17:09:24 -0700
+Subject: scsi: ufs: fix bugs related to null pointer access and array size
+
+From: Yaniv Gardi <ygardi@codeaurora.org>
+
+commit e3ce73d69aff44421d7899b235fec5ac2c306ff4 upstream.
+
+In this change there are a few fixes of possible NULL pointer access and
+possible access to index that exceeds array boundaries.
+
+Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
+Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/ufs/ufs.h    |    3 ++-
+ drivers/scsi/ufs/ufshcd.c |   25 +++++++++++++++++++------
+ 2 files changed, 21 insertions(+), 7 deletions(-)
+
+--- a/drivers/scsi/ufs/ufs.h
++++ b/drivers/scsi/ufs/ufs.h
+@@ -46,6 +46,7 @@
+ #define QUERY_DESC_HDR_SIZE       2
+ #define QUERY_OSF_SIZE            (GENERAL_UPIU_REQUEST_SIZE - \
+                                       (sizeof(struct utp_upiu_header)))
++#define RESPONSE_UPIU_SENSE_DATA_LENGTH       18
+ #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
+                       cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
+@@ -410,7 +411,7 @@ struct utp_cmd_rsp {
+       __be32 residual_transfer_count;
+       __be32 reserved[4];
+       __be16 sense_data_len;
+-      u8 sense_data[18];
++      u8 sense_data[RESPONSE_UPIU_SENSE_DATA_LENGTH];
+ };
+ /**
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -901,10 +901,14 @@ static inline void ufshcd_copy_sense_dat
+       int len;
+       if (lrbp->sense_buffer &&
+           ufshcd_get_rsp_upiu_data_seg_len(lrbp->ucd_rsp_ptr)) {
++              int len_to_copy;
++
+               len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len);
++              len_to_copy = min_t(int, RESPONSE_UPIU_SENSE_DATA_LENGTH, len);
++
+               memcpy(lrbp->sense_buffer,
+                       lrbp->ucd_rsp_ptr->sr.sense_data,
+-                      min_t(int, len, SCSI_SENSE_BUFFERSIZE));
++                      min_t(int, len_to_copy, SCSI_SENSE_BUFFERSIZE));
+       }
+ }
+@@ -6373,7 +6377,10 @@ EXPORT_SYMBOL(ufshcd_system_suspend);
+ int ufshcd_system_resume(struct ufs_hba *hba)
+ {
+-      if (!hba || !hba->is_powered || pm_runtime_suspended(hba->dev))
++      if (!hba)
++              return -EINVAL;
++
++      if (!hba->is_powered || pm_runtime_suspended(hba->dev))
+               /*
+                * Let the runtime resume take care of resuming
+                * if runtime suspended.
+@@ -6394,7 +6401,10 @@ EXPORT_SYMBOL(ufshcd_system_resume);
+  */
+ int ufshcd_runtime_suspend(struct ufs_hba *hba)
+ {
+-      if (!hba || !hba->is_powered)
++      if (!hba)
++              return -EINVAL;
++
++      if (!hba->is_powered)
+               return 0;
+       return ufshcd_suspend(hba, UFS_RUNTIME_PM);
+@@ -6424,10 +6434,13 @@ EXPORT_SYMBOL(ufshcd_runtime_suspend);
+  */
+ int ufshcd_runtime_resume(struct ufs_hba *hba)
+ {
+-      if (!hba || !hba->is_powered)
++      if (!hba)
++              return -EINVAL;
++
++      if (!hba->is_powered)
+               return 0;
+-      else
+-              return ufshcd_resume(hba, UFS_RUNTIME_PM);
++
++      return ufshcd_resume(hba, UFS_RUNTIME_PM);
+ }
+ EXPORT_SYMBOL(ufshcd_runtime_resume);
diff --git a/queue-4.9/scsi-ufs-fix-race-between-clock-gating-and-devfreq-scaling-work.patch b/queue-4.9/scsi-ufs-fix-race-between-clock-gating-and-devfreq-scaling-work.patch
new file mode 100644 (file)
index 0000000..f704a59
--- /dev/null
@@ -0,0 +1,138 @@
+From 30fc33f1ef475480dc5bea4fe1bda84b003b992c Mon Sep 17 00:00:00 2001
+From: Subhash Jadavani <subhashj@codeaurora.org>
+Date: Thu, 27 Oct 2016 17:25:47 -0700
+Subject: scsi: ufs: fix race between clock gating and devfreq scaling work
+
+From: Subhash Jadavani <subhashj@codeaurora.org>
+
+commit 30fc33f1ef475480dc5bea4fe1bda84b003b992c upstream.
+
+UFS devfreq clock scaling work may require clocks to be ON if it need to
+execute some UFS commands hence it may request for clock hold before
+issuing the command. But if UFS clock gating work is already running in
+parallel, ungate work would end up waiting for the clock gating work to
+finish and as clock gating work would also wait for the clock scaling
+work to finish, we would enter in deadlock state. Here is the call trace
+during this deadlock state:
+
+Workqueue: devfreq_wq devfreq_monitor
+       __switch_to
+       __schedule
+       schedule
+       schedule_timeout
+       wait_for_common
+       wait_for_completion
+       flush_work
+       ufshcd_hold
+       ufshcd_send_uic_cmd
+       ufshcd_dme_get_attr
+       ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div
+       ufs_qcom_clk_scale_notify
+       ufshcd_scale_clks
+       ufshcd_devfreq_target
+       update_devfreq
+       devfreq_monitor
+       process_one_work
+       worker_thread
+       kthread
+       ret_from_fork
+
+Workqueue: events ufshcd_gate_work
+       __switch_to
+       __schedule
+       schedule
+       schedule_preempt_disabled
+       __mutex_lock_slowpath
+       mutex_lock
+       devfreq_monitor_suspend
+       devfreq_simple_ondemand_handler
+       devfreq_suspend_device
+       ufshcd_gate_work
+       process_one_work
+       worker_thread
+       kthread
+       ret_from_fork
+
+Workqueue: events ufshcd_ungate_work
+       __switch_to
+       __schedule
+       schedule
+       schedule_timeout
+       wait_for_common
+       wait_for_completion
+       flush_work
+       __cancel_work_timer
+       cancel_delayed_work_sync
+       ufshcd_ungate_work
+       process_one_work
+       worker_thread
+       kthread
+       ret_from_fork
+
+This change fixes this deadlock by doing this in devfreq work (devfreq_wq):
+Try cancelling clock gating work. If we are able to cancel gating work
+or it wasn't scheduled, hold the clock reference count until scaling is
+in progress. If gate work is already running in parallel, let's skip
+the frequecy scaling at this time and it will be retried once next scaling
+window expires.
+
+Reviewed-by: Sahitya Tummala <stummala@codeaurora.org>
+Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/ufs/ufshcd.c |   32 ++++++++++++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -6633,15 +6633,47 @@ static int ufshcd_devfreq_target(struct
+ {
+       int err = 0;
+       struct ufs_hba *hba = dev_get_drvdata(dev);
++      bool release_clk_hold = false;
++      unsigned long irq_flags;
+       if (!ufshcd_is_clkscaling_enabled(hba))
+               return -EINVAL;
++      spin_lock_irqsave(hba->host->host_lock, irq_flags);
++      if (ufshcd_eh_in_progress(hba)) {
++              spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
++              return 0;
++      }
++
++      if (ufshcd_is_clkgating_allowed(hba) &&
++          (hba->clk_gating.state != CLKS_ON)) {
++              if (cancel_delayed_work(&hba->clk_gating.gate_work)) {
++                      /* hold the vote until the scaling work is completed */
++                      hba->clk_gating.active_reqs++;
++                      release_clk_hold = true;
++                      hba->clk_gating.state = CLKS_ON;
++              } else {
++                      /*
++                       * Clock gating work seems to be running in parallel
++                       * hence skip scaling work to avoid deadlock between
++                       * current scaling work and gating work.
++                       */
++                      spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
++                      return 0;
++              }
++      }
++      spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
++
+       if (*freq == UINT_MAX)
+               err = ufshcd_scale_clks(hba, true);
+       else if (*freq == 0)
+               err = ufshcd_scale_clks(hba, false);
++      spin_lock_irqsave(hba->host->host_lock, irq_flags);
++      if (release_clk_hold)
++              __ufshcd_release(hba);
++      spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
++
+       return err;
+ }
diff --git a/queue-4.9/scsi-ufshcd-fix-race-between-clk-scaling-and-ungate-work.patch b/queue-4.9/scsi-ufshcd-fix-race-between-clk-scaling-and-ungate-work.patch
new file mode 100644 (file)
index 0000000..8136123
--- /dev/null
@@ -0,0 +1,70 @@
+From f2a785ac23125fa0774327d39e837e45cf28fe92 Mon Sep 17 00:00:00 2001
+From: Venkat Gopalakrishnan <venkatg@codeaurora.org>
+Date: Mon, 17 Oct 2016 17:10:53 -0700
+Subject: scsi: ufshcd: Fix race between clk scaling and ungate work
+
+From: Venkat Gopalakrishnan <venkatg@codeaurora.org>
+
+commit f2a785ac23125fa0774327d39e837e45cf28fe92 upstream.
+
+The ungate work turns on the clock before it exits hibern8, if the link
+was put in hibern8 during clock gating work.  There occurs a race
+condition when clock scaling work calls ufshcd_hold() to make sure low
+power states cannot be entered, but that returns by checking only
+whether the clocks are on.  This causes the clock scaling work to issue
+UIC commands when the link is in hibern8 causing failures. Make sure we
+exit hibern8 state before returning from ufshcd_hold().
+
+Callstacks for race condition:
+
+ ufshcd_scale_gear
+ ufshcd_devfreq_scale
+ ufshcd_devfreq_target
+ update_devfreq
+ devfreq_monitor
+ process_one_work
+ worker_thread
+ kthread
+ ret_from_fork
+
+ ufshcd_uic_hibern8_exit
+ ufshcd_ungate_work
+ process_one_work
+ worker_thread
+ kthread
+ ret_from_fork
+
+Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
+Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/ufs/ufshcd.c |   15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -672,6 +672,21 @@ int ufshcd_hold(struct ufs_hba *hba, boo
+ start:
+       switch (hba->clk_gating.state) {
+       case CLKS_ON:
++              /*
++               * Wait for the ungate work to complete if in progress.
++               * Though the clocks may be in ON state, the link could
++               * still be in hibner8 state if hibern8 is allowed
++               * during clock gating.
++               * Make sure we exit hibern8 state also in addition to
++               * clocks being ON.
++               */
++              if (ufshcd_can_hibern8_during_gating(hba) &&
++                  ufshcd_is_link_hibern8(hba)) {
++                      spin_unlock_irqrestore(hba->host->host_lock, flags);
++                      flush_work(&hba->clk_gating.ungate_work);
++                      spin_lock_irqsave(hba->host->host_lock, flags);
++                      goto start;
++              }
+               break;
+       case REQ_CLKS_OFF:
+               if (cancel_delayed_work(&hba->clk_gating.gate_work)) {
diff --git a/queue-4.9/scsi-ufshcd-release-resources-if-probe-fails.patch b/queue-4.9/scsi-ufshcd-release-resources-if-probe-fails.patch
new file mode 100644 (file)
index 0000000..2facbb3
--- /dev/null
@@ -0,0 +1,85 @@
+From afa3dfd42d205b106787476647735aa1de1a5d02 Mon Sep 17 00:00:00 2001
+From: Subhash Jadavani <subhashj@codeaurora.org>
+Date: Thu, 27 Oct 2016 17:25:58 -0700
+Subject: scsi: ufshcd: release resources if probe fails
+
+From: Subhash Jadavani <subhashj@codeaurora.org>
+
+commit afa3dfd42d205b106787476647735aa1de1a5d02 upstream.
+
+If ufshcd pltfrm/pci driver's probe fails for some reason then ensure
+that scsi host is released to avoid memory leak but managed memory
+allocations (via devm_* calls) need not to be freed explicitly on probe
+failure as memory allocated with these functions is automatically freed
+on driver detach.
+
+Reviewed-by: Sahitya Tummala <stummala@codeaurora.org>
+Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/ufs/ufshcd-pci.c    |    2 ++
+ drivers/scsi/ufs/ufshcd-pltfrm.c |    5 +----
+ drivers/scsi/ufs/ufshcd.c        |    3 ---
+ 3 files changed, 3 insertions(+), 7 deletions(-)
+
+--- a/drivers/scsi/ufs/ufshcd-pci.c
++++ b/drivers/scsi/ufs/ufshcd-pci.c
+@@ -104,6 +104,7 @@ static void ufshcd_pci_remove(struct pci
+       pm_runtime_forbid(&pdev->dev);
+       pm_runtime_get_noresume(&pdev->dev);
+       ufshcd_remove(hba);
++      ufshcd_dealloc_host(hba);
+ }
+ /**
+@@ -147,6 +148,7 @@ ufshcd_pci_probe(struct pci_dev *pdev, c
+       err = ufshcd_init(hba, mmio_base, pdev->irq);
+       if (err) {
+               dev_err(&pdev->dev, "Initialization failed\n");
++              ufshcd_dealloc_host(hba);
+               return err;
+       }
+--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
++++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
+@@ -163,7 +163,7 @@ static int ufshcd_populate_vreg(struct d
+       if (ret) {
+               dev_err(dev, "%s: unable to find %s err %d\n",
+                               __func__, prop_name, ret);
+-              goto out_free;
++              goto out;
+       }
+       vreg->min_uA = 0;
+@@ -185,9 +185,6 @@ static int ufshcd_populate_vreg(struct d
+       goto out;
+-out_free:
+-      devm_kfree(dev, vreg);
+-      vreg = NULL;
+ out:
+       if (!ret)
+               *out_vreg = vreg;
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -6507,8 +6507,6 @@ void ufshcd_remove(struct ufs_hba *hba)
+       ufshcd_disable_intr(hba, hba->intr_mask);
+       ufshcd_hba_stop(hba, true);
+-      scsi_host_put(hba->host);
+-
+       ufshcd_exit_clk_gating(hba);
+       if (ufshcd_is_clkscaling_enabled(hba))
+               devfreq_remove_device(hba->devfreq);
+@@ -6876,7 +6874,6 @@ exit_gating:
+       ufshcd_exit_clk_gating(hba);
+ out_disable:
+       hba->is_irq_enabled = false;
+-      scsi_host_put(host);
+       ufshcd_hba_exit(hba);
+ out_error:
+       return err;
index c115e4d06f3d6c1028d088109113fe988509f4ee..842095cf13253c469f3b963b5c9e6072976208e0 100644 (file)
@@ -67,3 +67,12 @@ input-xpad-avoid-using-__set_bit-for-capabilities.patch
 input-xpad-add-gpd-win-2-controller-usb-ids.patch
 input-xpad-fix-gpd-win-2-controller-name.patch
 input-xpad-add-support-for-xbox1-pdp-camo-series-gam.patch
+cw1200-don-t-leak-memory-if-krealloc-failes.patch
+mwifiex-prevent-register-accesses-after-host-is-sleeping.patch
+mwifiex-report-error-to-pcie-for-suspend-failure.patch
+mwifiex-fix-null-pointer-dereference-in-skb_dequeue.patch
+mwifiex-fix-p2p-device-doesn-t-find-in-scan-problem.patch
+scsi-ufs-fix-bugs-related-to-null-pointer-access-and-array-size.patch
+scsi-ufshcd-fix-race-between-clk-scaling-and-ungate-work.patch
+scsi-ufs-fix-race-between-clock-gating-and-devfreq-scaling-work.patch
+scsi-ufshcd-release-resources-if-probe-fails.patch