From: Greg Kroah-Hartman Date: Thu, 29 Nov 2018 10:13:18 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.19.6~29 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8c1bc6b0193e2d9c07eb8c24f40e3ad0fa966d07;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches 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 --- 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 index 00000000000..16faa759d5e --- /dev/null +++ b/queue-4.9/cw1200-don-t-leak-memory-if-krealloc-failes.patch @@ -0,0 +1,53 @@ +From 9afdd6128c39f42398041bb2e017d8df0dcebcd1 Mon Sep 17 00:00:00 2001 +From: Johannes Thumshirn +Date: Fri, 30 Sep 2016 14:39:17 +0200 +Subject: cw1200: Don't leak memory if krealloc failes + +From: Johannes Thumshirn + +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 +Cc: Johannes Berg +Signed-off-by: Kalle Valo +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } diff --git a/queue-4.9/input-xpad-add-support-for-xbox1-pdp-camo-series-gam.patch b/queue-4.9/input-xpad-add-support-for-xbox1-pdp-camo-series-gam.patch index 3408988f05d..a7d87b5ef05 100644 --- a/queue-4.9/input-xpad-add-support-for-xbox1-pdp-camo-series-gam.patch +++ b/queue-4.9/input-xpad-add-support-for-xbox1-pdp-camo-series-gam.patch @@ -19,11 +19,9 @@ Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov Signed-off-by: Sasha Levin --- - 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 index 00000000000..cbbc4b0c062 --- /dev/null +++ b/queue-4.9/mwifiex-fix-null-pointer-dereference-in-skb_dequeue.patch @@ -0,0 +1,71 @@ +From c44c040300d7afd79294710313a4989683e2afb1 Mon Sep 17 00:00:00 2001 +From: Amitkumar Karwar +Date: Wed, 28 Sep 2016 18:18:23 +0530 +Subject: mwifiex: Fix NULL pointer dereference in skb_dequeue() + +From: Amitkumar Karwar + +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 +Signed-off-by: Kalle Valo +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..66f852fd1da --- /dev/null +++ b/queue-4.9/mwifiex-fix-p2p-device-doesn-t-find-in-scan-problem.patch @@ -0,0 +1,41 @@ +From 3d8bd85c2c9e47ed2c82348aa5b6029ed48376ae Mon Sep 17 00:00:00 2001 +From: Karthik D A +Date: Wed, 28 Sep 2016 18:18:28 +0530 +Subject: mwifiex: fix p2p device doesn't find in scan problem + +From: Karthik D A + +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 +Signed-off-by: Amitkumar Karwar +Signed-off-by: Kalle Valo +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..95eb5ffdf63 --- /dev/null +++ b/queue-4.9/mwifiex-prevent-register-accesses-after-host-is-sleeping.patch @@ -0,0 +1,91 @@ +From ec815dd2a5f110f627d7955e0027a3a008f68166 Mon Sep 17 00:00:00 2001 +From: Amitkumar Karwar +Date: Wed, 28 Sep 2016 18:18:21 +0530 +Subject: mwifiex: prevent register accesses after host is sleeping + +From: Amitkumar Karwar + +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 +Reviewed-by: Brian Norris +Tested-by: Brian Norris +Signed-off-by: Kalle Valo +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..6874330f5df --- /dev/null +++ b/queue-4.9/mwifiex-report-error-to-pcie-for-suspend-failure.patch @@ -0,0 +1,51 @@ +From 5190f2e405919cd30ba2f12c58129fb2d71cd6b6 Mon Sep 17 00:00:00 2001 +From: Amitkumar Karwar +Date: Wed, 28 Sep 2016 18:18:22 +0530 +Subject: mwifiex: report error to PCIe for suspend failure + +From: Amitkumar Karwar + +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 +Reviewed-by: Brian Norris +Tested-by: Brian Norris +Signed-off-by: Kalle Valo +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..b8e0b11c172 --- /dev/null +++ b/queue-4.9/scsi-ufs-fix-bugs-related-to-null-pointer-access-and-array-size.patch @@ -0,0 +1,101 @@ +From e3ce73d69aff44421d7899b235fec5ac2c306ff4 Mon Sep 17 00:00:00 2001 +From: Yaniv Gardi +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 + +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 +Signed-off-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..f704a59ad25 --- /dev/null +++ b/queue-4.9/scsi-ufs-fix-race-between-clock-gating-and-devfreq-scaling-work.patch @@ -0,0 +1,138 @@ +From 30fc33f1ef475480dc5bea4fe1bda84b003b992c Mon Sep 17 00:00:00 2001 +From: Subhash Jadavani +Date: Thu, 27 Oct 2016 17:25:47 -0700 +Subject: scsi: ufs: fix race between clock gating and devfreq scaling work + +From: Subhash Jadavani + +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 +Signed-off-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..81361232932 --- /dev/null +++ b/queue-4.9/scsi-ufshcd-fix-race-between-clk-scaling-and-ungate-work.patch @@ -0,0 +1,70 @@ +From f2a785ac23125fa0774327d39e837e45cf28fe92 Mon Sep 17 00:00:00 2001 +From: Venkat Gopalakrishnan +Date: Mon, 17 Oct 2016 17:10:53 -0700 +Subject: scsi: ufshcd: Fix race between clk scaling and ungate work + +From: Venkat Gopalakrishnan + +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 +Signed-off-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..2facbb3dd2c --- /dev/null +++ b/queue-4.9/scsi-ufshcd-release-resources-if-probe-fails.patch @@ -0,0 +1,85 @@ +From afa3dfd42d205b106787476647735aa1de1a5d02 Mon Sep 17 00:00:00 2001 +From: Subhash Jadavani +Date: Thu, 27 Oct 2016 17:25:58 -0700 +Subject: scsi: ufshcd: release resources if probe fails + +From: Subhash Jadavani + +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 +Signed-off-by: Subhash Jadavani +Signed-off-by: Martin K. Petersen +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.9/series b/queue-4.9/series index c115e4d06f3..842095cf132 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -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